[FIX] l10n_it_edi: fiscal code format

According to
www.agenziaentrate.gov.it/portale/web/guest/schede/istanze/richiesta-ts_cf/informazioni-codificazione-pf

The tax identification number of natural persons
consists of an alphanumeric expression of sixteen characters.

The first fifteen characters are indicative of the master data
of each individual in the following order:

- 3 alphabetic characters for the surname;
- 3 alphabetic characters for the first name;
- 2 numeric characters for the year of birth;
- 1 alphabetic character for the month of birth;
- 2 numeric characters for the day of birth and sex;
- 4 characters, 1 alphabetic and 3 numeric for the Italian municipality
  or foreign state of birth.
The sixteenth character, alphabetic, serves as a control.

The main fix is about this part:

When two or more individuals have master data generating
the same tax code (homocodes), the tax code is differentiated
for each of them. For this purpose, systematic substitutions
of one or more digits starting from the right one are made
within the seven numeric characters contained in the code
with corresponding alphabetic characters according to the
following table:

0 = L 4 = Q 8 = U
1 = M 5 = R 9 = V
2 = N 6 = S
3 = P 7 = T

Also the check for iva number format was incomplete.
Indeed, The three penultimate digits correspond to the region of the
VAT office and must be between 001 and 100 inclusive,
or equal to 120, 121, 888 or 999.

We use the stdnum library's methods for the validation of fiscal code
and iva number format.

opw-2797408

closes odoo/odoo#97633

X-original-commit: 262eb7bd021d177d9a05397f9cda3fc76a21d4cb
Signed-off-by: Josse Colpaert <jco@odoo.com>
This commit is contained in:
Guillaume (guva)
2022-08-08 22:16:32 +02:00
parent 1766f75bb2
commit 8434eed9ac
3 changed files with 65 additions and 3 deletions
+3 -3
View File
@@ -1,5 +1,6 @@
# -*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from stdnum.it import codicefiscale, iva
from odoo import api, fields, models, _
from odoo.exceptions import UserError
@@ -45,7 +46,6 @@ class ResPartner(models.Model):
@api.constrains('l10n_it_codice_fiscale')
def validate_codice_fiscale(self):
p = re.compile(r'^([A-Za-z]{6}[0-9]{2}[A-Za-z]{1}[0-9]{2}[A-Za-z]{1}[0-9]{3}[A-Za-z]{1}$)|([0-9]{11})|(IT[0-9]{11})$')
for record in self:
if record.l10n_it_codice_fiscale and not p.match(record.l10n_it_codice_fiscale):
raise UserError(_("Invalid Codice Fiscale '%s': should be like 'MRTMTT91D08F205J' for physical person and '12345678901' or 'IT12345678901' for businesses.", record.l10n_it_codice_fiscale))
if record.l10n_it_codice_fiscale and (not codicefiscale.is_valid(record.l10n_it_codice_fiscale) and not iva.is_valid(record.l10n_it_codice_fiscale)):
raise UserError(_("Invalid Codice Fiscale '%s': should be like 'MRTMTT91D08F205J' for physical person and '12345670546' or 'IT12345670546' for businesses.", record.l10n_it_codice_fiscale))
+1
View File
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_ir_mail_server
from . import test_res_partner
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import UserError
from odoo.tests.common import TransactionCase, tagged
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestResPartner(TransactionCase):
def test_validate_fiscal_code(self):
valid_codes = [
"AORTHV05P30V295L",
"SPDTHB43S93F42VH",
"MDRTUV99H14X2MNU",
"XPTDRX73R64YPLUD",
"LOLXDR40T3MZRTSV",
"GJTIUG55DLQZRTSS",
"CDEOTG5PBLQZRTSE",
"PERTLELPALQZRTSN",
"IT12345678887",
"IT12345670546",
"IT95286931217",
"IT95867361206",
"IT94567689990",
"12345670546",
"95286931217",
"95867361206",
"94567689990",
]
invalid_codes = [
"AORTHV05P34V295U",
"SPDTHB43O93F42VH",
"MDRTUVV9H14X2MNU",
"XPTDRX73RS4YPLUD",
"LOLXDRQ0T3QZRTSJ",
"GJTIUGR5DLQZRTSS",
"CDEOTG5PBLQZRTSS",
"PERTLEZPALQZRTSN",
"IT12345678901",
"IT12345678885",
"IT45689349992",
"IT78239131204",
"IT45692151219",
"12345678901",
"12345678885",
"45689349992",
"78239131204",
"45692151219",
]
partners = self.env['res.partner']
for i, code in enumerate(invalid_codes):
with self.assertRaises(UserError):
partners += self.env['res.partner'].create({'name': f'partner_{i}', 'l10n_it_codice_fiscale': code})
for i, code in enumerate(valid_codes):
partners += self.env['res.partner'].create({'name': f'partner_{i}', 'l10n_it_codice_fiscale': code})
self.assertEqual(len(partners), len(valid_codes))