summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorLaurent Smet <las@odoo.com>2021-01-15 14:38:04 +0000
committerLaurent Smet <las@odoo.com>2021-01-15 15:00:20 +0000
commit4d4e6e588d14742f153a1c6b67d510e0c21e5d64 (patch)
tree1ee6706aab7c3fab49119a60f6783543a89e7642 /addons
parent6b4941160f336ed7a45287c5568dabd1c56289aa (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.py23
-rw-r--r--addons/account/tests/test_account_bank_statement.py51
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},
+ ])