details: https://code.tryton.org/tryton/commit/d75e351bb91d
branch: default
user: Cédric Krier <[email protected]>
date: Fri Dec 19 09:41:39 2025 +0100
description:
Support European VAT number as EAS and VATIN
Closes #14435
diffstat:
modules/edocument_ubl/party.py | 33 +++++++++++++++++++++++------
modules/edocument_ubl/tests/test_module.py | 24 +++++++++++++++++++++
2 files changed, 50 insertions(+), 7 deletions(-)
diffs (90 lines):
diff -r f10a9c508cee -r d75e351bb91d modules/edocument_ubl/party.py
--- a/modules/edocument_ubl/party.py Thu Dec 18 12:55:42 2025 +0100
+++ b/modules/edocument_ubl/party.py Fri Dec 19 09:41:39 2025 +0100
@@ -95,20 +95,39 @@
return ISO6523_TYPES.get(self.type, '')
@property
+ def _eas_type(self):
+ if self.type == 'eu_vat':
+ code = self.code[:2].lower()
+ code = (code
+ .replace('xi', 'gb')
+ .replace('el', 'gr'))
+ return f'{code}_vat'
+ else:
+ return self.type
+
+ @property
def eas_code(self):
- return EAS_TYPES.get(self.type, '')
+ return EAS_TYPES.get(self._eas_type, '')
@property
def eas(self):
if self.eas_code:
- if re.match(r'[a-z]{2}_vat', self.type):
- country = self.type[:2].replace('gr', 'el')
- return f'{country}{self.code}'.lower()
+ if re.match(r'[a-z]{2}_vat', self._eas_type):
+ country = self._eas_type[:2].replace('gr', 'el')
+ if self.type == 'eu_vat':
+ code = self.code[2:]
+ else:
+ code = self.code
+ return f'{country}{code}'.lower()
else:
return self.code
@property
def vatin(self):
- if re.match(r'[a-z]{2}_vat', self.type):
- country = self.type[:2].replace('gr', 'el')
- return f'{country}{self.code}'.lower()
+ if re.match(r'[a-z]{2}_vat', self._eas_type):
+ country = self._eas_type[:2].replace('gr', 'el')
+ if self.type == 'eu_vat':
+ code = self.code[2:]
+ else:
+ code = self.code
+ return f'{country}{code}'.lower()
diff -r f10a9c508cee -r d75e351bb91d modules/edocument_ubl/tests/test_module.py
--- a/modules/edocument_ubl/tests/test_module.py Thu Dec 18 12:55:42
2025 +0100
+++ b/modules/edocument_ubl/tests/test_module.py Fri Dec 19 09:41:39
2025 +0100
@@ -44,6 +44,7 @@
type='be_vat',
code='BE123456789')
type(identifier).iso_6523 = Identifier.iso_6523
+ type(identifier)._eas_type = Identifier._eas_type
type(identifier).eas = Identifier.eas
type(identifier).unece_code = Identifier.unece_code
party = MagicMock(
@@ -230,5 +231,28 @@
schema = etree.XMLSchema(etree.parse(schema_file))
schema.assertValid(invoice_xml)
+ @with_transaction()
+ def test_identifier_eas(self):
+ "Test EAS identifier"
+ pool = Pool()
+ Identifier = pool.get('party.identifier')
+
+ for type, code, eas_code, eas in [
+ ('gr_vat', '023456783', '9933', 'el023456783'),
+ ('eu_vat', 'EL023456783', '9933', 'el023456783'),
+ ('eu_vat', 'GR023456783', '9933', 'el023456783'),
+ ('be_vat', '0403019261', '9925', 'be0403019261'),
+ ('eu_vat', 'BE0403019261', '9925', 'be0403019261'),
+ ('gb_vat', '980780684', '9932', 'gb980780684'),
+ ('eu_vat', 'GB980780684', '9932', 'gb980780684'),
+ ('eu_vat', 'XI980780684', '9932', 'gb980780684'),
+ ]:
+ with self.subTest(type=type, code=code):
+ identifier = Identifier(type=type, code=code)
+
+ self.assertEqual(identifier.eas_code, eas_code)
+ self.assertEqual(identifier.eas, eas)
+ self.assertEqual(identifier.vatin, eas)
+
del ModuleTestCase