Skip to content

Commit

Permalink
[IMP] l10n_it_fatturapa_in: Computation of prices with many digits
Browse files Browse the repository at this point in the history
When price precision is increased during import, the price of the created lines should have been computed using the new precision
  • Loading branch information
SirAionTech committed Nov 26, 2024
1 parent c62d173 commit 6ba5e5b
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 5 deletions.
1 change: 1 addition & 0 deletions l10n_it_fatturapa_in/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import fields
from . import models
from . import wizard
47 changes: 47 additions & 0 deletions l10n_it_fatturapa_in/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2024 Simone Rubino - Aion Tech
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.fields import Float

orig_convert_to_cache = Float.convert_to_cache
orig_get_digits = Float.get_digits

E_INVOICE_PRECISION_TO_FIELD = {
"Discount": "discount_decimal_digits",
"Product Price": "price_decimal_digits",
"Product Unit of Measure": "quantity_decimal_digits",
}
# Map a `decimal.precision` to the name of the field in `fatturapa.attachment`
# that stores the value used during import


def get_digits(self, env):
digits = orig_get_digits(self, env)
if e_invoice_precision := env.context.get("l10n_it_fatturapa_in_precision"):
digits = digits[0], e_invoice_precision
return digits


def convert_to_cache(self, value, record, validate=True):
if record._name in ("account.move", "account.move.line"):
e_invoice = record.fatturapa_attachment_in_id
if e_invoice:
# The invoice [line] has been created by importing an e-invoice.
# If a different precision has been used,
# keep using that precision to read values that have it.
field_precision = self._digits
if isinstance(field_precision, str):
e_invoice_precision_field = E_INVOICE_PRECISION_TO_FIELD.get(
field_precision
)
if e_invoice_precision_field:
if e_invoice_precision := e_invoice[e_invoice_precision_field]:
record = record.with_context(
l10n_it_fatturapa_in_precision=e_invoice_precision
)

return orig_convert_to_cache(self, value, record, validate=validate)


Float.convert_to_cache = convert_to_cache
Float.get_digits = get_digits
18 changes: 18 additions & 0 deletions l10n_it_fatturapa_in/models/attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ class FatturaPAAttachmentIn(models.Model):
compute="_compute_linked_invoice_id_xml",
store=True,
)
price_decimal_digits = fields.Integer(
string="Prices decimal digits",
help="Value used during import of this e-invoice "
'to override "Product Price" precision.',
readonly=True,
)
quantity_decimal_digits = fields.Integer(
string="Quantities decimal digits",
help="Value used during import of this e-invoice "
'to override "Product Unit of Measure" precision.',
readonly=True,
)
discount_decimal_digits = fields.Integer(
string="Discounts decimal digits",
help="Value used during import of this e-invoice "
'to override "Discount" precision.',
readonly=True,
)

_sql_constraints = [
(
Expand Down
87 changes: 87 additions & 0 deletions l10n_it_fatturapa_in/tests/data/IT01234567890_FPR16.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<q1:FatturaElettronica xmlns:q1="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" versione="FPR12">
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>IT</IdPaese>
<IdCodice>02780790107</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>FPR14</ProgressivoInvio>
<FormatoTrasmissione>FPR12</FormatoTrasmissione>
<CodiceDestinatario>0000000</CodiceDestinatario>
<ContattiTrasmittente>
<Telefono>06543534343</Telefono>
<Email>[email protected]</Email>
</ContattiTrasmittente>
<PECDestinatario>[email protected]</PECDestinatario>
</DatiTrasmissione>
<CedentePrestatore>
<DatiAnagrafici>
<IdFiscaleIVA>
<IdPaese>IT</IdPaese>
<IdCodice>02780790107</IdCodice>
</IdFiscaleIVA>
<Anagrafica>
<Denominazione>YourCompany</Denominazione>
</Anagrafica>
<RegimeFiscale>RF01</RegimeFiscale>
</DatiAnagrafici>
<Sede>
<Indirizzo>Via Milano, 1</Indirizzo>
<CAP>00100</CAP>
<Comune>Roma</Comune>
<Provincia>AK</Provincia>
<Nazione>IT</Nazione>
</Sede>
<Contatti>
<Telefono>06543534343</Telefono>
<Email>[email protected]</Email>
</Contatti>
</CedentePrestatore>
<CessionarioCommittente>
<DatiAnagrafici>
<IdFiscaleIVA>
<IdPaese>IT</IdPaese>
<IdCodice>07973780013</IdCodice>
</IdFiscaleIVA>
<CodiceFiscale>07973780013</CodiceFiscale>
<Anagrafica>
<Denominazione>B2B Customer</Denominazione>
</Anagrafica>
</DatiAnagrafici>
<Sede>
<Indirizzo>Via Roma, 1</Indirizzo>
<CAP>16100</CAP>
<Comune>Genova</Comune>
<Provincia>AK</Provincia>
<Nazione>IT</Nazione>
</Sede>
</CessionarioCommittente>
</FatturaElettronicaHeader>
<FatturaElettronicaBody>
<DatiGenerali>
<DatiGeneraliDocumento>
<TipoDocumento>TD01</TipoDocumento>
<Divisa>EUR</Divisa>
<Data>2020-09-30</Data>
<Numero>14481</Numero>
<ImportoTotaleDocumento>81.49</ImportoTotaleDocumento>
</DatiGeneraliDocumento>
</DatiGenerali>
<DatiBeniServizi>
<DettaglioLinee>
<NumeroLinea>1</NumeroLinea>
<Descrizione>Test precisione decimale</Descrizione>
<Quantita>69.00</Quantita>
<PrezzoUnitario>0.968</PrezzoUnitario>
<PrezzoTotale>66.792</PrezzoTotale>
<AliquotaIVA>22.00</AliquotaIVA>
</DettaglioLinee>
<DatiRiepilogo>
<AliquotaIVA>22.00</AliquotaIVA>
<ImponibileImporto>66.79</ImponibileImporto>
<Imposta>14.69</Imposta>
</DatiRiepilogo>
</DatiBeniServizi>
</FatturaElettronicaBody>
</q1:FatturaElettronica>
4 changes: 4 additions & 0 deletions l10n_it_fatturapa_in/tests/fatturapa_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ def run_wizard(
):
if module_name is None:
module_name = "l10n_it_fatturapa_in"
if wiz_values is None:
wiz_values = dict()
attach = self.create_attachment(name, file_name, module_name=module_name)
attach.e_invoice_received_date = fields.Datetime.now()
attach_id = attach.id
Expand All @@ -297,6 +299,8 @@ def run_wizard(
active_ids=[attach_id], active_model="fatturapa.attachment.in"
)
)
for wiz_field, wiz_value in wiz_values.items():
setattr(wizard_form, wiz_field, wiz_value)
wizard = wizard_form.save()
return wizard.importFatturaPA()
if mode == "link":
Expand Down
59 changes: 59 additions & 0 deletions l10n_it_fatturapa_in/tests/test_import_fatturapa_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,65 @@ def test_ignore_global_discount(self):
self.assertEqual(invoice.amount_tax, 5.12)
self.assertEqual(invoice.amount_total, 28.39)

def test_increased_decimal_precision(self):
"""
Increase price decimal precision during import:
computation of line's price is more accurate.
"""
res = self.run_wizard(
"increased_decimal_precision",
"IT01234567890_FPR16.xml",
wiz_values={
"price_decimal_digits": 3,
},
)

# The new precision allows to compute the correct amount
invoice = self.invoice_model.search(res["domain"])
expected_invoice_values = {
"amount_untaxed": 66.79,
"amount_tax": 14.69,
"amount_total": 81.48,
}
self.assertRecordValues(
invoice,
[
expected_invoice_values,
],
)
invoice_line = invoice.invoice_line_ids
expected_invoice_line_values = {
"price_subtotal": 66.79,
"price_total": 81.48,
}
self.assertRecordValues(
invoice_line,
[
expected_invoice_line_values,
],
)

# Trigger amounts recomputation because:
# date triggers an update on date_due
# date_due triggers an update on needed_terms
# needed_terms needs amount_total_signed
with Form(invoice) as invoice_form:
invoice_form.date = fields.Date.today()

# The correct amount is kept
self.assertRecordValues(
invoice,
[
expected_invoice_values,
],
)
self.assertRecordValues(
invoice_line,
[
expected_invoice_line_values,
],
)


class TestFatturaPAEnasarco(FatturapaCommon):
def setUp(self):
Expand Down
21 changes: 16 additions & 5 deletions l10n_it_fatturapa_in/wizard/wizard_import_fatturapa.py
Original file line number Diff line number Diff line change
Expand Up @@ -1786,7 +1786,7 @@ def create_and_get_line_id(self, invoice_line_ids, invoice_line_model, upd_vals)
)
invoice_line_ids.append(invoice_line_id)

def _set_decimal_precision(self, precision_name, field_name):
def _set_decimal_precision(self, precision_name, field_name, attachments):
precision = self.env["decimal.precision"].search(
[("name", "=", precision_name)], limit=1
)
Expand All @@ -1796,6 +1796,11 @@ def _set_decimal_precision(self, precision_name, field_name):
different_precisions = self[field_name] != original_precision
if different_precisions:
precision.sudo().digits = self[field_name]
attachments.update(
{
field_name: self[field_name],
}
)
return precision, different_precisions, original_precision

def _restore_original_precision(self, precision, original_precision):
Expand All @@ -1808,28 +1813,34 @@ def _get_invoice_partner_id(self, fatt):

def importFatturaPA(self):
self.ensure_one()
fatturapa_attachments = self._get_selected_records()

(
price_precision,
different_price_precisions,
original_price_precision,
) = self._set_decimal_precision("Product Price", "price_decimal_digits")
) = self._set_decimal_precision(
"Product Price", "price_decimal_digits", attachments=fatturapa_attachments
)
(
qty_precision,
different_qty_precisions,
original_qty_precision,
) = self._set_decimal_precision(
"Product Unit of Measure", "quantity_decimal_digits"
"Product Unit of Measure",
"quantity_decimal_digits",
attachments=fatturapa_attachments,
)
(
discount_precision,
different_discount_precisions,
original_discount_precision,
) = self._set_decimal_precision("Discount", "discount_decimal_digits")
) = self._set_decimal_precision(
"Discount", "discount_decimal_digits", attachments=fatturapa_attachments
)

new_invoices = []
# convert to dict in order to be able to modify context
fatturapa_attachments = self._get_selected_records()
self.env.context = dict(self.env.context)
for fatturapa_attachment in fatturapa_attachments:
self.reset_inconsistencies()
Expand Down

0 comments on commit 6ba5e5b

Please sign in to comment.