Skip to content
Closed
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
11 changes: 11 additions & 0 deletions l10n_ar_payment_bundle/models/account_payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,17 @@ def _compute_counterpart_rate(self):
for rec in self.filtered(lambda x: x.main_payment_id and x.currency_id == x.company_currency_id):
rec.counterpart_rate = rec.main_payment_id.counterpart_rate

@api.depends("main_payment_id")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acá capaz agregar el rate del main en el depends, por si cambia el rate que no quede el anterior?

def _compute_accounting_rate(self):
super(AccountPayment, self)._compute_accounting_rate()
Comment on lines +164 to +166
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

El override de _compute_accounting_rate redefine @api.depends solo con main_payment_id, pero el método (y el super()) depende de currency_id, company_currency_id, company_id, date, etc. Así se pierde el grafo de dependencias original y accounting_rate puede quedar desactualizado en pagos NO vinculados (y también no recomputar cuando cambia la tasa/fecha/moneda). Mantener los depends del padre y agregar los del main (p.ej. main_payment_id.counterpart_rate/main_payment_id.accounting_rate y las monedas involucradas).

Copilot uses AI. Check for mistakes.
for rec in self.filtered(lambda x: x.main_payment_id and x.currency_id == x.counterpart_currency_id):
# Si B = C en ambos pagos, tomamos la tasa forzada del main como
# fuente de verdad para mantener counterpart_rate alineado.
if rec.main_payment_id.counterpart_rate and rec.accounting_rate != rec.main_payment_id.counterpart_rate:
Comment on lines +168 to +170
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La condición if rec.main_payment_id.counterpart_rate and rec.accounting_rate != rec.main_payment_id.counterpart_rate hace que, cuando la tasa del linked ya coincide con la del main (caso normal sin “forced rate”), caiga en el else y termine asignando rec.main_payment_id.accounting_rate (que para el main suele ser 1.0). Esto parece incorrecto: para linked con currency_id == counterpart_currency_id debería tomar siempre la tasa del main (o, si no aplica, una fuente consistente), sin depender del !=.

Suggested change
# Si B = C en ambos pagos, tomamos la tasa forzada del main como
# fuente de verdad para mantener counterpart_rate alineado.
if rec.main_payment_id.counterpart_rate and rec.accounting_rate != rec.main_payment_id.counterpart_rate:
# Si B = C en ambos pagos, tomamos la tasa del main como fuente de
# verdad para mantener counterpart_rate alineado. Si el main tiene
# counterpart_rate, debe prevalecer siempre; si no, usamos su
# accounting_rate como fallback consistente.
if rec.main_payment_id.counterpart_rate:

Copilot uses AI. Check for mistakes.
rec.accounting_rate = rec.main_payment_id.counterpart_rate
else:
rec.accounting_rate = rec.main_payment_id.accounting_rate

@api.depends("main_payment_id.counterpart_currency_id")
def _compute_counterpart_currency_id(self):
for rec in self.filtered("main_payment_id"):
Expand Down
47 changes: 47 additions & 0 deletions l10n_ar_payment_bundle/tests/test_payment_bundle_multimoneda.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,53 @@ def test_b3_bundle_deuda_usd_linked_mixtos(self):
# Pago intencional parcial: 500+500+30 = 1030 USD de 1210 USD total
self.assertEqual(invoice.payment_state, "partial", "1030 USD pagados de 1210 USD → debe quedar parcial")

def test_b3_linked_usd_uses_forced_main_counterpart_rate(self):
"""B.3.x · Main con deuda USD y counterpart rate forzado.

Caso de regresión:
- Main: A=ARS, B=USD, se fuerza user_counterpart_rate=1400 (en vez de tasa vigente)
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En el docstring del test se indica que se fuerza user_counterpart_rate=1400, pero el test en realidad setea main.counterpart_rate = 1/1400. Para evitar confusión (y dejar claro qué campo es la “fuente de verdad”), conviene alinear el texto con el código o setear el campo que describe el docstring.

Suggested change
- Main: A=ARS, B=USD, se fuerza user_counterpart_rate=1400 (en vez de tasa vigente)
- Main: A=ARS, B=USD, se fuerza counterpart_rate=1/1400 (equivalente a user rate 1400)

Copilot uses AI. Check for mistakes.
- Linked USD: A=B=USD

Verifica:
- linked.accounting_rate toma la tasa forzada del main (USD/ARS = 1/1400)
- no toma la tasa contable de mercado del día
"""
invoice = self._create_invoice(1_000, self.usd)
main = self._create_main_payment(invoice, fiscal_position=False, l10n_ar_fiscal_position_id=False)

forced_user_rate = 1_400.0
forced_counterpart_rate = 1.0 / forced_user_rate
market_counterpart_rate = self._get_rate(self.ars, self.usd)

self.assertNotAlmostEqual(
forced_counterpart_rate,
market_counterpart_rate,
places=9,
msg="Precondición: la tasa forzada debe diferir de la tasa de mercado",
)

main.counterpart_rate = forced_counterpart_rate
self.assertAlmostEqual(main.counterpart_rate, forced_counterpart_rate, places=9)

linked_usd = self._add_linked_payment(main, self.bank_usd, 100)
self.assertEqual(linked_usd.currency_id, self.usd)
self.assertEqual(linked_usd.counterpart_currency_id, self.usd)
self.assertAlmostEqual(linked_usd.counterpart_rate, 1.0, places=9, msg="A=B en linked USD")

self.assertAlmostEqual(
linked_usd.accounting_rate,
forced_counterpart_rate,
places=9,
msg="El linked USD debe respetar la tasa forzada en el main",
)
self.assertNotAlmostEqual(
linked_usd.accounting_rate,
market_counterpart_rate,
places=9,
msg="No debe usar la tasa contable de mercado",
)
self.assertAlmostEqual(linked_usd.user_accounting_rate, forced_user_rate, places=6)

def test_b4_bundle_deuda_usd_cheques_ars_y_transfer_usd(self):
"""B.4 · Factura 1 210 USD (1 000 neto, 1 USD = 1 200 ARS).
Bundle: 2 cheques propios ARS + 1 transferencia USD + retención IIBB.
Expand Down
Loading