diff --git a/l10n_it_fatturapa_in/models/account.py b/l10n_it_fatturapa_in/models/account.py
index 651824151643..a09ec93ba744 100644
--- a/l10n_it_fatturapa_in/models/account.py
+++ b/l10n_it_fatturapa_in/models/account.py
@@ -179,10 +179,13 @@ def remove_attachment_link(self):
return {'type': 'ir.actions.client', 'tag': 'reload'}
@api.model
- def compute_xml_amount_untaxed(self, DatiRiepilogo):
- amount_untaxed = 0.0
- for Riepilogo in DatiRiepilogo:
- amount_untaxed += float(Riepilogo.ImponibileImporto)
+ def compute_xml_amount_untaxed(self, FatturaBody):
+ amount_untaxed = float(
+ FatturaBody.DatiGenerali.DatiGeneraliDocumento.Arrotondamento
+ or 0.0)
+ for Riepilogo in FatturaBody.DatiBeniServizi.DatiRiepilogo:
+ rounding = float(Riepilogo.Arrotondamento or 0.0)
+ amount_untaxed += float(Riepilogo.ImponibileImporto) + rounding
return amount_untaxed
@api.model
@@ -194,8 +197,7 @@ def compute_xml_amount_tax(self, DatiRiepilogo):
def set_einvoice_data(self, fattura):
self.ensure_one()
- amount_untaxed = self.compute_xml_amount_untaxed(
- fattura.DatiBeniServizi.DatiRiepilogo)
+ amount_untaxed = self.compute_xml_amount_untaxed(fattura)
amount_tax = self.compute_xml_amount_tax(
fattura.DatiBeniServizi.DatiRiepilogo)
amount_total = float(
diff --git a/l10n_it_fatturapa_in/models/company.py b/l10n_it_fatturapa_in/models/company.py
index 5b1dac6da8e7..6f26694fa03b 100644
--- a/l10n_it_fatturapa_in/models/company.py
+++ b/l10n_it_fatturapa_in/models/company.py
@@ -1,9 +1,10 @@
-from odoo import fields, models, api
+from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
+
cassa_previdenziale_product_id = fields.Many2one(
'product.product', 'Welfare Fund Data Product',
help="Product used to model DatiCassaPrevidenziale XML element "
@@ -12,38 +13,45 @@ class ResCompany(models.Model):
sconto_maggiorazione_product_id = fields.Many2one(
'product.product', 'Discount Supplement Product',
help="Product used to model ScontoMaggiorazione XML element on bills."
- )
+ )
+
+ arrotondamenti_attivi_account_id = fields.Many2one(
+ 'account.account', 'Round Up Account',
+ domain=[('deprecated', '=', False)],
+ help="Account used to round up bills amount."
+ )
+ arrotondamenti_passivi_account_id = fields.Many2one(
+ 'account.account', 'Round Down Account',
+ domain=[('deprecated', '=', False)],
+ help="Account used to round down bills amount."
+ )
+ arrotondamenti_tax_id = fields.Many2one(
+ 'account.tax', 'Rounding Tax',
+ domain=[('type_tax_use', '=', 'purchase'), ('amount', '=', 0.0)],
+ help="Tax used to both round up and down bills amount."
+ )
class AccountConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
+
cassa_previdenziale_product_id = fields.Many2one(
related='company_id.cassa_previdenziale_product_id',
- string="Welfare Fund Data Product",
- help="Product used to model DatiCassaPrevidenziale XML element "
- "on bills.", readonly=False
+ readonly=False
)
sconto_maggiorazione_product_id = fields.Many2one(
related='company_id.sconto_maggiorazione_product_id',
- string="Discount Supplement Product",
- help='Product used to model ScontoMaggiorazione XML element on bills',
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.cassa_previdenziale_product_id = (
- company.cassa_previdenziale_product_id and
- company.cassa_previdenziale_product_id.id or False
- )
- self.sconto_maggiorazione_product_id = (
- company.sconto_maggiorazione_product_id and
- company.sconto_maggiorazione_product_id.id or False
- )
- else:
- self.cassa_previdenziale_product_id = False
- self.sconto_maggiorazione_product_id = False
- return res
+ )
+ arrotondamenti_attivi_account_id = fields.Many2one(
+ related='company_id.arrotondamenti_attivi_account_id',
+ readonly=False
+ )
+ arrotondamenti_passivi_account_id = fields.Many2one(
+ related='company_id.arrotondamenti_passivi_account_id',
+ readonly=False
+ )
+ arrotondamenti_tax_id = fields.Many2one(
+ related='company_id.arrotondamenti_tax_id',
+ readonly=False
+ )
diff --git a/l10n_it_fatturapa_in/readme/ROADMAP.rst b/l10n_it_fatturapa_in/readme/ROADMAP.rst
new file mode 100644
index 000000000000..9ec04c0ccbb1
--- /dev/null
+++ b/l10n_it_fatturapa_in/readme/ROADMAP.rst
@@ -0,0 +1,19 @@
+Il modulo contiene un cambiamento alla firma di un metodo in ``models/account.py``
+il quale cambia da
+
+``compute_xml_amount_untaxed(self, DatiRiepilogo)``
+
+a
+
+``compute_xml_amount_untaxed(self, FatturaBody)``
+
+Il cambiamento è dovuto all'implementazione della gestione degli arrotondamenti
+che posso essere presenti in 2 sezioni diverse del file XML della fattura elettronica.
+
+La soluzione ottimale è stata di cambiare la firma del metodo per consentire
+la visibilità delle sezioni ``FatturaElettronicaBody.DatiBeniServizi.DatiRiepilogo`` e
+``FatturaElettronicaBody.DatiGenerali.DatiGeneraliDocumento`` dove è presente il nodo ``Arrotondamento``
+
+Pertanto, al fine di ottenere il corretto valore del totale imponibile, i moduli che
+avessero ridefinito il metodo ``compute_xml_amount_untaxed`` nel modello ``account.invoice``
+dovranno adeguare la chiamata al metodo stesso preoccupandosi di utilizzare come primo parametro l'oggetto ``FatturaElettronicaBody``.
\ No newline at end of file
diff --git a/l10n_it_fatturapa_in/tests/data/IT05979361218_012.xml b/l10n_it_fatturapa_in/tests/data/IT05979361218_012.xml
new file mode 100644
index 000000000000..84f640e0730d
--- /dev/null
+++ b/l10n_it_fatturapa_in/tests/data/IT05979361218_012.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+ IT
+ 05979361218
+
+ 006
+ FPA12
+ UFPQ1O
+
+
+
+
+ IT
+ 05979361218
+
+
+ SOCIETA' ALPHA BETA SRL
+
+ RF02
+
+
+ VIALE ROMA 543B
+ 07100
+ SASSARI
+ SS
+ IT
+
+
+
+
+ 80213330584
+
+ AMMINISTRAZIONE BETA
+
+
+
+ VIA TORINO 38-B
+ 00145
+ ROMA
+ RM
+ IT
+
+
+
+
+
+
+ TD01
+ EUR
+ 2019-05-11
+ 852S1
+ 34.32
+ Rif ordine 908
+
+
+
+
+ 1
+ USB4
+ 1.00
+ Pz.
+ 18.07
+ 18.07
+ 0.00
+ N4
+
+
+ 2
+ USB
+ 1.00
+ Pz.
+ 16.60
+ 16.60
+ 0.00
+ N4
+
+
+ 0.00
+ N4
+ -0.35
+ 34.67
+ 0.00
+ I
+ Esenzione Art.8 comma 1 DPR 633/72
+
+
+
+
diff --git a/l10n_it_fatturapa_in/tests/data/IT05979361218_013.xml b/l10n_it_fatturapa_in/tests/data/IT05979361218_013.xml
new file mode 100644
index 000000000000..2ade52ad22b1
--- /dev/null
+++ b/l10n_it_fatturapa_in/tests/data/IT05979361218_013.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+ IT
+ 05979361218
+
+ 006
+ FPA12
+ UFPQ1O
+
+
+
+
+ IT
+ 05979361218
+
+
+ SOCIETA' ALPHA BETA SRL
+
+ RF02
+
+
+ VIALE ROMA 543B
+ 07100
+ SASSARI
+ SS
+ IT
+
+
+
+
+ 80213330584
+
+ AMMINISTRAZIONE BETA
+
+
+
+ VIA TORINO 38-B
+ 00145
+ ROMA
+ RM
+ IT
+
+
+
+
+
+
+ TD01
+ EUR
+ 2019-05-11
+ 852S1
+ 34.32
+ -0.35
+ Rif ordine 908
+
+
+
+
+ 1
+ USB4
+ 1.00
+ Pz.
+ 18.07
+ 18.07
+ 0.00
+ N4
+
+
+ 2
+ USB
+ 1.00
+ Pz.
+ 16.60
+ 16.60
+ 0.00
+ N4
+
+
+ 0.00
+ N4
+ 34.67
+ 0.00
+ I
+ Esenzione Art.8 comma 1 DPR 633/72
+
+
+
+
diff --git a/l10n_it_fatturapa_in/tests/fatturapa_common.py b/l10n_it_fatturapa_in/tests/fatturapa_common.py
index d903f23fa5f5..10ffcbac31f7 100644
--- a/l10n_it_fatturapa_in/tests/fatturapa_common.py
+++ b/l10n_it_fatturapa_in/tests/fatturapa_common.py
@@ -84,3 +84,18 @@ def setUp(self):
self.imac = self.env.ref(
'product.product_product_8_product_template')
self.service = self.env.ref('product.product_product_1')
+ arrotondamenti_attivi_account_id = self.env['account.account'].\
+ search([('user_type_id', '=', self.env.ref(
+ 'account.data_account_type_other_income').id)], limit=1).id
+ arrotondamenti_passivi_account_id = self.env['account.account'].\
+ search([('user_type_id', '=', self.env.ref(
+ 'account.data_account_type_direct_costs').id)], limit=1).id
+ arrotondamenti_tax_id = self.env['account.tax'].search(
+ [('type_tax_use', '=', 'purchase'),
+ ('amount', '=', 0.0)], order='sequence', limit=1)
+ self.env.user.company_id.arrotondamenti_attivi_account_id = (
+ arrotondamenti_attivi_account_id)
+ self.env.user.company_id.arrotondamenti_passivi_account_id = (
+ arrotondamenti_passivi_account_id)
+ self.env.user.company_id.arrotondamenti_tax_id = (
+ arrotondamenti_tax_id)
diff --git a/l10n_it_fatturapa_in/tests/test_import_fatturapa_xml.py b/l10n_it_fatturapa_in/tests/test_import_fatturapa_xml.py
index 4317e8c1dc8a..810961a789ea 100644
--- a/l10n_it_fatturapa_in/tests/test_import_fatturapa_xml.py
+++ b/l10n_it_fatturapa_in/tests/test_import_fatturapa_xml.py
@@ -478,6 +478,22 @@ def test_23_xml_import(self):
invoices = self.invoice_model.browse(invoice_ids)
self.assertEqual(len(invoices), 2)
+ def test_24_xml_import(self):
+ res = self.run_wizard('test24', 'IT05979361218_012.xml')
+ invoice_id = res.get('domain')[0][2][0]
+ invoice = self.invoice_model.browse(invoice_id)
+ self.assertAlmostEqual(invoice.e_invoice_amount_untaxed, 34.32)
+ self.assertEqual(invoice.e_invoice_amount_tax, 0.0)
+ self.assertEqual(invoice.e_invoice_amount_total, 34.32)
+
+ def test_25_xml_import(self):
+ res = self.run_wizard('test25', 'IT05979361218_013.xml')
+ invoice_id = res.get('domain')[0][2][0]
+ invoice = self.invoice_model.browse(invoice_id)
+ self.assertAlmostEqual(invoice.e_invoice_amount_untaxed, 34.32)
+ self.assertEqual(invoice.e_invoice_amount_tax, 0.0)
+ self.assertEqual(invoice.e_invoice_amount_total, 34.32)
+
def test_30_xml_import(self):
self.env.user.company_id.cassa_previdenziale_product_id = (
self.service.id)
diff --git a/l10n_it_fatturapa_in/views/company_view.xml b/l10n_it_fatturapa_in/views/company_view.xml
index 6ba336c43839..2b1957c986cb 100644
--- a/l10n_it_fatturapa_in/views/company_view.xml
+++ b/l10n_it_fatturapa_in/views/company_view.xml
@@ -27,6 +27,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/l10n_it_fatturapa_in/wizard/link_to_existing_invoice.py b/l10n_it_fatturapa_in/wizard/link_to_existing_invoice.py
index 3a4dce94a2af..9d0b8bbe5ff8 100644
--- a/l10n_it_fatturapa_in/wizard/link_to_existing_invoice.py
+++ b/l10n_it_fatturapa_in/wizard/link_to_existing_invoice.py
@@ -104,7 +104,7 @@ def _get_default_lines_vals(self, attachment):
bill_nbr=dati_generali_documento.Numero,
bill_date=dati_generali_documento.Data,
bill_no_tax=invoice_model.compute_xml_amount_untaxed(
- dati_riepilogo),
+ FatturaBody),
bill_tax=invoice_model.compute_xml_amount_tax(
dati_riepilogo)
),
diff --git a/l10n_it_fatturapa_in/wizard/wizard_import_fatturapa.py b/l10n_it_fatturapa_in/wizard/wizard_import_fatturapa.py
index 1c4a277b3abc..15908dc5ea48 100644
--- a/l10n_it_fatturapa_in/wizard/wizard_import_fatturapa.py
+++ b/l10n_it_fatturapa_in/wizard/wizard_import_fatturapa.py
@@ -964,6 +964,8 @@ def invoiceCreate(
self._addGlobalDiscount(
invoice_id, FatturaBody.DatiGenerali.DatiGeneraliDocumento)
+ self.set_roundings(FatturaBody, invoice)
+
# compute the invoice
invoice.compute_taxes()
return invoice_id
@@ -1044,6 +1046,58 @@ def set_art73(self, FatturaBody, invoice_data):
if FatturaBody.DatiGenerali.DatiGeneraliDocumento.Art73:
invoice_data['art73'] = True
+ def set_roundings(self, FatturaBody, invoice):
+ rounding = 0.0
+ if FatturaBody.DatiBeniServizi.DatiRiepilogo:
+ for summary in FatturaBody.DatiBeniServizi.DatiRiepilogo:
+ rounding += float(summary.Arrotondamento or 0.0)
+ if FatturaBody.DatiGenerali.DatiGeneraliDocumento:
+ summary = FatturaBody.DatiGenerali.DatiGeneraliDocumento
+ rounding += float(summary.Arrotondamento or 0.0)
+
+ if rounding:
+ arrotondamenti_attivi_account_id = self.env.user.company_id.\
+ arrotondamenti_attivi_account_id
+ if not arrotondamenti_attivi_account_id:
+ raise UserError(_("Round up account is not set "
+ "in Accounting Settings"))
+
+ arrotondamenti_passivi_account_id = self.env.user.company_id.\
+ arrotondamenti_passivi_account_id
+ if not arrotondamenti_passivi_account_id:
+ raise UserError(_("Round down account is not set "
+ "in Accounting Settings"))
+
+ arrotondamenti_tax_id = self.env.user.company_id.\
+ arrotondamenti_tax_id
+ if not arrotondamenti_tax_id:
+ self.log_inconsistency(
+ _('Round up and down tax is not set')
+ )
+
+ line_vals = {}
+ if rounding > 0.0:
+ line_vals = {
+ 'invoice_id': invoice.id,
+ 'name': _("Rounding down"),
+ 'account_id': arrotondamenti_passivi_account_id.id,
+ 'price_unit': rounding,
+ 'invoice_line_tax_ids':
+ [(6, 0, [arrotondamenti_tax_id.id])],
+ }
+ elif rounding < 0.0:
+ line_vals = {
+ 'invoice_id': invoice.id,
+ 'name': _("Rounding up"),
+ 'account_id': arrotondamenti_attivi_account_id.id,
+ 'price_unit': rounding,
+ 'invoice_line_tax_ids':
+ [(6, 0, [arrotondamenti_tax_id.id])],
+ }
+
+ if line_vals:
+ self.env['account.invoice.line'].create(line_vals)
+
def set_efatt_rounding(self, FatturaBody, invoice_data):
if FatturaBody.DatiGenerali.DatiGeneraliDocumento.Arrotondamento:
invoice_data['efatt_rounding'] = float(
@@ -1267,7 +1321,7 @@ def check_invoice_amount(self, invoice, FatturaElettronicaBody):
# because otherwise DatiRiepilogo and odoo invoice total would
# differ
amount_untaxed = invoice.compute_xml_amount_untaxed(
- FatturaElettronicaBody.DatiBeniServizi.DatiRiepilogo)
+ FatturaElettronicaBody)
if not float_is_zero(
invoice.amount_untaxed-amount_untaxed, precision_digits=2
):