[FIX] account_edi_ubl_cii: fix peppol fields computes & update BE EAS
Replace every mentions of 9925 to 0208 for Belgian companies (public administration also have this 10 digits number). The EAS 0208 corresponds to the company_registry. Introduce a mechanism to validate the `peppol_endpoint` and refactor the computes for the `peppol_endpoint` and `peppol_eas` fields. See: https://openpeppol.atlassian.net/wiki/spaces/Belgium/overview task-3297311 closes odoo/odoo#138343 X-original-commit: 744bfa9e5f087a2aa9d714351a559c3320ecfda4 Signed-off-by: Laurent Smet (las) <las@odoo.com> Signed-off-by: Julien Van Roy (juvr) <juvr@odoo.com>
This commit is contained in:
@@ -780,6 +780,21 @@ msgstr ""
|
||||
msgid "Tax '%s' is invalid: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_edi_ubl_cii
|
||||
#. odoo-python
|
||||
#: code:addons/account_edi_ubl_cii/models/res_partner.py:0
|
||||
#, python-format
|
||||
msgid "The Peppol endpoint is not valid. The expected format is: 0239843188"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_edi_ubl_cii
|
||||
#. odoo-python
|
||||
#: code:addons/account_edi_ubl_cii/models/res_partner.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The Peppol endpoint is not valid. The expected format is: 73282932000074"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_edi_ubl_cii
|
||||
#. odoo-python
|
||||
#: code:addons/account_edi_ubl_cii/models/account_edi_xml_ubl_bis3.py:0
|
||||
|
||||
@@ -44,7 +44,7 @@ EAS_MAPPING = {
|
||||
'AT': {'9915': 'vat'},
|
||||
'AU': {'0151': 'vat'},
|
||||
'BA': {'9924': 'vat'},
|
||||
'BE': {'9925': 'vat', '0208': 'company_registry'},
|
||||
'BE': {'0208': 'company_registry'},
|
||||
'BG': {'9926': 'vat'},
|
||||
'CH': {'9927': 'vat'},
|
||||
'CY': {'9928': 'vat'},
|
||||
@@ -54,7 +54,7 @@ EAS_MAPPING = {
|
||||
'EE': {'9931': 'vat'},
|
||||
'ES': {'9920': 'vat'},
|
||||
'FI': {'0213': 'vat'},
|
||||
'FR': {'9957': 'vat', '0009': 'siret'},
|
||||
'FR': {'0009': 'siret', '9957': 'vat'},
|
||||
'SG': {'0195': 'l10n_sg_unique_entity_number'},
|
||||
'GB': {'9932': 'vat'},
|
||||
'GR': {'9933': 'vat'},
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import models, fields, api
|
||||
import re
|
||||
from stdnum.fr import siret
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.addons.account_edi_ubl_cii.models.account_edi_common import EAS_MAPPING
|
||||
|
||||
|
||||
@@ -121,6 +125,14 @@ class ResPartner(models.Model):
|
||||
]
|
||||
)
|
||||
|
||||
@api.constrains('peppol_endpoint')
|
||||
def _check_peppol_fields(self):
|
||||
for partner in self:
|
||||
if partner.peppol_endpoint and partner.peppol_eas:
|
||||
error = self._build_error_peppol_endpoint(partner.peppol_eas, partner.peppol_endpoint)
|
||||
if error:
|
||||
raise ValidationError(error)
|
||||
|
||||
@api.depends('country_code')
|
||||
def _compute_ubl_cii_format(self):
|
||||
for partner in self:
|
||||
@@ -139,35 +151,45 @@ class ResPartner(models.Model):
|
||||
else:
|
||||
partner.ubl_cii_format = partner.ubl_cii_format
|
||||
|
||||
@api.depends('country_code')
|
||||
@api.depends('peppol_eas')
|
||||
def _compute_peppol_endpoint(self):
|
||||
""" If the EAS changes and a valid endpoint is available, set it. Otherwise, keep the existing value."""
|
||||
for partner in self:
|
||||
if partner.ubl_cii_format != 'facturx' and partner.country_code in EAS_MAPPING:
|
||||
eas_to_field = EAS_MAPPING[partner.country_code]
|
||||
# Try to set both the peppol_eas and the peppol_endpoint
|
||||
for field_name in eas_to_field.values():
|
||||
if field_name and field_name in partner._fields and partner[field_name]:
|
||||
partner.peppol_endpoint = partner[field_name]
|
||||
# If it's not possible to set the peppol_endpoint, just set the peppol_eas
|
||||
if not partner.peppol_endpoint:
|
||||
partner.peppol_endpoint = partner.peppol_endpoint
|
||||
else:
|
||||
partner.peppol_endpoint = partner.peppol_endpoint
|
||||
partner.peppol_endpoint = partner.peppol_endpoint
|
||||
if partner.country_code in EAS_MAPPING:
|
||||
field = EAS_MAPPING[partner.country_code].get(partner.peppol_eas)
|
||||
if field \
|
||||
and field in partner._fields \
|
||||
and partner[field] \
|
||||
and not partner._build_error_peppol_endpoint(partner.peppol_eas, partner[field]):
|
||||
partner.peppol_endpoint = partner[field]
|
||||
|
||||
@api.depends('country_code')
|
||||
def _compute_peppol_eas(self):
|
||||
"""
|
||||
If the country_code changes, recompute the EAS only if there is a country_code, it exists in the
|
||||
EAS_MAPPING, and the current EAS is not consistent with the new country_code.
|
||||
"""
|
||||
for partner in self:
|
||||
if partner.ubl_cii_format != 'facturx' and partner.country_code in EAS_MAPPING:
|
||||
partner.peppol_eas = partner.peppol_eas
|
||||
if partner.country_code and partner.country_code in EAS_MAPPING:
|
||||
eas_to_field = EAS_MAPPING[partner.country_code]
|
||||
# Try to set both the peppol_eas and the peppol_endpoint
|
||||
for eas, field_name in eas_to_field.items():
|
||||
if field_name in partner._fields and partner[field_name]:
|
||||
partner.peppol_eas = eas
|
||||
# If it's not possible to set the peppol_endpoint, just set the peppol_eas
|
||||
if not partner.peppol_eas:
|
||||
partner.peppol_eas = list(eas_to_field.keys())[0]
|
||||
else:
|
||||
partner.peppol_eas = partner.peppol_eas
|
||||
if partner.peppol_eas not in eas_to_field.keys():
|
||||
new_eas = list(EAS_MAPPING[partner.country_code].keys())[0]
|
||||
# Iterate on the possible EAS until a valid one is found
|
||||
for eas, field in eas_to_field.items():
|
||||
if field and field in partner._fields and partner[field]:
|
||||
if not partner._build_error_peppol_endpoint(eas, partner[field]):
|
||||
new_eas = eas
|
||||
break
|
||||
partner.peppol_eas = new_eas
|
||||
|
||||
def _build_error_peppol_endpoint(self, eas, endpoint):
|
||||
""" This function contains all the rules regarding the peppol_endpoint."""
|
||||
if eas == '0208' and not re.match(r"^\d{10}$", endpoint):
|
||||
return _("The Peppol endpoint is not valid. The expected format is: 0239843188")
|
||||
if eas == '0009' and not siret.is_valid(endpoint):
|
||||
return _("The Peppol endpoint is not valid. The expected format is: 73282932000074")
|
||||
|
||||
def _get_edi_builder(self):
|
||||
self.ensure_one()
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import test_partner_peppol_fields
|
||||
@@ -0,0 +1,80 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from contextlib import contextmanager
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAccountUblCii(AccountTestInvoicingCommon):
|
||||
|
||||
@contextmanager
|
||||
def check_peppol_vals(self, partner, expected, reset=True):
|
||||
if reset:
|
||||
partner.write({
|
||||
'country_id': False,
|
||||
'peppol_eas': False,
|
||||
'peppol_endpoint': False,
|
||||
})
|
||||
yield
|
||||
partner.country_id = self.env.ref('base.dk')
|
||||
self.assertEqual((partner.peppol_eas, partner.peppol_endpoint), expected)
|
||||
|
||||
def _build_error_peppol_endpoint(self, eas, endpoint):
|
||||
""" Mock _build_error_peppol_endpoint"""
|
||||
if eas == "0184" and endpoint != "digstorg":
|
||||
return f"(0184, {endpoint}) is not a valid peppol couple."
|
||||
|
||||
@patch(
|
||||
'odoo.addons.account_edi_ubl_cii.models.res_partner.ResPartner._build_error_peppol_endpoint',
|
||||
_build_error_peppol_endpoint,
|
||||
)
|
||||
def test_peppol_eas_endpoint(self):
|
||||
# NB: the EAS_MAPPING for DK is: {'DK': {'0184': 'company_registry', '0198': 'vat'}}
|
||||
partner = self.company_data['company'].partner_id
|
||||
|
||||
partner.company_registry = "digstorg"
|
||||
partner.vat = "DK12345674"
|
||||
|
||||
# Base case -> (0184, company_registry)
|
||||
with self.check_peppol_vals(partner, expected=("0184", partner.company_registry)):
|
||||
pass
|
||||
|
||||
# No company_registry -> (0198, vat)
|
||||
with self.check_peppol_vals(partner, expected=("0198", partner.vat)):
|
||||
partner.company_registry = False
|
||||
|
||||
# Invalid company_registry -> (0198, vat)
|
||||
with self.check_peppol_vals(partner, expected=("0198", partner.vat)):
|
||||
partner.company_registry = "turlututu"
|
||||
|
||||
# No company_registry nor vat -> (0184, False)
|
||||
with self.check_peppol_vals(partner, expected=("0184", False)):
|
||||
partner.write({
|
||||
'company_registry': False,
|
||||
'vat': False,
|
||||
})
|
||||
|
||||
# Create a partner, fill the peppol fields, then set the country
|
||||
partner_1 = self.env['res.partner'].create({
|
||||
'name': "A new partner",
|
||||
'peppol_eas': '0184',
|
||||
'peppol_endpoint': 'digstorg'
|
||||
})
|
||||
with self.check_peppol_vals(partner_1, expected=("0184", 'digstorg'), reset=False):
|
||||
pass
|
||||
|
||||
# Create a partner, set the country, then fill the peppol fields
|
||||
partner_2 = self.env['res.partner'].create({
|
||||
'name': "A new partner",
|
||||
'country_id': self.env.ref('base.dk').id,
|
||||
})
|
||||
with self.check_peppol_vals(partner_2, expected=("0184", 'digstorg'), reset=False):
|
||||
partner_2.peppol_eas = '0184'
|
||||
partner_2.peppol_endpoint = 'digstorg'
|
||||
|
||||
# Change the country, the EAS changes but we do not overwrite the existing endpoint
|
||||
partner_2.country_id = self.env.ref('base.be')
|
||||
self.assertEqual((partner_2.peppol_eas, partner_2.peppol_endpoint), ('0208', 'digstorg'))
|
||||
+2
-2
@@ -14,7 +14,7 @@
|
||||
</cac:OrderReference>
|
||||
<cac:AccountingSupplierParty>
|
||||
<cac:Party>
|
||||
<cbc:EndpointID schemeID="9925">BE0202239951</cbc:EndpointID>
|
||||
<cbc:EndpointID schemeID="0208">0202239951</cbc:EndpointID>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>partner_1</cbc:Name>
|
||||
</cac:PartyName>
|
||||
@@ -43,7 +43,7 @@
|
||||
</cac:AccountingSupplierParty>
|
||||
<cac:AccountingCustomerParty>
|
||||
<cac:Party>
|
||||
<cbc:EndpointID schemeID="9925">BE0477472701</cbc:EndpointID>
|
||||
<cbc:EndpointID schemeID="0208">0477472701</cbc:EndpointID>
|
||||
<cac:PartyName>
|
||||
<cbc:Name>partner_2</cbc:Name>
|
||||
</cac:PartyName>
|
||||
|
||||
@@ -238,8 +238,8 @@ class TestUBLBE(TestUBLCommon, TestAccountMoveSendCommon):
|
||||
# Setup a public admin in Luxembourg
|
||||
self.partner_2.write({
|
||||
'vat': None,
|
||||
'peppol_endpoint': '00005000041',
|
||||
'peppol_eas': '9938',
|
||||
'peppol_endpoint': '00005000041',
|
||||
'country_id': self.env.ref('base.lu').id,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user