diff options
| author | Laurent Smet <las@odoo.com> | 2021-01-15 14:38:04 +0000 |
|---|---|---|
| committer | Laurent Smet <las@odoo.com> | 2021-01-15 15:00:20 +0000 |
| commit | 4d4e6e588d14742f153a1c6b67d510e0c21e5d64 (patch) | |
| tree | 1ee6706aab7c3fab49119a60f6783543a89e7642 /addons | |
| parent | 6b4941160f336ed7a45287c5568dabd1c56289aa (diff) | |
[FIX] account: Fix statement line rounding issue multi-currency
When reconciling a statement line with multiple lines in a multi-currency environment, it could lead to a rounding issue due to the currency rates. It could lead to an auto-generated open-balance of 0.01 amount to auto-balance the journal entry but the result is wrong since the partner has an open amount left on the receivable/payable account.
closes odoo/odoo#64620
Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/models/account_bank_statement.py | 23 | ||||
| -rw-r--r-- | addons/account/tests/test_account_bank_statement.py | 51 |
2 files changed, 72 insertions, 2 deletions
diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 5a3593ccf9a..805cc6b7e31 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -1024,6 +1024,9 @@ class AccountBankStatementLine(models.Model): ''' self.ensure_one() + journal = self.journal_id + company_currency = journal.company_id.currency_id + foreign_currency = self.foreign_currency_id or journal.currency_id or company_currency liquidity_lines, suspense_lines, other_lines = self._seek_for_lines() @@ -1040,6 +1043,7 @@ class AccountBankStatementLine(models.Model): reconciliation_overview = [] total_balance = liquidity_lines.balance + total_amount_currency = liquidity_lines.amount_currency # Step 1: Split 'lines_vals_list' into two batches: # - The existing account.move.lines that need to be reconciled with the statement line. @@ -1061,6 +1065,7 @@ class AccountBankStatementLine(models.Model): # Newly created account.move.line from scratch. line_vals = self._prepare_counterpart_move_line_vals(vals) total_balance += line_vals['debit'] - line_vals['credit'] + total_amount_currency += line_vals['amount_currency'] reconciliation_overview.append({ 'line_vals': line_vals, @@ -1072,6 +1077,7 @@ class AccountBankStatementLine(models.Model): for line, counterpart_vals in zip(existing_lines, to_process_vals): line_vals = self._prepare_counterpart_move_line_vals(counterpart_vals, move_line=line) balance = line_vals['debit'] - line_vals['credit'] + amount_currency = line_vals['amount_currency'] reconciliation_vals = { 'line_vals': line_vals, @@ -1084,7 +1090,7 @@ class AccountBankStatementLine(models.Model): payment_vals = self.env['account.payment.register']\ .with_context(active_model='account.move.line', active_ids=line.ids)\ .create({ - 'amount': abs(line_vals['amount_currency']) if line_vals['currency_id'] else abs(balance), + 'amount': abs(amount_currency) if line_vals['currency_id'] else abs(balance), 'payment_date': self.date, 'payment_type': 'inbound' if balance < 0.0 else 'outbound', 'journal_id': self.journal_id.id, @@ -1127,8 +1133,21 @@ class AccountBankStatementLine(models.Model): reconciliation_overview.append(reconciliation_vals) total_balance += balance + total_amount_currency += amount_currency + + # Step 3: Fix rounding issue due to currency conversions. + # Add the remaining balance on the first encountered line starting with the custom ones. + + if foreign_currency.is_zero(total_amount_currency) and not company_currency.is_zero(total_balance): + vals = reconciliation_overview[0]['line_vals'] + new_balance = vals['debit'] - vals['credit'] - total_balance + vals.update({ + 'debit': new_balance if new_balance > 0.0 else 0.0, + 'credit': -new_balance if new_balance < 0.0 else 0.0, + }) + total_balance = 0.0 - # Step 3: If the journal entry is not yet balanced, create an open balance. + # Step 4: If the journal entry is not yet balanced, create an open balance. if self.company_currency_id.round(total_balance): counterpart_vals = { diff --git a/addons/account/tests/test_account_bank_statement.py b/addons/account/tests/test_account_bank_statement.py index 253c9e8243e..c582a6d1dc3 100644 --- a/addons/account/tests/test_account_bank_statement.py +++ b/addons/account/tests/test_account_bank_statement.py @@ -1498,3 +1498,54 @@ class TestAccountBankStatementLine(TestAccountBankStatementCommon): 'amount_residual_currency': 0.0, }, ]) + + def test_conversion_rate_rounding_issue(self): + ''' Ensure the reconciliation is well handling the rounding issue due to multiple currency conversion rates. + + In this test, the resulting journal entry after reconciliation is: + {'amount_currency': 7541.66, 'debit': 6446.97, 'credit': 0.0} + {'amount_currency': 226.04, 'debit': 193.22, 'credit': 0.0} + {'amount_currency': -7767.70, 'debit': 0.0, 'credit': 6640.19} + ... but 226.04 / 1.1698 = 193.23. In this situation, 0.01 has been removed from this write-off line in order to + avoid an unecessary open-balance line being an exchange difference issue. + ''' + self.bank_journal_2.currency_id = self.currency_2 + self.currency_data['rates'][-1].rate = 1.1698 + + statement = self.env['account.bank.statement'].create({ + 'name': 'test_statement', + 'date': '2017-01-01', + 'journal_id': self.bank_journal_2.id, + 'line_ids': [ + (0, 0, { + 'date': '2019-01-01', + 'payment_ref': 'line_1', + 'partner_id': self.partner_a.id, + 'amount': 7541.66, + }), + ], + }) + statement.button_post() + statement_line = statement.line_ids + + payment = self.env['account.payment'].create({ + 'amount': 7767.70, + 'date': '2019-01-01', + 'currency_id': self.currency_2.id, + 'payment_type': 'inbound', + 'partner_type': 'customer', + }) + payment.action_post() + liquidity_lines, counterpart_lines, writeoff_lines = payment._seek_for_lines() + self.assertRecordValues(liquidity_lines, [{'amount_currency': 7767.70}]) + + statement_line.reconcile([ + {'id': liquidity_lines.id}, + {'balance': 226.04, 'account_id': self.company_data['default_account_revenue'].id, 'name': "write-off"}, + ]) + + self.assertRecordValues(statement_line.line_ids, [ + {'amount_currency': 7541.66, 'debit': 6446.97, 'credit': 0.0}, + {'amount_currency': 226.04, 'debit': 193.22, 'credit': 0.0}, + {'amount_currency': -7767.70, 'debit': 0.0, 'credit': 6640.19}, + ]) |
