From d3f3aff5e46574d2bf02c363507330073874fc69 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Fri, 17 Dec 2021 17:49:51 +0100 Subject: [PATCH] [IMP] supporto per la conversione degli importi in EUR per fatture in valuta estera --- .../data/invoice_it_template.xml | 43 ++++++- l10n_it_fatturapa_out/models/company.py | 20 ++++ .../tests/data/IT06363391001_00009.xml | 104 ---------------- .../tests/data/IT06363391001_00015.xml | 105 +++++++++++++++++ .../tests/data/IT06363391001_00016.xml | 105 +++++++++++++++++ .../tests/test_fatturapa_xml_validation.py | 111 +++++++++--------- l10n_it_fatturapa_out/views/company_view.xml | 14 ++- l10n_it_fatturapa_out/wizard/efattura.py | 16 ++- 8 files changed, 349 insertions(+), 169 deletions(-) delete mode 100644 l10n_it_fatturapa_out/tests/data/IT06363391001_00009.xml create mode 100644 l10n_it_fatturapa_out/tests/data/IT06363391001_00015.xml create mode 100644 l10n_it_fatturapa_out/tests/data/IT06363391001_00016.xml diff --git a/l10n_it_fatturapa_out/data/invoice_it_template.xml b/l10n_it_fatturapa_out/data/invoice_it_template.xml index 748a9989a2b4..35e73a6d4fe1 100644 --- a/l10n_it_fatturapa_out/data/invoice_it_template.xml +++ b/l10n_it_fatturapa_out/data/invoice_it_template.xml @@ -170,7 +170,9 @@ e 'line' per riga di fattura (a seconda del livello in cui sono chiamati) - + INVCONT + + Valuta + + + + @@ -217,9 +227,11 @@ e 'line' per riga di fattura (a seconda del livello in cui sono chiamati) + - + - + + --> + @@ -600,10 +625,10 @@ e 'line' per riga di fattura (a seconda del livello in cui sono chiamati) + + diff --git a/l10n_it_fatturapa_out/models/company.py b/l10n_it_fatturapa_out/models/company.py index fcbf2fe3c24c..3ba9073a0dbc 100644 --- a/l10n_it_fatturapa_out/models/company.py +++ b/l10n_it_fatturapa_out/models/company.py @@ -1,9 +1,12 @@ # Copyright 2019 Roberto Fichera +# Copyright 2022 Marco Colombo # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo import _, api, fields, models from odoo.exceptions import ValidationError +_DEFAULT_XML_DIVISA_VALUE = "force_eur" + class ResCompany(models.Model): _inherit = "res.company" @@ -15,6 +18,15 @@ class ResCompany(models.Model): "in a single XML file. 0=Unlimited", ) + xml_divisa_value = fields.Selection( + [ + ("keep_orig", "Keep original"), + ("force_eur", "Force euro"), + ], + string="XML Divisa value", + default=_DEFAULT_XML_DIVISA_VALUE, + ) + @api.constrains("max_invoice_in_xml") def _validate_max_invoice_in_xml(self): if self.max_invoice_in_xml < 0: @@ -33,12 +45,20 @@ class AccountConfigSettings(models.TransientModel): related="company_id.max_invoice_in_xml", readonly=False ) + xml_divisa_value = fields.Selection( + related="company_id.xml_divisa_value", readonly=False + ) + @api.onchange("company_id") def onchange_company_id(self): res = super(AccountConfigSettings, self).onchange_company_id() if self.company_id: company = self.company_id self.max_invoice_in_xml = company.max_invoice_in_xml or 0 + self.xml_divisa_value = ( + company.xml_divisa_value or _DEFAULT_XML_DIVISA_VALUE + ) else: self.max_invoice_in_xml = 0 + self.xml_divisa_value = _DEFAULT_XML_DIVISA_VALUE return res diff --git a/l10n_it_fatturapa_out/tests/data/IT06363391001_00009.xml b/l10n_it_fatturapa_out/tests/data/IT06363391001_00009.xml deleted file mode 100644 index 94ccc4e7d2ab..000000000000 --- a/l10n_it_fatturapa_out/tests/data/IT06363391001_00009.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - IT - 06363391001 - - 00009 - FPR12 - XXXXXXX - - 06543534343 - info@yourcompany.example.com - - - - - - IT - 06363391001 - - - YourCompany - - RF01 - - - Via Milano, 1 - 00100 - Roma - AK - IT - - - 06543534343 - info@yourcompany.example.com - - - - - - AE - 99999999999 - - - Foreign Customer - - - - 29-17 Al Thanya St - 00000 - Dubai - EE - AE - - - - - - - TD01 - AED - 2018-01-07 - INV/2018/0018 - 14.00 - SI - - - - - 1 - Mouse Optical - 1.000 - Unit(s) - 8.19672 - 8.20 - 22.00 - - - 2 - Zed+ Antivirus - 1.000 - Unit(s) - 3.27869 - 3.28 - 22.00 - - - 22.00 - 11.48 - 2.52 - - - - TP02 - - MP05 - 2018-02-28 - 14.00 - - - - diff --git a/l10n_it_fatturapa_out/tests/data/IT06363391001_00015.xml b/l10n_it_fatturapa_out/tests/data/IT06363391001_00015.xml new file mode 100644 index 000000000000..0aab977ff77b --- /dev/null +++ b/l10n_it_fatturapa_out/tests/data/IT06363391001_00015.xml @@ -0,0 +1,105 @@ + + + + + + IT + 06363391001 + + 00015 + FPA12 + UFPQ1O + + 06543534343 + info@yourcompany.example.com + + + + + + IT + 06363391001 + + + YourCompany + + RF01 + + + Via Milano, 1 + 00100 + Roma + AK + IT + + + 06543534343 + info@yourcompany.example.com + + + + + + IT + 06363391001 + + 06363391001 + + Public Administration + + + + Via Roma, 1 + 10100 + Torino + AK + IT + + + + + + + TD01 + EUR + 2021-12-16 + INV/2021/12/0001 + 14.00 + SI + + + + + 1 + Cabinet with Doors + 1.000 + Unit(s) + 14.00000 + 14.00 + 0.00 + N3.2 + + Valuta + USD + 16.38000 + 2021-12-16 + + + + 0.00 + N3.2 + 14.00 + 0.00 + Not subject to VAT law + + + + TP02 + + MP05 + 2022-01-31 + 14.00 + + + + diff --git a/l10n_it_fatturapa_out/tests/data/IT06363391001_00016.xml b/l10n_it_fatturapa_out/tests/data/IT06363391001_00016.xml new file mode 100644 index 000000000000..ca62e8138b71 --- /dev/null +++ b/l10n_it_fatturapa_out/tests/data/IT06363391001_00016.xml @@ -0,0 +1,105 @@ + + + + + + IT + 06363391001 + + 00016 + FPA12 + UFPQ1O + + 06543534343 + info@yourcompany.example.com + + + + + + IT + 06363391001 + + + YourCompany + + RF01 + + + Via Milano, 1 + 00100 + Roma + AK + IT + + + 06543534343 + info@yourcompany.example.com + + + + + + IT + 06363391001 + + 06363391001 + + Public Administration + + + + Via Roma, 1 + 10100 + Torino + AK + IT + + + + + + + TD01 + USD + 2021-12-16 + INV/2021/12/0001 + 16.38 + SI + + + + + 1 + Cabinet with Doors + 1.000 + Unit(s) + 14.00000 + 14.00 + 0.00 + N3.2 + + Valuta + USD + 16.38000 + 2021-12-16 + + + + 0.00 + N3.2 + 14.00 + 0.00 + Not subject to VAT law + + + + TP02 + + MP05 + 2022-01-31 + 16.38 + + + + diff --git a/l10n_it_fatturapa_out/tests/test_fatturapa_xml_validation.py b/l10n_it_fatturapa_out/tests/test_fatturapa_xml_validation.py index 1fa6396ffa04..09d59c457b4e 100644 --- a/l10n_it_fatturapa_out/tests/test_fatturapa_xml_validation.py +++ b/l10n_it_fatturapa_out/tests/test_fatturapa_xml_validation.py @@ -450,62 +450,6 @@ def test_8_xml_export(self): xml_content = base64.decodebytes(attachment.datas) self.check_content(xml_content, "IT06363391001_00008.xml") - def test_9_xml_export(self): - self.tax_22.price_include = True - self.set_sequences(18, "2018-01-07") - partner = self.res_partner_fatturapa_4 - partner.onchange_country_id_e_inv() - partner.write(partner._convert_to_write(partner._cache)) - self.assertEqual(partner.codice_destinatario, "XXXXXXX") - invoice = self.invoice_model.create( - { - "name": "INV/2018/0018", - "invoice_date": "2018-01-07", - "partner_id": partner.id, - "journal_id": self.sales_journal.id, - # "account_id": self.a_recv.id, - "invoice_payment_term_id": self.account_payment_term.id, - "user_id": self.user_demo.id, - "move_type": "out_invoice", - "currency_id": self.AED.id, - "invoice_line_ids": [ - ( - 0, - 0, - { - "account_id": self.a_sale.id, - "product_id": self.product_product_10.id, - "name": "Mouse Optical", - "quantity": 1, - "product_uom_id": self.product_uom_unit.id, - "price_unit": 10, - "tax_ids": [(6, 0, {self.tax_22.id})], - }, - ), - ( - 0, - 0, - { - "account_id": self.a_sale.id, - "product_id": self.product_order_01.id, - "name": "Zed+ Antivirus", - "quantity": 1, - "product_uom_id": self.product_uom_unit.id, - "price_unit": 4, - "tax_ids": [(6, 0, {self.tax_22.id})], - }, - ), - ], - } - ) - invoice._post() - res = self.run_wizard(invoice.id) - attachment = self.attach_model.browse(res["res_id"]) - self.set_e_invoice_file_id(attachment, "IT06363391001_00009.xml") - - xml_content = base64.decodebytes(attachment.datas) - self.check_content(xml_content, "IT06363391001_00009.xml") - def test_10_xml_export(self): # invoice with descriptive line self.set_sequences(10, "2019-08-07") @@ -747,6 +691,61 @@ def test_14_xml_export(self): xml_content = base64.decodebytes(attachment.datas) self.check_content(xml_content, "IT06363391001_00014.xml") + def test_15_xml_export(self): + """ + - create an invoice in USD + + expect an XML with values in EUR + """ + + usd = self.env.ref("base.USD") + + self.env["res.currency.rate"].create( + { + "name": fields.Date.from_string("2021-12-16"), + "rate": 1.17, + "currency_id": usd.id, + "company_id": self.env.company.id, + } + ) + + invoice_form = Form( + self.env["account.move"].with_context({"default_move_type": "out_invoice"}) + ) + invoice_form.currency_id = usd + invoice_form.partner_id = self.res_partner_fatturapa_0 + invoice_form.name = "INV/2021/12/0001" + invoice_form.date = fields.Date.from_string("2021-12-16") + invoice_form.invoice_date = fields.Date.from_string("2021-12-16") + invoice_form.invoice_payment_term_id = self.account_payment_term + + self.tax_00_ns.kind_id = self.env.ref("l10n_it_account_tax_kind.n3_2") + + with invoice_form.line_ids.new() as line_form: + line_form.product_id = self.product_product_10 + line_form.account_id = self.a_sale + line_form.tax_ids.clear() + line_form.tax_ids.add(self.tax_00_ns) + invoice = invoice_form.save() + invoice.action_post() + + invoice.company_id.xml_divisa_value = "force_eur" + res = self.run_wizard(invoice.id) + attachment = self.attach_model.browse(res["res_id"]) + self.set_e_invoice_file_id(attachment, "IT06363391001_00015.xml") + + xml_content = base64.decodebytes(attachment.datas) + self.check_content(xml_content, "IT06363391001_00015.xml") + attachment.unlink() + + invoice.company_id.xml_divisa_value = "keep_orig" + res = self.run_wizard(invoice.id) + attachment = self.attach_model.browse(res["res_id"]) + self.set_e_invoice_file_id(attachment, "IT06363391001_00016.xml") + + xml_content = base64.decodebytes(attachment.datas) + self.check_content(xml_content, "IT06363391001_00016.xml") + def test_no_tax_fail(self): """ - create an invoice with a product line without taxes diff --git a/l10n_it_fatturapa_out/views/company_view.xml b/l10n_it_fatturapa_out/views/company_view.xml index f50771ba8ac1..4af49e26c90a 100644 --- a/l10n_it_fatturapa_out/views/company_view.xml +++ b/l10n_it_fatturapa_out/views/company_view.xml @@ -15,10 +15,20 @@ position="after" >
-
+
+
diff --git a/l10n_it_fatturapa_out/wizard/efattura.py b/l10n_it_fatturapa_out/wizard/efattura.py index d288d9a2832f..00a15b4fadfc 100644 --- a/l10n_it_fatturapa_out/wizard/efattura.py +++ b/l10n_it_fatturapa_out/wizard/efattura.py @@ -99,7 +99,7 @@ def format_phone(number): return number return False - def format_price(line): + def format_price(line, original_currency=False): res = line.price_unit if line.tax_ids and line.tax_ids[0].price_include: res = line.price_unit / (1 + (line.tax_ids[0].amount / 100)) @@ -114,6 +114,10 @@ def format_price(line): if line.quantity < 0: res = -res + # force EUR unless we want the original currency + if not original_currency: + res = fpa_to_eur(res, line.move_id) + # XXX arrotondamento? res = "{prezzo:.{precision}f}".format(prezzo=res, precision=price_precision) return res @@ -258,6 +262,15 @@ def get_importo(line): return False return line.price_unit * line.discount / 100 + def fpa_to_eur(amount, invoice): + currency = invoice.currency_id + euro = self.env.ref("base.EUR") + if currency == euro: + return amount + return currency._convert( + amount, euro, invoice.company_id, invoice.date, False + ) + if self.partner_id.commercial_partner_id.is_pa: # check value code code = self.partner_id.ipa_code @@ -292,6 +305,7 @@ def get_importo(line): "all_taxes": { invoice.id: get_all_taxes(invoice) for invoice in self.invoices }, + "fpa_to_eur": fpa_to_eur, } return template_values