From d40358639f3a55f2e4c9f6378e6508a1166a102d Mon Sep 17 00:00:00 2001 From: dbkosky Date: Fri, 4 Mar 2022 13:58:19 +0000 Subject: [PATCH] [FIX] l10n_it_edi: Tax calculation fails edi constraint if tax price included MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using price included taxes, the xml contained data that failed to meet the constraints of the edi. This is due to the local rounding on the lines of the invoice. For example: A product costing 321€, on two lines of the invoice, with a price included tax of 22% Rounded per line: float_round( 321 - (321/122 * 100), 2 # To two decimal places ) evaluates to 57.89, the total tax will be 2 * 57.89 = 115.78 In the case of global rounding float_round( 321 + 321 - (321/122*100) - (321/122*100), 2 # To two decimal places ) evaluates to 115.77, so we have a difference of one cent. This can be exacerbated by more lines. The constraints on the EDI that this conflicts with are on the tax summary section for each tax. The constraints (roughly reworded): 00422: The base taxable amount for the tax must be equal to the sum of the base product prices (for which we have already used the rounded computed values, calcuated in the invoice) + (rounding). 00421: The value provided for the that is the value of the vat is equal to the taxable base multiplied by the tax rate. The problem is that because of our local roundings, the taxable base is equal to our products, but the tax rate * taxable base is not equal to the tax amount (as present in the invoice). This commit adds to the rounding field and subtracts from the taxable base of the tax summary a value rounding value that should make tax rate * taxable base equal to the value of the vat. closes odoo/odoo#86711 Task: 2789290 X-original-commit: def954e85e83e5be18c0a1805f0af20f8116bf3d Signed-off-by: Josse Colpaert --- .../l10n_it_edi/data/invoice_it_template.xml | 27 +++++++------------ addons/l10n_it_edi/models/account_invoice.py | 17 +++++++++++- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/addons/l10n_it_edi/data/invoice_it_template.xml b/addons/l10n_it_edi/data/invoice_it_template.xml index 25cfc517a5a..bfcbe47dc08 100644 --- a/addons/l10n_it_edi/data/invoice_it_template.xml +++ b/addons/l10n_it_edi/data/invoice_it_template.xml @@ -162,26 +162,17 @@ - + + - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/addons/l10n_it_edi/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py index 22d12387c16..1f2d3b60966 100644 --- a/addons/l10n_it_edi/models/account_invoice.py +++ b/addons/l10n_it_edi/models/account_invoice.py @@ -11,7 +11,7 @@ from datetime import date, datetime from lxml import etree from odoo import api, fields, models, _ -from odoo.tools import float_repr +from odoo.tools import float_repr, float_compare from odoo.exceptions import UserError, ValidationError from odoo.addons.base.models.ir_mail_server import MailDeliveryException from odoo.tests.common import Form @@ -164,6 +164,20 @@ class AccountMove(models.Model): if tax.amount == 0.0: tax_map[tax] = tax_map.get(tax, 0.0) + line.price_subtotal + # Constraints within the edi make local rounding on price included taxes a problem. + # To solve this there is a or 'rounding' field, such that: + # taxable base = sum(taxable base for each unit) + Arrotondamento + tax_details = self._prepare_edi_tax_details() + for _tax_name, tax_dict in tax_details['tax_details'].items(): + base_amount = tax_dict['base_amount'] + tax_amount = tax_dict['tax_amount'] + tax_rate = tax_dict['tax'].amount + if tax_dict['tax'].price_include and tax_dict['tax'].amount_type == 'percent': + expected_base_amount = tax_amount * 100 / tax_rate if tax_rate else False + if expected_base_amount and float_compare(base_amount, expected_base_amount, 2): + tax_dict['rounding'] = base_amount - (tax_amount * 100 / tax_rate) + tax_dict['base_amount'] = base_amount - tax_dict['rounding'] + # Create file content. template_values = { 'record': self, @@ -182,6 +196,7 @@ class AccountMove(models.Model): 'pdf': pdf, 'pdf_name': pdf_name, 'tax_map': tax_map, + 'tax_details': tax_details, } return template_values