210 lines
10 KiB
Python
Raw Permalink Normal View History

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
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
class ResPartner(models.Model):
_inherit = 'res.partner'
ubl_cii_format = fields.Selection(
string="Format",
selection=[
('facturx', "Factur-X (CII)"),
('ubl_bis3', "BIS Billing 3.0"),
('xrechnung', "XRechnung CIUS"),
('nlcius', "NLCIUS"),
('ubl_a_nz', "BIS Billing 3.0 A-NZ"),
('ubl_sg', "BIS Billing 3.0 SG"),
],
compute='_compute_ubl_cii_format',
store=True,
readonly=False,
)
peppol_endpoint = fields.Char(
string="Peppol Endpoint",
help="Unique identifier used by the BIS Billing 3.0 and its derivatives, also known as 'Endpoint ID'.",
compute="_compute_peppol_endpoint",
store=True,
readonly=False,
tracking=True,
)
peppol_eas = fields.Selection(
string="Peppol e-address (EAS)",
help="""Code used to identify the Endpoint for BIS Billing 3.0 and its derivatives.
List available at https://docs.peppol.eu/poacc/billing/3.0/codelist/eas/""",
compute="_compute_peppol_eas",
store=True,
readonly=False,
tracking=True,
selection=[
('0002', "0002 - System Information et Repertoire des Entreprise et des Etablissements: SIRENE"),
('0007', "0007 - Organisationsnummer (Swedish legal entities)"),
('0009', "0009 - SIRET-CODE"),
('0037', "0037 - LY-tunnus"),
('0060', "0060 - Data Universal Numbering System (D-U-N-S Number)"),
('0088', "0088 - EAN Location Code"),
('0096', "0096 - DANISH CHAMBER OF COMMERCE Scheme (EDIRA compliant)"),
('0097', "0097 - FTI - Ediforum Italia, (EDIRA compliant)"),
('0106', "0106 - Association of Chambers of Commerce and Industry in the Netherlands, (EDIRA compliant)"),
('0130', "0130 - Directorates of the European Commission"),
('0135', "0135 - SIA Object Identifiers"),
('0142', "0142 - SECETI Object Identifiers"),
('0151', "0151 - Australian Business Number (ABN) Scheme"),
('0183', "0183 - Swiss Unique Business Identification Number (UIDB)"),
('0184', "0184 - DIGSTORG"),
('0188', "0188 - Corporate Number of The Social Security and Tax Number System"),
('0190', "0190 - Dutch Originator's Identification Number"),
('0191', "0191 - Centre of Registers and Information Systems of the Ministry of Justice"),
('0192', "0192 - Enhetsregisteret ved Bronnoysundregisterne"),
('0193', "0193 - UBL.BE party identifier"),
('0195', "0195 - Singapore UEN identifier"),
('0196', "0196 - Kennitala - Iceland legal id for individuals and legal entities"),
('0198', "0198 - ERSTORG"),
('0199', "0199 - Legal Entity Identifier (LEI)"),
('0200', "0200 - Legal entity code (Lithuania)"),
('0201', "0201 - Codice Univoco Unità Organizzativa iPA"),
('0202', "0202 - Indirizzo di Posta Elettronica Certificata"),
('0204', "0204 - Leitweg-ID"),
('0208', "0208 - Numero d'entreprise / ondernemingsnummer / Unternehmensnummer"),
('0209', "0209 - GS1 identification keys"),
('0210', "0210 - CODICE FISCALE"),
('0211', "0211 - PARTITA IVA"),
('0212', "0212 - Finnish Organization Identifier"),
('0213', "0213 - Finnish Organization Value Add Tax Identifier"),
('0215', "0215 - Net service ID"),
('0216', "0216 - OVTcode"),
('0221', "0221 - The registered number of the qualified invoice issuer (Japan)"),
('0230', "0230 - National e-Invoicing Framework (Malaysia)"),
('9901', "9901 - Danish Ministry of the Interior and Health"),
('9910', "9910 - Hungary VAT number"),
('9913', "9913 - Business Registers Network"),
('9914', "9914 - Österreichische Umsatzsteuer-Identifikationsnummer"),
('9915', "9915 - Österreichisches Verwaltungs bzw. Organisationskennzeichen"),
('9918', "9918 - SOCIETY FOR WORLDWIDE INTERBANK FINANCIAL, TELECOMMUNICATION S.W.I.F.T"),
('9919', "9919 - Kennziffer des Unternehmensregisters"),
('9920', "9920 - Agencia Española de Administración Tributaria"),
('9922', "9922 - Andorra VAT number"),
('9923', "9923 - Albania VAT number"),
('9924', "9924 - Bosnia and Herzegovina VAT number"),
('9925', "9925 - Belgium VAT number"),
('9926', "9926 - Bulgaria VAT number"),
('9927', "9927 - Switzerland VAT number"),
('9928', "9928 - Cyprus VAT number"),
('9929', "9929 - Czech Republic VAT number"),
('9930', "9930 - Germany VAT number"),
('9931', "9931 - Estonia VAT number"),
('9932', "9932 - United Kingdom VAT number"),
('9933', "9933 - Greece VAT number"),
('9934', "9934 - Croatia VAT number"),
('9935', "9935 - Ireland VAT number"),
('9936', "9936 - Liechtenstein VAT number"),
('9937', "9937 - Lithuania VAT number"),
('9938', "9938 - Luxemburg VAT number"),
('9939', "9939 - Latvia VAT number"),
('9940', "9940 - Monaco VAT number"),
('9941', "9941 - Montenegro VAT number"),
('9942', "9942 - Macedonia, the former Yugoslav Republic of VAT number"),
('9943', "9943 - Malta VAT number"),
('9944', "9944 - Netherlands VAT number"),
('9945', "9945 - Poland VAT number"),
('9946', "9946 - Portugal VAT number"),
('9947', "9947 - Romania VAT number"),
('9948', "9948 - Serbia VAT number"),
('9949', "9949 - Slovenia VAT number"),
('9950', "9950 - Slovakia VAT number"),
('9951', "9951 - San Marino VAT number"),
('9952', "9952 - Turkey VAT number"),
('9953', "9953 - Holy See (Vatican City State) VAT number"),
('9955', "9955 - Swedish VAT number"),
('9957', "9957 - French VAT number"),
('9959', "9959 - Employer Identification Number (EIN, USA)"),
]
)
@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:
if partner.country_code == 'DE':
partner.ubl_cii_format = 'xrechnung'
elif partner.country_code in ('AU', 'NZ'):
partner.ubl_cii_format = 'ubl_a_nz'
elif partner.country_code == 'NL':
partner.ubl_cii_format = 'nlcius'
elif partner.country_code == 'FR':
partner.ubl_cii_format = 'facturx'
elif partner.country_code == 'SG':
partner.ubl_cii_format = 'ubl_sg'
elif partner.country_code in EAS_MAPPING:
partner.ubl_cii_format = 'ubl_bis3'
else:
partner.ubl_cii_format = partner.ubl_cii_format
@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:
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:
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]
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()
if self.ubl_cii_format == 'xrechnung':
return self.env['account.edi.xml.ubl_de']
if self.ubl_cii_format == 'facturx':
return self.env['account.edi.xml.cii']
if self.ubl_cii_format == 'ubl_a_nz':
return self.env['account.edi.xml.ubl_a_nz']
if self.ubl_cii_format == 'nlcius':
return self.env['account.edi.xml.ubl_nl']
if self.ubl_cii_format == 'ubl_bis3':
return self.env['account.edi.xml.ubl_bis3']
if self.ubl_cii_format == 'ubl_sg':
return self.env['account.edi.xml.ubl_sg']