diff --git a/docs/authors.rst b/docs/authors.rst index 4e41ef55..8c0bb7c8 100644 --- a/docs/authors.rst +++ b/docs/authors.rst @@ -33,6 +33,7 @@ Authors * Ben Konrath * Bruno M. Custódio * Burhan Khalid +* Célia Prat * Claude Paroz * Daniel Ampuero * Daniela Ponader diff --git a/docs/changelog.rst b/docs/changelog.rst index 642acdd8..7227737b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -17,6 +17,8 @@ Modifications to existing flavors: - Fix Belarus passport field description punctuation (`gh-484 `_). - Change `Kiev` to `Kyiv` 🇺🇦 according to ISO_3166-2:UA +- Accept French Postal Services identifiers in forms + (`gh-505 `_). Other changes: diff --git a/localflavor/fr/forms.py b/localflavor/fr/forms.py index 5f642a23..0320e11c 100644 --- a/localflavor/fr/forms.py +++ b/localflavor/fr/forms.py @@ -184,21 +184,7 @@ def _check_foreign_countries(self, commune_of_origin, current_year, department_o raise ValidationError(self.error_messages['invalid'], code='invalid') -class FRSIRENENumberMixin: - """Abstract class for SIREN and SIRET numbers, from the SIRENE register.""" - - def clean(self, value): - value = super().clean(value) - if value in self.empty_values: - return value - - value = value.replace(' ', '').replace('-', '') - if not self.r_valid.match(value) or not luhn.is_valid(value): - raise ValidationError(self.error_messages['invalid'], code='invalid') - return value - - -class FRSIRENField(FRSIRENENumberMixin, CharField): +class FRSIRENField(CharField): """ SIREN stands for "Système d'identification du répertoire des entreprises". @@ -220,8 +206,18 @@ def prepare_value(self, value): value = value.replace(' ', '').replace('-', '') return ' '.join((value[:3], value[3:6], value[6:])) + def clean(self, value): + value = super().clean(value) + if value in self.empty_values: + return value + + value = value.replace(' ', '').replace('-', '') + if not self.r_valid.match(value) or not luhn.is_valid(value): + raise ValidationError(self.error_messages['invalid'], code='invalid') + return value + -class FRSIRETField(FRSIRENENumberMixin, CharField): +class FRSIRETField(CharField): """ SIRET stands for "Système d'identification du répertoire des établissements". @@ -244,7 +240,8 @@ def clean(self, value): value = value.replace(' ', '').replace('-', '') - if not luhn.is_valid(value[:9]): + if not self.r_valid.match(value) or not luhn.is_valid(value[:9]) or \ + (value.startswith("356000000") and sum(int(x) for x in value) % 5 != 0): raise ValidationError(self.error_messages['invalid'], code='invalid') return value diff --git a/tests/test_fr.py b/tests/test_fr.py index b836a4b6..0bc6b075 100644 --- a/tests/test_fr.py +++ b/tests/test_fr.py @@ -271,10 +271,12 @@ def test_FRSIRENNumber(self): '752932715': '752932715', '752 932 715': '752932715', '752-932-715': '752932715', + '356000000': '356000000' } invalid = { '1234': error_format, # wrong size '752932712': error_format, # Bad luhn on SIREN + '35600000014597' : error_format } self.assertFieldOutput(FRSIRENField, valid, invalid) @@ -294,11 +296,13 @@ def test_FRSIRETNumber(self): '75293271500010': '75293271500010', '752 932 715 00010': '75293271500010', '752-932-715-00010': '75293271500010', + '35600000014597' : '35600000014597', # Special case La Poste } invalid = { '1234': error_format, # wrong size '75293271200017': error_format, # Bad luhn on SIREN '75293271000010': error_format, # Bad luhn on whole + '35600000014596' : error_format # Special case La Poste } self.assertFieldOutput(FRSIRETField, valid, invalid)