Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions l10n_es_aeat_sii_oca/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ def _get_sii_tax_dict(self, tax_line, tax_lines):
if req_tax:
tax_dict["TipoRecargoEquivalencia"] = req_tax.amount
tax_dict["CuotaRecargoEquivalencia"] = tax_lines[req_tax]["amount"]
tax_dict = self._clean_sii_tax_dict(tax, self.move_type, tax_dict)
return tax_dict

def _get_document_amount_total(self):
Expand Down
40 changes: 38 additions & 2 deletions l10n_es_aeat_sii_oca/models/sii_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from odoo import _, api, exceptions, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo.modules.registry import Registry
from odoo.tools.float_utils import float_compare
from odoo.tools.float_utils import float_compare, float_is_zero

from odoo.addons.l10n_es_aeat.models.aeat_mixin import round_by_keys

Expand Down Expand Up @@ -422,7 +422,8 @@ def _get_sii_tax_dict(self, tax_line, tax_lines):
else:
tax_type = abs(tax.amount)
tax_dict = {"TipoImpositivo": str(tax_type), "BaseImponible": tax_base_amount}
if self._get_mapping_key() in ["out_invoice", "out_refund"]:
mapping_key = self._get_mapping_key()
if mapping_key in ["out_invoice", "out_refund"]:
key = "CuotaRepercutida"
else:
key = "CuotaSoportada"
Expand All @@ -432,6 +433,7 @@ def _get_sii_tax_dict(self, tax_line, tax_lines):
if req_tax:
tax_dict["TipoRecargoEquivalencia"] = req_tax.amount
tax_dict["CuotaRecargoEquivalencia"] = tax_lines[req_tax]["amount"]
tax_dict = self._clean_sii_tax_dict(tax, mapping_key, tax_dict)
return tax_dict

def _get_no_taxable_cause(self):
Expand Down Expand Up @@ -741,6 +743,40 @@ def _get_aeat_invoice_dict(self):
)
return inv_dict

def _clean_sii_tax_dict(self, tax, move_type, tax_dict):
"""
Clean tax dict for corner cases that produces SII rejections.
:param tax: tax record
:param move_type: invoice move type
:param tax_dict: tax dict to clean
:return: cleaned tax dict

Corner case 1:
- document with amount_total 0.0
- amount_untaxed -0.1 and amount_tax 0.1 or
0.1 amount_untaxed and -0.1 amount_tax due to rounding issues.
(example in test_get_invoice_data_tax_price_included_corner_case)
It should be sent with 0.0 values to avoid SII rejection with error:
1231:'El campo CuotaRepercutida y BaseImponible deben tener el mismo signo.'
"""
if tax.price_include:
base_amount = round(tax_dict.get("BaseImponible", 0.0), 2)
key = (
"CuotaRepercutida"
if move_type in ["out_invoice", "out_refund"]
else "CuotaSoportada"
)
tax_amount = round(tax_dict.get(key, 0.0), 2)

if (
float_compare(abs(base_amount), 0.01, precision_digits=2) == 0
and float_compare(abs(tax_amount), 0.01, precision_digits=2) == 0
and float_is_zero(base_amount + tax_amount, precision_digits=2)
):
tax_dict[key] = 0.0
tax_dict["BaseImponible"] = 0.0
return tax_dict

def _get_account_registration_date(self):
"""Hook method to allow the setting of the account registration date
of each supplier invoice. The SII recommends to set the send date as
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"IDFactura": {
"IDEmisorFactura": {"NIF": "U2687761C"},
"NumSerieFacturaEmisor": "TEST001",
"FechaExpedicionFacturaEmisor": "01-01-2020"
},
"PeriodoLiquidacion": {"Ejercicio": 2020, "Periodo": "01"},
"FacturaExpedida": {
"TipoFactura": "F1",
"ClaveRegimenEspecialOTrascendencia": "01",
"DescripcionOperacion": "/",
"TipoDesglose": {
"DesgloseTipoOperacion": {
"PrestacionServicios": {
"Sujeta": {
"NoExenta": {
"TipoNoExenta": "S1",
"DesgloseIVA": {
"DetalleIVA": [
{
"TipoImpositivo": "21.0",
"BaseImponible": 0.0,
"CuotaRepercutida": 0.0
}
]
}
}
}
}
}
},
"ImporteTotal": 0.0,
"Contraparte": {"NombreRazon": "Test partner", "NIF": "F35999705"}
}
}
32 changes: 32 additions & 0 deletions l10n_es_aeat_sii_oca/tests/test_l10n_es_aeat_sii.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,3 +545,35 @@ def test_start_date(self):
self.company.sii_start_date = False
self.assertTrue(invoice2.sii_enabled)
self.assertTrue(invoice2.filtered_domain([("sii_enabled", "=", True)]))

def test_get_invoice_data_tax_price_included_corner_case(self):
xml_id = "l10n_es.{}_account_tax_template_{}".format(
self.company.id, "s_iva21s"
)
tax = self.env.ref(xml_id)
tax.price_include = True
mapping = [
(
"out_invoice",
[
(-45, ["s_iva21s"]),
(15, ["s_iva21s"]),
(15, ["s_iva21s"]),
(15, ["s_iva21s"]),
],
{},
),
(
"out_invoice",
[
(45, ["s_iva21s"]),
(-15, ["s_iva21s"]),
(-15, ["s_iva21s"]),
(-15, ["s_iva21s"]),
],
{},
),
]
for inv_type, lines, extra_vals in mapping:
self._create_and_test_invoice_sii_dict(inv_type, lines, extra_vals)
return