Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .copier-answers.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Do NOT update manually; changes here will be overwritten by Copier
_commit: 2f2f7c4
_commit: a740779
_src_path: https://github.com/ingadhoc/addons-repo-template.git
description: ''
is_private: false
Expand Down
25 changes: 6 additions & 19 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@

* Confirmar que todos los archivos usados (vistas, seguridad, datos, reportes, wizards) estén referenciados en el manifest.
* Verificar dependencias declaradas: que no falten módulos requeridos ni se declaren innecesarios.
* **Regla de versión (obligatoria):**
Solo sugerir bump de versión si el `__manifest__.py` no incrementa `version` y se modificó la estructura de un modelo, una vista, o algún record .xml (ej. cambios en definición de campos, vistas XML, datos XML, seguridad).
* Solo hacerlo una vez por revisión, aunque haya múltiples archivos afectados.

---
Expand All @@ -61,7 +59,6 @@

* Verificar los archivos `ir.model.access.csv` para nuevos modelos: deben tener permisos mínimos necesarios.
* No proponer abrir acceso global sin justificación.
* Si se agregan nuevos modelos o campos de control de acceso, **recordar el bump de versión** (ver sección de manifest).
* Si se cambian `record rules`, revisar especialmente combinaciones multi-compañía y multi-website.

### Seguridad y rendimiento del ORM
Expand All @@ -86,7 +83,7 @@

## Cambios estructurales y scripts de migración – **cuestiones generales**

Cuando el diff sugiera **cambios de estructura de datos**, **siempre evaluar** si corresponde proponer un **script de migración** en `migrations/` (pre/post/end) **y recordar el bump de versión**.
Cuando el diff sugiera **cambios de estructura de datos**, **siempre evaluar** si corresponde proponer un **script de migración** en `migrations/` (pre/post/end).

### Reglas generales de estructura de `migrations/`

Expand Down Expand Up @@ -283,31 +280,21 @@ def migrate(cr, registry):
| ------------------ | -------------------------------------------------------------------------------------------------------- |
| Modelos | Relaciones válidas; constraints; uso adecuado de `@api.depends`; `super()` correcto |
| Vistas XML | Herencias correctas; campos válidos; adaptación a cambios de versión (p.ej. `<list>` vs `<tree>`) |
| Manifest | **Bump de versión obligatorio** si hay cambios estructurales en modelos/vistas/records .xml; archivos referenciados |
| Seguridad | Accesos mínimos necesarios; reglas revisadas |
| Migraciones | **Si hay cambios estructurales, sugerir script en `migrations/` (pre/post/end)** y describir qué hace |
| Rendimiento / ORM | Evitar loops costosos; no SQL innecesario; aprovechar las optimizaciones del ORM de la versión |
| Ortografía & typos | Errores evidentes corregibles sin modificar idioma ni estilo |

---

## Heurística práctica para el bump de versión (general)

* **SI** el diff modifica la estructura de un modelo, una vista, o algún record .xml (ej. cambios en definición de campos, vistas XML, datos XML, seguridad)
**Y** `__manifest__.py` no cambia `version` → **Sugerir bump**.
* **SI** hay scripts `migrations/pre_*.py` o `migrations/post_*.py` nuevos → **Sugerir al menos minor bump**.
* **SI** hay cambios que rompen compatibilidad (renombres, cambios de tipo con impacto, limpieza masiva de datos) → **Sugerir minor/major** según impacto.

---

## Estilo del feedback (general)

* Ser breve, claro y útil. Ejemplos:

* “El campo `partner_id` no se encuentra referenciado en la vista.”
* “Este método redefine `write()` sin usar `super()`.”
* “Tip: hay un error ortográfico en el nombre del parámetro.”
* **Bump + migración:** “Se renombra `old_ref` → `new_ref`: falta **bump de versión** y **pre-script** en `migrations/` para copiar valores antes del upgrade; añadir **post-script** para recompute del stored.”
* **Migración:** “Se renombra `old_ref` → `new_ref`: falta **pre-script** en `migrations/` para copiar valores antes del upgrade; añadir **post-script** para recompute del stored.”

* Evitar explicaciones largas o reescrituras completas salvo que el cambio sea claro y necesario.
* Priorizar comentarios en forma de **lista corta de puntos** (3–7 ítems) y frases breves en lugar de bloques de texto extensos.
Expand All @@ -316,10 +303,10 @@ def migrate(cr, registry):

## Resumen operativo para Copilot

1. **Detecta cambios estructurales en modelos, vistas o records .xml → exige bump de `version` en `__manifest__.py` si no está incrementada.**
2. **Si hay cambio estructural (según la lista actualizada) → propone y describe script(s) de migración en `migrations/` (pre/post/end)**, con enfoque idempotente y en lotes.
3. Distingue entre:
1. **Si hay cambio estructural (según la lista actualizada) → propone y describe script(s) de migración en `migrations/` (pre/post/end)**, con enfoque idempotente y en lotes.
2. Distingue entre:

* **cuestiones generales** (válidas para cualquier versión),
* y **matices específicos de Odoo 18** (por ejemplo, uso de `<list>`, passkeys, tours y comportamiento del framework).
4. Mantén el feedback **concreto, breve y accionable**.

3. Mantén el feedback **concreto, breve y accionable**.
7 changes: 6 additions & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ name: pre-commit

on:
push:
branches: "[0-9][0-9].0"
branches:
- "1[8-9].0"
- "[2-9][0-9].0"
pull_request_target:
branches:
- "1[8-9].0*"
- "[2-9][0-9].0*"

jobs:
pre-commit:
Expand Down
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ repos:
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-merge-conflict
args: ['--assume-in-merge']
exclude: '\.rst$'
- id: check-symlinks
- id: check-xml
- id: check-yaml
Expand Down
81 changes: 81 additions & 0 deletions account_reconcile_bg/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Account Reconcile Background
============================

This module enables background processing for bank reconciliation operations when dealing with large payment batches, preventing timeouts and improving user experience.

**Table of contents**

.. contents::
:local:

Overview
========

When reconciling large payment batches (e.g., multiple payments included in a single batch) with a bank statement line, the operation can take a long time and may cause timeouts. This module solves this problem by automatically processing large reconciliations in the background, allowing users to continue working while the reconciliation completes.

Features
========

* **Automatic Background Processing**: Large reconciliations are automatically sent to background processing
* **Configurable Threshold**: System parameter to control when background processing kicks in (default: 50 lines)
* **User Notifications**: Users receive notifications when background reconciliation completes
* **No UI Blocking**: Users can continue reconciling other transactions while large batches process
* **Seamless Integration**: Works transparently with existing bank reconciliation workflow

How It Works
============

The module monitors the number of lines being reconciled in the bank reconciliation widget:

1. When validating a reconciliation, it counts the number of source lines
2. If the count is **below the threshold** (default 50), the reconciliation proceeds normally (synchronous)
3. If the count is **above the threshold**, the reconciliation is enqueued as a background job
4. The user receives an immediate success notification and can continue working
5. When the background job completes, the user is notified via internal message

Configuration
=============

The threshold for background processing can be configured via system parameters:

* Navigate to **Settings > Technical > Parameters > System Parameters**
* Find or create the parameter ``account_reconcile_bg.lines_threshold``
* Default value: ``50``
* Set to a higher value to process larger reconciliations synchronously
* Set to a lower value to send more reconciliations to background

Technical Details
=================

Dependencies
------------

* ``account_accountant``: Odoo Enterprise accounting module with bank reconciliation
* ``base_bg``: Background job processing system

Model Inheritance
-----------------

The module inherits from ``bank.rec.widget`` and overrides:

* ``_js_action_validate()``: Detects large reconciliations and routes to background
* ``_validate_in_background()``: Enqueues the job using base_bg
* ``_do_validate()``: Executes the actual validation in background

Credits
=======

Authors
-------

* ADHOC SA

Contributors
------------

* ADHOC SA

Maintainers
-----------

This module is maintained by ADHOC SA.
2 changes: 2 additions & 0 deletions account_reconcile_bg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models
37 changes: 37 additions & 0 deletions account_reconcile_bg/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
##############################################################################
#
# Copyright (C) 2026 ADHOC SA (http://www.adhoc.com.ar)
# All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name": "Account Reconcile Background",
"version": "18.0.1.0.0",
"category": "Accounting",
"author": "ADHOC SA",
"website": "https://www.adhoc.com.ar",
"license": "AGPL-3",
"summary": "Process bank reconciliation in background for large payment batches",
"depends": [
"account_accountant",
"base_bg",
],
"data": [
"data/ir_config_parameter_data.xml",
],
"installable": True,
"auto_install": False,
}
10 changes: 10 additions & 0 deletions account_reconcile_bg/data/ir_config_parameter_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>

<!-- Parámetro de configuración para el umbral de líneas -->
<record id="config_lines_threshold" model="ir.config_parameter">
<field name="key">account_reconcile_bg.lines_threshold</field>
<field name="value">100</field>
</record>

</odoo>
5 changes: 5 additions & 0 deletions account_reconcile_bg/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import bank_rec_widget
from . import account_bank_statement_line
from . import account_move_line
from . import bg_job
84 changes: 84 additions & 0 deletions account_reconcile_bg/models/account_bank_statement_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
import logging

from markupsafe import Markup
from odoo import _, api, fields, models
from odoo.exceptions import UserError


class AccountBankStatementLine(models.Model):
_inherit = "account.bank.statement.line"

reconciliation_in_background = fields.Boolean(
string="Reconciliation in Background",
default=False,
readonly=True,
help="Indicates that this line is being reconciled in background",
)

def _bg_validate_reconciliation(self, selected_aml_ids=None):
"""
Método ejecutado en background para validar la conciliación.
Se llama desde el job de base_bg.

:param selected_aml_ids: IDs de las líneas seleccionadas por el usuario
"""
self.ensure_one()
_logger = logging.getLogger(__name__)

# Preparar datos para mensaje
base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url")
st_line_url = f"{base_url}/odoo/account.bank.statement.line/{self.id}"
st_line_name = self.name or f"Line {self.id}"

try:
# Crear el widget de conciliación
wizard = self.env["bank.rec.widget"].with_context(default_st_line_id=self.id).new({})

_logger.info(f"[BG] Wizard created for st_line {self.id}")

# Agregar las líneas al widget correctamente usando el método interno
if selected_aml_ids:
amls = self.env["account.move.line"].browse(selected_aml_ids)
wizard._action_add_new_amls(amls, allow_partial=False)

# Ejecutar la validación con el context manager
with wizard._action_validate_method():
wizard._action_validate()

# Retornar mensaje de éxito
return Markup(
_("Bank reconciliation completed successfully:<br><a href='%s' target='_blank'>%s</a>")
% (st_line_url, st_line_name)
)
except Exception as e:
return Markup(
_("Bank reconciliation failed:<br><a href='%s' target='_blank'>%s</a><br><br>Error: %s")
% (st_line_url, st_line_name, str(e))
)
finally:
self.write({"reconciliation_in_background": False})

@api.constrains(
"amount",
"amount_currency",
"currency_id",
)
def _check_reconciliation_in_background(self):
"""Valida que no se modifiquen líneas en proceso de conciliación background."""
if self.env.context.get("bg_job"):
return
for line in self:
if line.reconciliation_in_background:
raise UserError(
_(
"Cannot modify payment lines that are being reconciled in background. "
"Please wait until the reconciliation process is complete.\n"
"Journal Entry (id): %(entry)s (%(id)s)",
entry=line.move_id.name,
id=line.move_id.id,
)
)
16 changes: 16 additions & 0 deletions account_reconcile_bg/models/account_move_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import fields, models


class AccountMoveLine(models.Model):
_inherit = "account.move.line"

reconciliation_in_background = fields.Boolean(
string="Reconciliation in Background",
default=False,
readonly=True,
help="Indicates that this line is being reconciled in background",
)
Loading
Loading