[FIX] account_reconcile_oca : foreign currency reconcile with late currency rate

It is possible that the statement line in foreign currency is created before the rate of the day is updated in Odoo. In this case we need to take the real rate of the statement line to comput the exchange rate
pull/694/head
Florian da Costa 2024-10-08 12:44:09 +02:00 committed by Enric Tobella
parent 3fce9ac661
commit cd165e299d
2 changed files with 85 additions and 2 deletions

View File

@ -8,6 +8,7 @@ from dateutil.relativedelta import relativedelta
from odoo import Command, _, api, fields, models
from odoo.exceptions import UserError
from odoo.fields import first
from odoo.tools import float_is_zero
@ -415,7 +416,11 @@ class AccountBankStatementLine(models.Model):
@api.onchange("manual_amount_in_currency")
def _onchange_manual_amount_in_currency(self):
if self.manual_line_id.exists() and self.manual_line_id:
if (
self.manual_line_id.exists()
and self.manual_line_id
and self.manual_kind != "liquidity"
):
self.manual_amount = self.manual_in_currency_id._convert(
self.manual_amount_in_currency,
self.company_id.currency_id,
@ -1046,7 +1051,7 @@ class AccountBankStatementLine(models.Model):
return reconcile_auxiliary_id, new_vals
def _get_exchange_rate_amount(self, amount, currency_amount, currency, line):
if self.foreign_currency_id:
if self.foreign_currency_id == currency:
# take real rate of statement line to compute the exchange rate gain/loss
real_rate = self.amount / self.amount_currency
to_amount_journal_currency = currency_amount * real_rate
@ -1057,6 +1062,12 @@ class AccountBankStatementLine(models.Model):
self.date,
)
to_amount = self.company_id.currency_id.round(to_amount_company_currency)
elif self.currency_id == currency and not self.foreign_currency_id:
liquidity_lines, _suspense_lines, _other_lines = self._seek_for_lines()
real_rate = (
first(liquidity_lines).balance / first(liquidity_lines).amount_currency
)
to_amount = self.company_id.currency_id.round(currency_amount * real_rate)
else:
to_amount = currency._convert(
currency_amount,

View File

@ -1195,3 +1195,75 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
self.assertFalse(f.add_account_move_line_id)
self.assertTrue(f.can_reconcile)
self.assertEqual(3, len(f.reconcile_data_info["data"]))
def test_invoice_foreign_currency_late_change_of_rate(self):
# Test we can reconcile lines in foreign currency even if the rate was updated
# late in odoo, meaning the statement line was created and the rate was updated
# in odoo after that.
self.env["res.currency.rate"].create(
{
"currency_id": self.env.ref("base.USD").id,
"name": time.strftime("%Y-07-14"),
"rate": 1.15,
}
)
self.env["res.currency.rate"].create(
{
"currency_id": self.env.ref("base.USD").id,
"name": time.strftime("%Y-07-15"),
"rate": 1.2,
}
)
inv1 = self._create_invoice(
currency_id=self.currency_usd_id,
invoice_amount=100,
date_invoice=time.strftime("%Y-07-14"),
auto_validate=True,
)
bank_stmt = self.acc_bank_stmt_model.create(
{
"journal_id": self.bank_journal_usd.id,
"date": time.strftime("%Y-07-15"),
"name": "test",
}
)
bank_stmt_line = self.acc_bank_stmt_line_model.create(
{
"name": "testLine",
"journal_id": self.bank_journal_usd.id,
"statement_id": bank_stmt.id,
"amount": 100,
"date": time.strftime("%Y-07-16"),
}
)
# rate of 07-16 is create after the statement line, meaning the rate of the
# statement line is the one of the 07-15
self.env["res.currency.rate"].create(
{
"currency_id": self.env.ref("base.USD").id,
"name": time.strftime("%Y-07-16"),
"rate": 1.25,
}
)
with Form(
bank_stmt_line,
view="account_reconcile_oca.bank_statement_line_form_reconcile_view",
) as f:
line = f.reconcile_data_info["data"][0]
self.assertEqual(
line["currency_amount"],
100,
)
self.assertEqual(
line["amount"],
83.33,
)
f.manual_reference = "account.move.line;%s" % line["id"]
# simulate click on statement line, check amount does not recompute
self.assertEqual(f.manual_amount, 83.33)
f.add_account_move_line_id = inv1.line_ids.filtered(
lambda l: l.account_id.account_type == "asset_receivable"
)
self.assertEqual(3, len(f.reconcile_data_info["data"]))
self.assertTrue(f.can_reconcile)
self.assertEqual(f.reconcile_data_info["data"][-1]["amount"], 3.63)