diff --git a/account_reconcile_oca/models/account_bank_statement_line.py b/account_reconcile_oca/models/account_bank_statement_line.py index dc22854013..4aa30e2a49 100644 --- a/account_reconcile_oca/models/account_bank_statement_line.py +++ b/account_reconcile_oca/models/account_bank_statement_line.py @@ -8,6 +8,7 @@ from odoo import Command, _, api, fields, models from odoo.exceptions import UserError +from odoo.fields import first from odoo.tools import float_is_zero @@ -417,7 +418,11 @@ def _onchange_manual_reconcile_reference(self): @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, @@ -1039,7 +1044,7 @@ def _get_reconcile_line( 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 @@ -1050,6 +1055,12 @@ def _get_exchange_rate_amount(self, amount, currency_amount, currency, line): 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, diff --git a/account_reconcile_oca/tests/test_bank_account_reconcile.py b/account_reconcile_oca/tests/test_bank_account_reconcile.py index 76fd638d18..78cd0669b5 100644 --- a/account_reconcile_oca/tests/test_bank_account_reconcile.py +++ b/account_reconcile_oca/tests/test_bank_account_reconcile.py @@ -1183,3 +1183,75 @@ def test_invoice_foreign_currency_change(self): 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)