diff options
| author | Thibault Francois <tfr@openerp.com> | 2020-03-06 14:27:48 +0000 |
|---|---|---|
| committer | Laurent Smet <las@odoo.com> | 2020-03-20 07:59:25 +0000 |
| commit | bc6dc53b6da17b22f66e744924cabb976e3f37e6 (patch) | |
| tree | 5627c99a5b352fd7ab18949c0ec8c1ad968495f6 /addons | |
| parent | 215b2fffa23409ab91729bf926d6a8ed9a2e6f35 (diff) | |
[FIX] account: issue with not rounding price_subtotal
Write on business field on account.move.line
may lead to an unbalanced move due to currency conversion
from the price_subtotal to debit or credit
How to reproduce:
You need to create an invoice in a different currency
than the company currency
The rate form currency to company currency should be much
bigger then 1 for example 8 or 10
Create a line the will have a pricesubtotal
with 3 decimal
For example:
price unit : 28.8
qty: 4
discount: 22%
the price_subtotal will be 89.856
rounded in the form to 89.86
Based on that with a rate of 7.79356837023608
You end up with a credit of 700.33
then write on the line, for example the analytic account
It will trigger the computation of the price subtotal
and directly with that value the credit
and you endup with a credit 700.30
which is not balanced with the 700.33 of the other line
Solution:
Always round the pricesubtotal computed with the currency before
using it in any further computation
closes odoo/odoo#47305
X-original-commit: a60017df0e947e32f0606ee1487224d2c00470a4
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/account/models/account_move.py | 3 | ||||
| -rw-r--r-- | addons/account/tests/test_account_move_out_invoice.py | 74 |
2 files changed, 77 insertions, 0 deletions
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index d14164136b8..b1458bf43e6 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -2740,6 +2740,9 @@ class AccountMoveLine(models.Model): res['price_total'] = taxes_res['total_included'] else: res['price_total'] = res['price_subtotal'] = subtotal + #In case of multi currency, round before it's use for computing debit credit + if currency: + res = {k: currency.round(v) for k, v in res.items()} return res def _get_fields_onchange_subtotal(self, price_subtotal=None, move_type=None, currency=None, company=None, date=None): diff --git a/addons/account/tests/test_account_move_out_invoice.py b/addons/account/tests/test_account_move_out_invoice.py index 508ba4bec0b..f497438fef1 100644 --- a/addons/account/tests/test_account_move_out_invoice.py +++ b/addons/account/tests/test_account_move_out_invoice.py @@ -810,6 +810,80 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'amount_total': 1730.0, }) + def test_out_invoice_line_onchange_rounding_price_subtotal(self): + ''' Seek for rounding issue on the price_subtotal when dealing with a price_unit having more digits than the + foreign currency one. + ''' + decimal_precision_name = self.env['account.move.line']._fields['price_unit']._digits + decimal_precision = self.env['decimal.precision'].search([('name', '=', decimal_precision_name)]) + + self.assertTrue(decimal_precision, "Decimal precision '%s' not found" % decimal_precision_name) + + self.currency_data['currency'].rounding = 0.01 + decimal_precision.digits = 4 + + def check_invoice_values(invoice): + self.assertInvoiceValues(invoice, [ + { + 'quantity': 1.0, + 'price_unit': 0.025, + 'price_subtotal': 0.03, + 'debit': 0.0, + 'credit': 0.02, + 'currency_id': self.currency_data['currency'].id, + }, + { + 'quantity': 1.0, + 'price_unit': -0.03, + 'price_subtotal': -0.03, + 'debit': 0.02, + 'credit': 0.0, + 'currency_id': self.currency_data['currency'].id, + }, + ], { + 'amount_untaxed': 0.03, + 'amount_tax': 0.0, + 'amount_total': 0.03, + }) + + # == Test at the creation of the invoice == + + invoice_1 = self.env['account.move'].create({ + 'move_type': 'out_invoice', + 'invoice_date': '2017-01-01', + 'date': '2017-01-01', + 'partner_id': self.partner_a.id, + 'currency_id': self.currency_data['currency'].id, + 'invoice_line_ids': [(0, 0, { + 'name': 'test line', + 'price_unit': 0.025, + 'quantity': 1, + 'account_id': self.company_data['default_account_revenue'].id, + })], + }) + + check_invoice_values(invoice_1) + + # == Test when writing on the invoice == + + invoice_2 = self.env['account.move'].create({ + 'move_type': 'out_invoice', + 'invoice_date': '2017-01-01', + 'date': '2017-01-01', + 'partner_id': self.partner_a.id, + 'currency_id': self.currency_data['currency'].id, + }) + invoice_2.write({ + 'invoice_line_ids': [(0, 0, { + 'name': 'test line', + 'price_unit': 0.025, + 'quantity': 1, + 'account_id': self.company_data['default_account_revenue'].id, + })], + }) + + check_invoice_values(invoice_2) + def test_out_invoice_line_onchange_taxes_2_price_unit_tax_included(self): ''' Seek for rounding issue in the price unit. Suppose a price_unit of 2300 with a 5.5% price-included tax applied on it. |
