[FIX] partner update from reconciliation widget

We cant to avoid to change amounts on accounting entries during the reconciliation process. One of the goal is to avoid a following case :
The statement line is created in a foreign currency journal, later, the rate is updated in Odoo.
During reconciliation process, the partner is set on liquidity line, the accounting entries are synchronized and the balance changes.
pull/808/head
Florian da Costa 2025-02-05 16:35:47 +01:00 committed by Jordi Ballester Alomar
parent a42eae4fab
commit dbd55e8fa5
2 changed files with 51 additions and 44 deletions

View File

@ -493,6 +493,8 @@ class AccountBankStatementLine(models.Model):
line["kind"] if line["kind"] != "suspense" else "other" line["kind"] if line["kind"] != "suspense" else "other"
) )
line.update(line_vals) line.update(line_vals)
if line["kind"] == "liquidity":
self._update_move_partner()
if self.manual_line_id and self.manual_line_id.id == line.get( if self.manual_line_id and self.manual_line_id.id == line.get(
"original_exchange_line_id" "original_exchange_line_id"
): ):
@ -518,6 +520,11 @@ class AccountBankStatementLine(models.Model):
) )
self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False) self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
def _update_move_partner(self):
if self.partner_id == self.manual_partner_id:
return
self.partner_id = self.manual_partner_id
@api.depends("reconcile_data", "is_reconciled") @api.depends("reconcile_data", "is_reconciled")
def _compute_reconcile_data_info(self): def _compute_reconcile_data_info(self):
for record in self: for record in self:
@ -972,61 +979,48 @@ class AccountBankStatementLine(models.Model):
)(self._prepare_reconcile_line_data(data["data"])) )(self._prepare_reconcile_line_data(data["data"]))
return result return result
def _synchronize_to_moves_custom(self, changed_fields): def _synchronize_to_moves(self, changed_fields):
"""Similar process to what _synchronize_to_moves() method would do but without """We want to avoid to change stuff (mainly amounts ) in accounting entries
the relative to all the changed_fields, we just need to update partner_id. when some changes happen in the reconciliation widget. The only change
We precisely do not do an onchange of self.partner_id = self.manual_partner_id (among the fields triggering the synchronization) possible from the
to avoid making all those unnecessary changes, but we need to apply this reconciliation widget is the partner_id field.
change to the account.move and the lines without side effects.
A change of manual_partner_id that has been reconciled should NOT change the So, in case of change on partner_id field we do not call super but make
values of the account.move lines. only the required change (relative to partner) on accounting entries.
And if something else changes, we then re-define reconcile_data_info to
make the data consistent (for example, if debit/credit has changed by
applying a different rate or even if there was a correction on statement
line amount).
""" """
if self._context.get("skip_account_move_synchronization"): if self._context.get("skip_account_move_synchronization"):
return return
if "partner_id" in changed_fields and not any(
# we actually check reconcile_data to find the partner of the liquidity lines field_name in changed_fields
# because the written manual_partner_id is not always related to the liquidity for field_name in (
# line... "payment_ref",
if not any(f_name in changed_fields for f_name in ("reconcile_data",)): "amount",
return "amount_currency",
"foreign_currency_id",
for st_line in self.with_context(skip_account_move_synchronization=True): "currency_id",
data = st_line.reconcile_data_info.get("data", []) )
partner_id = False ):
for line_data in data: for st_line in self.with_context(skip_account_move_synchronization=True):
if line_data["kind"] == "liquidity":
partner_id = (
line_data.get("partner_id")
and line_data.get("partner_id")[0]
or False
)
break
if st_line.partner_id.id != partner_id:
( (
liquidity_lines, liquidity_lines,
suspense_lines, suspense_lines,
_other_lines, _other_lines,
) = st_line._seek_for_lines() ) = st_line._seek_for_lines()
line_vals = {"partner_id": partner_id} line_vals = {"partner_id": st_line.partner_id}
line_ids_commands = [(1, liquidity_lines.id, line_vals)] line_ids_commands = [(1, liquidity_lines.id, line_vals)]
if suspense_lines: if suspense_lines:
line_ids_commands.append((1, suspense_lines.id, line_vals)) line_ids_commands.append((1, suspense_lines.id, line_vals))
st_line_vals = {"line_ids": line_ids_commands} st_line_vals = {"line_ids": line_ids_commands}
if st_line.move_id.partner_id.id != partner_id: if st_line.move_id.partner_id != st_line.partner_id:
st_line_vals["partner_id"] = partner_id st_line_vals["partner_id"] = st_line.partner_id.id
st_line.move_id.write(st_line_vals) st_line.move_id.write(st_line_vals)
st_line.write({"partner_id": partner_id}) else:
super()._synchronize_to_moves(changed_fields=changed_fields)
def _synchronize_to_moves(self, changed_fields):
"""We take advantage of this method to call the custom method that does
specific things. Also, if something is changed, we will re-define
reconcile_data_info to make the data consistent (for example, if debit/credit
has changed by applying a different rate).
"""
super()._synchronize_to_moves(changed_fields=changed_fields)
self._synchronize_to_moves_custom(changed_fields)
if self._context.get("skip_account_move_synchronization"):
return
if not any( if not any(
field_name in changed_fields field_name in changed_fields
@ -1040,8 +1034,9 @@ class AccountBankStatementLine(models.Model):
) )
): ):
return return
# reset reconcile_data_info if amounts are not consistent anymore with the
for st_line in self.with_context(skip_account_move_synchronization=True): # amounts of the accounting entries
for st_line in self:
if st_line._check_reconcile_data_changed(): if st_line._check_reconcile_data_changed():
st_line.reconcile_data_info = st_line._default_reconcile_data() st_line.reconcile_data_info = st_line._default_reconcile_data()

View File

@ -1352,6 +1352,7 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
"rate": 1.25, "rate": 1.25,
} }
) )
liquidity_lines, suspense_lines, other_lines = bank_stmt_line._seek_for_lines()
with Form( with Form(
bank_stmt_line, bank_stmt_line,
view="account_reconcile_oca.bank_statement_line_form_reconcile_view", view="account_reconcile_oca.bank_statement_line_form_reconcile_view",
@ -1365,6 +1366,17 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
line["amount"], line["amount"],
83.33, 83.33,
) )
# check that adding a partner does not recompute the amounts on accounting
# entries, but is still synchronized with accounting entries
f.manual_reference = "account.move.line;%s" % liquidity_lines.id
f.manual_partner_id = inv1.partner_id
self.assertEqual(f.partner_id, inv1.partner_id)
self.assertEqual(liquidity_lines.debit, 83.33)
f.save()
# check liquidity line did not recompute debit with the new rate with
# partner change
self.assertEqual(liquidity_lines.debit, 83.33)
self.assertEqual(liquidity_lines.partner_id, inv1.partner_id)
f.manual_reference = "account.move.line;%s" % line["id"] f.manual_reference = "account.move.line;%s" % line["id"]
# simulate click on statement line, check amount does not recompute # simulate click on statement line, check amount does not recompute
f.manual_partner_id = inv1.partner_id f.manual_partner_id = inv1.partner_id