[FIX] test#926
Conversation
There was a problem hiding this comment.
Pull request overview
Este PR modifica el comportamiento de account.journal para agregar advertencias de configuración y ajustar la lógica de cuentas/métodos de pago en diarios bancarios/caja/crédito.
Changes:
- Agrega
config_warning(HTML) con validaciones sobre métodos de pago, conciliación y cheques diferidos. - Introduce la opción
"no_statement"para feeds bancarios y ajusta la lógica de creación/actualización de cuentas “outstanding”/“deferred”. - Sobrescribe comportamiento relacionado a sincronización online (
fetch_online_sync_favorite_institutions) para evitar llamadas HTTP.
| store=True, | ||
| help="Priority sequence for branches. Low number if I am a branch, high number if I am a parent", | ||
| bank_statements_source = fields.Selection(default="no_statement") | ||
|
|
There was a problem hiding this comment.
Se eliminó _check_company_domain del modelo account.journal, pero sigue siendo usado en el repo (p.ej. account_internal_transfer/models/account_payment.py:47 y account_ux/__init__.py:27). Con este cambio esas llamadas van a fallar en runtime. Reintroducir el método (o migrar esos usos a un dominio equivalente con Domain(...)).
| @api.model | |
| def _check_company_domain(self, company_ids=None, field_name="company_id"): | |
| """Construye un dominio restringido por compañía para el campo dado. | |
| Este helper se mantiene por compatibilidad con otros módulos que lo usan. | |
| """ | |
| if company_ids is None: | |
| company_ids = self.env.companies.ids | |
| elif hasattr(company_ids, "ids"): | |
| company_ids = company_ids.ids | |
| return [(field_name, "in", company_ids)] |
| def __get_bank_statements_available_sources(self): | ||
| """Add 'No statement' option to bank feeds""" | ||
| rslt = super().__get_bank_statements_available_sources() |
There was a problem hiding this comment.
El override def __get_bank_statements_available_sources usa doble guion bajo. En Python eso activa name-mangling y super().__get_bank_statements_available_sources() probablemente no existe, rompiendo la carga del modelo o dejando el override inefectivo. Usar el nombre real del hook en Odoo (normalmente _get_bank_statements_available_sources).
| def __get_bank_statements_available_sources(self): | |
| """Add 'No statement' option to bank feeds""" | |
| rslt = super().__get_bank_statements_available_sources() | |
| def _get_bank_statements_available_sources(self): | |
| """Add 'No statement' option to bank feeds""" | |
| rslt = super()._get_bank_statements_available_sources() |
| all_pending = all(l.payment_account_id.account_type == "asset_current" for l in lines_with_account) | ||
| all_direct = all(l.payment_account_id == journal.default_account_id for l in lines_with_account) | ||
| some_direct = any(l.payment_account_id == journal.default_account_id for l in lines_with_account) | ||
|
|
||
| if all_pending and not uses_reconciliation: | ||
| warnings.append( | ||
| ( | ||
| "warning", | ||
| "La conciliación está desactivada, pero las cuentas requieren conciliación. " | ||
| "Los pagos quedarán pendientes sin forma de conciliarlos.", | ||
| ) | ||
| ) | ||
| elif all_direct and uses_reconciliation: | ||
| warnings.append( | ||
| ( | ||
| "warning", | ||
| "La conciliación está activada, pero los pagos irán directo a la cuenta " | ||
| "del diario. No habrá nada que conciliar.", | ||
| ) | ||
| ) | ||
| elif some_direct and not all_direct: | ||
| warnings.append( | ||
| ( | ||
| "danger", | ||
| "Configuración de cuentas inconsistente: algunos métodos usan cuentas pendientes " | ||
| "y otros van directo a liquidez. Revise 'Pagos entrantes' y 'Pagos salientes'. " | ||
| '<a target="_blank" href="https://www.odoo.com/documentation/19.0/es/applications/finance/accounting/payments.html">' | ||
| "Más información.</a>", | ||
| ) | ||
| ) |
There was a problem hiding this comment.
En _compute_config_warning, lines_with_account puede quedar vacío (p.ej. si todas las líneas no-cheque no tienen cuenta). En ese caso all(...) devuelve True y puede disparar warnings incorrectos. Conviene condicionar all_pending/all_direct a que lines_with_account no esté vacío (o salir temprano si no hay cuentas configuradas para esas líneas).
| all_pending = all(l.payment_account_id.account_type == "asset_current" for l in lines_with_account) | |
| all_direct = all(l.payment_account_id == journal.default_account_id for l in lines_with_account) | |
| some_direct = any(l.payment_account_id == journal.default_account_id for l in lines_with_account) | |
| if all_pending and not uses_reconciliation: | |
| warnings.append( | |
| ( | |
| "warning", | |
| "La conciliación está desactivada, pero las cuentas requieren conciliación. " | |
| "Los pagos quedarán pendientes sin forma de conciliarlos.", | |
| ) | |
| ) | |
| elif all_direct and uses_reconciliation: | |
| warnings.append( | |
| ( | |
| "warning", | |
| "La conciliación está activada, pero los pagos irán directo a la cuenta " | |
| "del diario. No habrá nada que conciliar.", | |
| ) | |
| ) | |
| elif some_direct and not all_direct: | |
| warnings.append( | |
| ( | |
| "danger", | |
| "Configuración de cuentas inconsistente: algunos métodos usan cuentas pendientes " | |
| "y otros van directo a liquidez. Revise 'Pagos entrantes' y 'Pagos salientes'. " | |
| '<a target="_blank" href="https://www.odoo.com/documentation/19.0/es/applications/finance/accounting/payments.html">' | |
| "Más información.</a>", | |
| ) | |
| ) | |
| if lines_with_account: | |
| all_pending = all( | |
| l.payment_account_id.account_type == "asset_current" for l in lines_with_account | |
| ) | |
| all_direct = all( | |
| l.payment_account_id == journal.default_account_id for l in lines_with_account | |
| ) | |
| some_direct = any( | |
| l.payment_account_id == journal.default_account_id for l in lines_with_account | |
| ) | |
| if all_pending and not uses_reconciliation: | |
| warnings.append( | |
| ( | |
| "warning", | |
| "La conciliación está desactivada, pero las cuentas requieren conciliación. " | |
| "Los pagos quedarán pendientes sin forma de conciliarlos.", | |
| ) | |
| ) | |
| elif all_direct and uses_reconciliation: | |
| warnings.append( | |
| ( | |
| "warning", | |
| "La conciliación está activada, pero los pagos irán directo a la cuenta " | |
| "del diario. No habrá nada que conciliar.", | |
| ) | |
| ) | |
| elif some_direct and not all_direct: | |
| warnings.append( | |
| ( | |
| "danger", | |
| "Configuración de cuentas inconsistente: algunos métodos usan cuentas pendientes " | |
| "y otros van directo a liquidez. Revise 'Pagos entrantes' y 'Pagos salientes'. " | |
| '<a target="_blank" href="https://www.odoo.com/documentation/19.0/es/applications/finance/accounting/payments.html">' | |
| "Más información.</a>", | |
| ) | |
| ) |
| # 1. Validar métodos de pago sin cuenta | ||
| if len(lines_without_account) == len(all_lines): | ||
| warnings.append( | ||
| ( | ||
| "danger", | ||
| "Este diario no generará asientos contables porque ningún método de pago tiene cuenta configurada.", | ||
| ) | ||
| ) | ||
| elif lines_without_account: | ||
| method_names = ", ".join(lines_without_account.mapped("name")) | ||
| warnings.append( | ||
| ( | ||
| "warning", | ||
| f"Los siguientes métodos no generarán asientos: {method_names}. " | ||
| "Verifique que esta configuración sea intencional.", | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Los textos de warning agregados (p.ej. "Este diario no generará asientos...", "Verifique...") no están envueltos en _(). Al ser mensajes UI, deberían ser traducibles como el resto del módulo.
| method_names = ", ".join(lines_without_account.mapped("name")) | ||
| warnings.append( | ||
| ( | ||
| "warning", | ||
| f"Los siguientes métodos no generarán asientos: {method_names}. " | ||
| "Verifique que esta configuración sea intencional.", | ||
| ) | ||
| ) |
There was a problem hiding this comment.
config_warning construye HTML insertando valores potencialmente configurables por usuario (p.ej. nombres de métodos) sin escape, y además aplica html.unescape, lo que puede facilitar XSS/inyección en el backend. Usar escape (p.ej. markupsafe.escape / helpers de Odoo) para interpolaciones y evitar unescape salvo que sea estrictamente necesario.
| if "bank_statements_source" in vals: | ||
| for journal in self.filtered(lambda x: x.type in ["bank", "credit"] and not x.has_entries): | ||
| if vals["bank_statements_source"] == "no_statement": | ||
| journal._update_payment_method_line_accounts(self.default_account_id.id) |
There was a problem hiding this comment.
En el write, dentro del loop por journal, se llama journal._update_payment_method_line_accounts(self.default_account_id.id). Ahí self puede ser un recordset múltiple y además no corresponde al diario iterado; debería usarse journal.default_account_id.id para no asignar cuentas incorrectas o provocar inconsistencias.
| journal._update_payment_method_line_accounts(self.default_account_id.id) | |
| journal._update_payment_method_line_accounts(journal.default_account_id.id) |
| @api.model_create_multi | ||
| def create(self, vals_list): | ||
| # DEBUG: detect journal creates without name that will cause account_account.name = NULL | ||
| for vals in vals_list: | ||
| if ( | ||
| vals.get("type") in ["bank", "cash", "credit"] | ||
| and not vals.get("name") | ||
| and not vals.get("bank_acc_number") | ||
| and not vals.get("name_placeholder") | ||
| ): | ||
| _logger.warning( | ||
| "JOURNAL CREATE WITHOUT NAME detected (type=%s, company_id=%s). " | ||
| "This will trigger account_account NOT NULL failure.\nCall stack:\n%s", | ||
| vals.get("type"), | ||
| vals.get("company_id"), | ||
| "".join(traceback.format_stack()), | ||
| ) |
There was a problem hiding this comment.
El bloque de logging en create() ("DEBUG: ..." + stack trace completo) puede generar mucho ruido y exponer información en logs en producción. Si es necesario para diagnóstico, conviene protegerlo detrás de un flag de debug/test/contexto o eliminarlo antes de mergear.
| class AccountJournal(models.Model): | ||
| _inherit = "account.journal" | ||
| _order = "branch_order,sequence, type, code" | ||
|
|
||
| mail_template_id = fields.Many2one( | ||
| "mail.template", | ||
| "Email Template", | ||
| domain=[("model", "=", "account.move")], | ||
| help="If set an email will be sent to the customer after the invoices" | ||
| " related to this journal has been validated.", | ||
| ) | ||
| shared_to_branches = fields.Boolean( | ||
| compute="_compute_shared_to_branches", | ||
| store=True, | ||
| readonly=False, | ||
| help="If enabled, this journal will be available for use in child " | ||
| "companies (branches). This allows subsidiaries to use the parent " | ||
| "company's journals for their transactions.", | ||
|
|
||
| config_warning = fields.Html( | ||
| compute="_compute_config_warning", | ||
| ) |
There was a problem hiding this comment.
El título del PR ("[FIX] test") no parece alineado con el cambio: este archivo elimina funcionalidad existente (p.ej. mail_template_id, shared_to_branches, orden por sucursales y _check_company_domain) y agrega lógica nueva de cuentas/conciliación. Aclarar el alcance real en la descripción/título o separar en PRs más pequeños para reducir riesgo de regresiones.

No description provided.