Skip to content
Snippets Groups Projects
Commit 262eb7bd authored by Guillaume (guva)'s avatar Guillaume (guva)
Browse files

[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#95594

Signed-off-by: default avatarJosse Colpaert <jco@odoo.com>
parent ca2f4c8e
No related branches found
No related tags found
No related merge requests found
# -*- 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, ValidationError
......@@ -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))
......@@ -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
# -*- 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))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment