[FIX] account: Fix reconciliation rounding issue
Steps to reproduce: - Create an invoice: select a product; set the price to 23.00$; change the currency to €; confirm the invoice. - Create a receiving payment from the same customer: select the $ currency and put 100$ - Go back to the invoice and select the payment/reconcile the invoice and the payment. Issue: The payment is partial with 0.01€ to be paid. Cause: (conversion rate: 1.5289$/1€) 1) When the currency is changed or the price assigned, we convert the price EXCL. and then we convert the tax amount. https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L3953-L3954 In our example: - price EXCL.: 23€ * 1.5289 = 35.1647$ price._convert() -> 35.16$ - Tax amount: 3.45€ * 1.5289 = 5.274705$ tax_amount._convert() -> 5.27$ Real Sum = 40,439405$ Sum returned after convertion = 40.43$ != 40.44$ 2) To compute what is left to be paid, we use the converted amount and convert it back to the currency of the invoice. Double conversion, double mistake. https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L4873-L4878 In our example: 3) We convert back the 40.43$ to know the residual: - 40.43$ / 1.5289 = 26.443848519€ => rounded = 26.44€ != 26.45 We then compute the `debit_amount_residual_currency` (26.45€) by substracting from it the `min_debit_amount_residual_currency`(26.44€). https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L4886-L4887 Which lefts us with a `debit_amount_residual_currency` 0.01€ (0.0099999..801). https://github.com/odoo/odoo/blob/582b43bdf46c485be8219e1cbeb60dbed033f1e7/addons/account/models/account_move.py#L1421-L1437 Ticket: 2765223 X-original-commit: ce1d64cdcf160e596dba97b29f970a8b9d87b348 Part-of: odoo/odoo#88265
This commit is contained in:
@@ -2237,6 +2237,39 @@ class TestAccountMoveReconcile(AccountTestInvoicingCommon):
|
||||
{'amount_residual': 0.0, 'amount_residual_currency': 0.0, 'reconciled': True},
|
||||
])
|
||||
|
||||
def test_reconcile_rounding_issue(self):
|
||||
rate = 1/1.5289
|
||||
currency = self.setup_multi_currency_data(default_values={
|
||||
'name': 'XXX',
|
||||
'symbol': 'XXX',
|
||||
'currency_unit_label': 'XX',
|
||||
'currency_subunit_label': 'X',
|
||||
'rounding': 0.01,
|
||||
}, rate2016=rate, rate2017=rate)['currency']
|
||||
|
||||
# Create an invoice 26.45 XXX = 40.43 USD
|
||||
invoice = self.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': self.partner_a.id,
|
||||
'currency_id': currency.id,
|
||||
'date': '2017-01-01',
|
||||
'invoice_date': '2017-01-01',
|
||||
'invoice_line_ids': [(0, 0, {
|
||||
'product_id': self.product_a.id,
|
||||
'price_unit': 23.0,
|
||||
'tax_ids': [(6, 0, self.company_data['default_tax_sale'].ids)],
|
||||
})],
|
||||
})
|
||||
invoice.action_post()
|
||||
|
||||
# Pay it with 100.0 USD
|
||||
self.env['account.payment.register']\
|
||||
.with_context(active_model='account.move', active_ids=invoice.ids)\
|
||||
.create({'amount': 100.0, 'currency_id': self.company_data['currency'].id})\
|
||||
._create_payments()
|
||||
|
||||
self.assertTrue(invoice.payment_state in ('in_payment', 'paid'))
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Test creation of extra journal entries during the reconciliation to
|
||||
# deal with taxes that are exigible on payment (cash basis).
|
||||
|
||||
Reference in New Issue
Block a user