[FIX] account_reconcile_model_oca: rounding issue reconciliation

Fix a decimal issue on reconciliation.

Steps:

- Set a reconciliation model with payment tolerance of 2%
- Create an invoice for $1210
- Create a bank stmt with a line for $1185.80
-> Reconciliation model is not apply

This is because of a decimal issue when calculating
the residual balance after reconciliation, leading to
the difference being 2.000000000000004% instead of 2%.

Related to d33e98b141
pull/819/head
Víctor Martínez 2025-03-31 08:57:16 +02:00
parent 92580c31aa
commit c533e46623
2 changed files with 15 additions and 7 deletions

View File

@ -701,7 +701,9 @@ class AccountReconcileModel(models.Model):
for aml_values in amls_values_list for aml_values in amls_values_list
) )
sign = 1 if st_line_amount_curr > 0.0 else -1 sign = 1 if st_line_amount_curr > 0.0 else -1
amount_curr_after_rec = sign * (amls_amount_curr + st_line_amount_curr) amount_curr_after_rec = st_line_currency.round(
sign * (amls_amount_curr + st_line_amount_curr)
)
# The statement line will be fully reconciled. # The statement line will be fully reconciled.
if st_line_currency.is_zero(amount_curr_after_rec): if st_line_currency.is_zero(amount_curr_after_rec):
@ -720,7 +722,10 @@ class AccountReconcileModel(models.Model):
# amount doesn't exceed the tolerance. # amount doesn't exceed the tolerance.
if ( if (
self.payment_tolerance_type == "fixed_amount" self.payment_tolerance_type == "fixed_amount"
and -amount_curr_after_rec <= self.payment_tolerance_param and st_line_currency.compare_amounts(
-amount_curr_after_rec, self.payment_tolerance_param
)
<= 0
): ):
return {"allow_write_off", "allow_auto_reconcile"} return {"allow_write_off", "allow_auto_reconcile"}
@ -730,7 +735,10 @@ class AccountReconcileModel(models.Model):
) * 100.0 ) * 100.0
if ( if (
self.payment_tolerance_type == "percentage" self.payment_tolerance_type == "percentage"
and reconciled_percentage_left <= self.payment_tolerance_param and st_line_currency.compare_amounts(
reconciled_percentage_left, self.payment_tolerance_param
)
<= 0
): ):
return {"allow_write_off", "allow_auto_reconcile"} return {"allow_write_off", "allow_auto_reconcile"}

View File

@ -508,17 +508,17 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
@freeze_time("2019-01-01") @freeze_time("2019-01-01")
def test_enough_payment_tolerance(self): def test_enough_payment_tolerance(self):
rule = self._create_reconcile_model( rule = self._create_reconcile_model(
payment_tolerance_param=1.0, payment_tolerance_param=2.0,
line_ids=[{}], line_ids=[{}],
) )
for inv_type, bsl_sign in (("out_invoice", 1), ("in_invoice", -1)): for inv_type, bsl_sign in (("out_invoice", 1), ("in_invoice", -1)):
invl = self._create_invoice_line( invl = self._create_invoice_line(
1000.0, self.partner_a, inv_type, inv_date="2019-01-01" 1210.0, self.partner_a, inv_type, inv_date="2019-01-01"
) )
# Enough tolerance to match the invoice line. # Enough tolerance to match the invoice line.
st_line = self._create_st_line(amount=bsl_sign * 990.0) st_line = self._create_st_line(amount=bsl_sign * 1185.80)
self._check_statement_matching( self._check_statement_matching(
rule, rule,
{st_line: {"amls": invl, "model": rule, "status": "write_off"}}, {st_line: {"amls": invl, "model": rule, "status": "write_off"}},
@ -527,7 +527,7 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
# The payment amount is higher than the invoice one. # The payment amount is higher than the invoice one.
# However, since the invoice amount is lower than the payment amount, # However, since the invoice amount is lower than the payment amount,
# the tolerance is not checked and the invoice line is matched. # the tolerance is not checked and the invoice line is matched.
st_line = self._create_st_line(amount=bsl_sign * 1010.0) st_line = self._create_st_line(amount=bsl_sign * 1234.20)
self._check_statement_matching( self._check_statement_matching(
rule, rule,
{st_line: {"amls": invl, "model": rule}}, {st_line: {"amls": invl, "model": rule}},