changeset f5c2c4885143 in modules/party_siret:default
details:
https://hg.tryton.org/modules/party_siret?cmd=changeset&node=f5c2c4885143
description:
Use party identifier to store SIREN and SIRET
issue5834
review397071002
diffstat:
CHANGELOG | 1 +
address.py | 102 ++++++++++++++++++++++++++++++++++-----------
address.xml | 5 --
exceptions.py | 12 -----
luhn.py | 18 --------
message.xml | 13 -----
party.py | 47 ++++++++++++---------
party.xml | 5 --
tests/test_party_siret.py | 27 ------------
tryton.cfg | 1 -
view/address_form.xml | 13 -----
view/party_form.xml | 10 ----
12 files changed, 104 insertions(+), 150 deletions(-)
diffs (353 lines):
diff -r e253d14b3240 -r f5c2c4885143 CHANGELOG
--- a/CHANGELOG Thu Feb 03 23:13:26 2022 +0100
+++ b/CHANGELOG Sun Feb 13 00:43:49 2022 +0100
@@ -1,3 +1,4 @@
+* Use party identifier to store SIREN and SIRET
* Add support for Python 3.10
* Remove support for Python 3.6
diff -r e253d14b3240 -r f5c2c4885143 address.py
--- a/address.py Thu Feb 03 23:13:26 2022 +0100
+++ b/address.py Sun Feb 13 00:43:49 2022 +0100
@@ -1,37 +1,87 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
-from trytond.i18n import gettext
+from sql import Literal, Null
+from sql.operators import Concat
+
from trytond.model import fields
-from trytond.pool import PoolMeta
-
-from . import luhn
-from .exceptions import SIRETValidationError
+from trytond.pool import Pool, PoolMeta
+from trytond.transaction import Transaction
class Address(metaclass=PoolMeta):
__name__ = 'party.address'
- siret_nic = fields.Char("SIRET NIC", select=True, size=5)
- siret = fields.Function(fields.Char('SIRET'), 'get_siret')
-
- def get_siret(self, name):
- if self.party.siren and self.siret_nic:
- return self.party.siren + self.siret_nic
+ siret = fields.Function(fields.Many2One(
+ 'party.identifier', "SIRET"),
+ 'get_siret', searcher='search_siret')
@classmethod
- def validate(cls, addresses):
- super(Address, cls).validate(addresses)
- for address in addresses:
- address.check_siret()
+ def __register__(cls, module):
+ pool = Pool()
+ Party = pool.get('party.party')
+ Identifier = pool.get('party.identifier')
+ cursor = Transaction().connection.cursor()
+ party = Party.__table__()
+ address = cls.__table__()
+ identifier = Identifier.__table__()
+
+ super().__register__(module)
+
+ table_h = cls.__table_handler__(module)
+ party_h = Party.__table_handler__(module)
- def check_siret(self):
- '''
- Check validity of SIRET
- '''
- if self.siret:
- if (len(self.siret) != 14
- or not luhn.validate(self.siret)):
- raise SIRETValidationError(
- gettext('party_siret.msg_invalid_siret',
- number=self.siret,
- address=self.rec_name))
+ # Migrate from 6.2: replace siren and siret by identifier
+ if party_h.column_exist('siren'):
+ cursor.execute(*identifier.insert(
+ [identifier.party,
+ identifier.type, identifier.code,
+ identifier.active],
+ party.select(
+ party.id, Literal('fr_siren'),
+ party.siren, party.active,
+ where=(party.siren != Null)
+ & (party.siren != ''))))
+ if table_h.column_exist('siret_nic'):
+ cursor.execute(*identifier.insert(
+ [identifier.party, identifier.address,
+ identifier.type, identifier.code,
+ identifier.active],
+ address.join(
+ party, condition=address.party == party.id
+ ).select(
+ address.party, address.id,
+ Literal('fr_siret'),
+ Concat(party.siren, address.siret_nic),
+ address.active,
+ where=(address.siret_nic != Null)
+ & (address.siret_nic != '')
+ & (party.siren != Null)
+ & (party.siren != ''))))
+ table_h.drop_column('siret_nic')
+ party_h.drop_column('siren')
+
+ def get_siret(self, name):
+ for identifier in self.identifiers:
+ if identifier.type == 'fr_siret':
+ return identifier.id
+
+ @classmethod
+ def search_siret(cls, name, clause):
+ _, operator, value = clause
+ domain = [
+ ('identifiers', 'where', [
+ ('code', operator, value),
+ ('type', 'in', 'fr_siren'),
+ ]),
+ ]
+ # Add party without tax identifier
+ if ((operator == '=' and value is None)
+ or (operator == 'in' and None in value)):
+ domain = ['OR',
+ domain, [
+ ('identifiers', 'not where', [
+ ('type', '=', 'fr_siren'),
+ ]),
+ ],
+ ]
+ return domain
diff -r e253d14b3240 -r f5c2c4885143 address.xml
--- a/address.xml Thu Feb 03 23:13:26 2022 +0100
+++ b/address.xml Sun Feb 13 00:43:49 2022 +0100
@@ -8,10 +8,5 @@
<field name="inherit" ref="party.address_view_tree"/>
<field name="name">address_tree</field>
</record>
- <record model="ir.ui.view" id="address_view_form">
- <field name="model">party.address</field>
- <field name="inherit" ref="party.address_view_form"/>
- <field name="name">address_form</field>
- </record>
</data>
</tryton>
diff -r e253d14b3240 -r f5c2c4885143 exceptions.py
--- a/exceptions.py Thu Feb 03 23:13:26 2022 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-# This file is part of Tryton. The COPYRIGHT file at the top level of
-# this repository contains the full copyright notices and license terms.
-
-from trytond.model.exceptions import ValidationError
-
-
-class SIRENValidationError(ValidationError):
- pass
-
-
-class SIRETValidationError(SIRENValidationError):
- pass
diff -r e253d14b3240 -r f5c2c4885143 luhn.py
--- a/luhn.py Thu Feb 03 23:13:26 2022 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-# This file is part of Tryton. The COPYRIGHT file at the top level of
-# this repository contains the full copyright notices and license terms.
-
-
-def validate(value):
- """
- Validate value with Luhn algorithm
- :param value: the value
- :return: a boolean
- """
- if not isinstance(value, str):
- value = str(value)
- try:
- evens = sum(int(x) for x in value[-1::-2])
- odds = sum(sum(divmod(int(x) * 2, 10)) for x in value[-2::-2])
- return (evens + odds) % 10 == 0
- except ValueError:
- return False
diff -r e253d14b3240 -r f5c2c4885143 message.xml
--- a/message.xml Thu Feb 03 23:13:26 2022 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
-this repository contains the full copyright notices and license terms. -->
-<tryton>
- <data grouped="1">
- <record model="ir.message" id="msg_invalid_siren">
- <field name="text">The SIREN number "%(number)s" for party
"%(party)s" is not valid.</field>
- </record>
- <record model="ir.message" id="msg_invalid_siret">
- <field name="text">The SIRET number "%(number)s" for address
"%(address)s" is not valid.</field>
- </record>
- </data>
-</tryton>
diff -r e253d14b3240 -r f5c2c4885143 party.py
--- a/party.py Thu Feb 03 23:13:26 2022 +0100
+++ b/party.py Sun Feb 13 00:43:49 2022 +0100
@@ -1,31 +1,38 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
-from trytond.i18n import gettext
from trytond.model import fields
from trytond.pool import PoolMeta
-from . import luhn
-from .exceptions import SIRENValidationError
-
class Party(metaclass=PoolMeta):
__name__ = 'party.party'
- siren = fields.Char("SIREN", select=True, size=9)
+ siren = fields.Function(fields.Many2One(
+ 'party.identifier', "SIREN"),
+ 'get_siren', searcher='search_siren')
+
+ def get_siren(self, name):
+ for identifier in self.identifiers:
+ if identifier.type == 'fr_siren':
+ return identifier.id
@classmethod
- def validate(cls, parties):
- super(Party, cls).validate(parties)
- for party in parties:
- party.check_siren()
-
- def check_siren(self):
- '''
- Check validity of SIREN
- '''
- if self.siren:
- if len(self.siren) != 9 or not luhn.validate(self.siren):
- raise SIRENValidationError(
- gettext('party_siret.msg_invalid_siren',
- number=self.siren,
- party=self.rec_name))
+ def search_siren(cls, name, clause):
+ _, operator, value = clause
+ domain = [
+ ('identifiers', 'where', [
+ ('code', operator, value),
+ ('type', 'in', 'fr_siren'),
+ ]),
+ ]
+ # Add party without tax identifier
+ if ((operator == '=' and value is None)
+ or (operator == 'in' and None in value)):
+ domain = ['OR',
+ domain, [
+ ('identifiers', 'not where', [
+ ('type', '=', 'fr_siren'),
+ ]),
+ ],
+ ]
+ return domain
diff -r e253d14b3240 -r f5c2c4885143 party.xml
--- a/party.xml Thu Feb 03 23:13:26 2022 +0100
+++ b/party.xml Sun Feb 13 00:43:49 2022 +0100
@@ -8,10 +8,5 @@
<field name="inherit" ref="party.party_view_tree"/>
<field name="name">party_tree</field>
</record>
- <record model="ir.ui.view" id="party_view_form">
- <field name="model">party.party</field>
- <field name="inherit" ref="party.party_view_form"/>
- <field name="name">party_form</field>
- </record>
</data>
</tryton>
diff -r e253d14b3240 -r f5c2c4885143 tests/test_party_siret.py
--- a/tests/test_party_siret.py Thu Feb 03 23:13:26 2022 +0100
+++ b/tests/test_party_siret.py Sun Feb 13 00:43:49 2022 +0100
@@ -3,7 +3,6 @@
import unittest
import trytond.tests.test_tryton
-from trytond.modules.party_siret import luhn
from trytond.tests.test_tryton import ModuleTestCase
@@ -11,32 +10,6 @@
'Test PartySiret module'
module = 'party_siret'
- def test_luhn(self):
- 'Test luhn'
- values = (
- (4111111111111111, True),
- ('4111111111111111', True),
- (4222222222222, True),
- (378734493671000, True),
- (5424000000000015, True),
- (5555555555554444, True),
- (1008, True),
- ('0000001008', True),
- ('000000001008', True),
- (4012888888881881, True),
- (1234567890123456789012345678909, True),
- (4111111111211111, False),
- (42222222222224, False),
- (100, False),
- ('100', False),
- ('0000100', False),
- ('abc', False),
- (None, False),
- (object(), False),
- )
- for value, test in values:
- self.assertTrue(luhn.validate(value) == test)
-
def suite():
suite = trytond.tests.test_tryton.suite()
diff -r e253d14b3240 -r f5c2c4885143 tryton.cfg
--- a/tryton.cfg Thu Feb 03 23:13:26 2022 +0100
+++ b/tryton.cfg Sun Feb 13 00:43:49 2022 +0100
@@ -6,4 +6,3 @@
xml:
party.xml
address.xml
- message.xml
diff -r e253d14b3240 -r f5c2c4885143 view/address_form.xml
--- a/view/address_form.xml Thu Feb 03 23:13:26 2022 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
-this repository contains the full copyright notices and license terms. -->
-<data>
- <xpath expr="/form/field[@name='name']" position="after">
- <group id="siret" colspan="2" col="-1">
- <label name="siret_nic"/>
- <field name="siret_nic"/>
- <label name="siret"/>
- <field name="siret"/>
- </group>
- </xpath>
-</data>
diff -r e253d14b3240 -r f5c2c4885143 view/party_form.xml
--- a/view/party_form.xml Thu Feb 03 23:13:26 2022 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-<?xml version="1.0"?>
-<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
-this repository contains the full copyright notices and license terms. -->
-<data>
- <xpath expr="//page[@name='identifiers']/field[@name='identifiers']"
position="before">
- <label name="siren"/>
- <field name="siren"/>
- <newline/>
- </xpath>
-</data>