Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit 672e39a

Browse files
authored
Fix #243 - add Bulgaria TIN and UIC (#258)
1 parent 3ded5be commit 672e39a

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed

idnumbers/nationalid/BGR.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
from types import SimpleNamespace
12
from .bgr.uniform_civil import UniformCivilNumber
3+
from .bgr.unifed_id_code import UnifiedIdCode
24
from .util import alias_of
35

46
NationalID = alias_of(UniformCivilNumber)
57
"""alias of UniformCivilNumber"""
8+
TIN = SimpleNamespace(**{
9+
'individual': UniformCivilNumber,
10+
'entity': UnifiedIdCode
11+
})
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import re
2+
from types import SimpleNamespace
3+
from typing import Optional
4+
5+
from ..util import validate_regexp, CHECK_DIGIT, weighted_modulus_digit
6+
7+
8+
class UnifiedIdCode:
9+
"""
10+
Bulgaria unified identification code, UIC
11+
https://validatetin.com/bulgaria/
12+
"""
13+
METADATA = SimpleNamespace(**{
14+
'iso3166_alpha2': 'BG',
15+
# length without insignificant chars
16+
'min_length': 9,
17+
'max_length': 13,
18+
'parsable': False,
19+
'checksum': True,
20+
'regexp': re.compile(r'^(\d{9}|\d{13})$'),
21+
'alias_of': None,
22+
'names': ['Unified Identification Code',
23+
'UIC',
24+
'EIK',
25+
'BULSTAT',
26+
'ЕИК',
27+
'БУЛСТАТ'],
28+
'links': ['https://validatetin.com/bulgaria/',
29+
'https://taxid.pro/docs/countries/bulgaria',
30+
'https://www.wikidata.org/wiki/Property:P8894',
31+
'https://www.wikidata.org/wiki/Wikidata:Property_proposal/EIK',
32+
'https://bg.wikipedia.org/wiki/%D0%95%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD_'
33+
'%D0%B8%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%B5%D0%BD_'
34+
'%D0%BA%D0%BE%D0%B4'],
35+
'deprecated': False
36+
})
37+
38+
WEIGHTS9_1 = [1, 2, 3, 4, 5, 6, 7, 8]
39+
WEIGHTS9_2 = [3, 4, 5, 6, 7, 8, 9, 10]
40+
WEIGHTS13_1 = [2, 7, 3, 5]
41+
WEIGHTS13_2 = [4, 9, 5, 7]
42+
43+
@staticmethod
44+
def validate(id_number: str) -> bool:
45+
"""
46+
Validate the BGR id number
47+
"""
48+
if not validate_regexp(id_number, UnifiedIdCode.METADATA.regexp):
49+
return False
50+
check = UnifiedIdCode.checksum(id_number)
51+
return check is not None and str(check) == id_number[-1]
52+
53+
@staticmethod
54+
def checksum(id_number: str) -> Optional[CHECK_DIGIT]:
55+
if not validate_regexp(id_number, UnifiedIdCode.METADATA.regexp):
56+
return None
57+
"""
58+
Get the checksum digit
59+
python version of:
60+
https://github.com/mirovit/eik-validator/blob/master/src/EIKValidator/EIKValidator.php
61+
"""
62+
if len(id_number) == 9:
63+
numbers = [int(i) for i in id_number[:-1]]
64+
weights = [UnifiedIdCode.WEIGHTS9_1, UnifiedIdCode.WEIGHTS9_2]
65+
else:
66+
numbers = [int(i) for i in id_number[0:4]]
67+
weights = [UnifiedIdCode.WEIGHTS13_1, UnifiedIdCode.WEIGHTS13_2]
68+
69+
modulus1 = weighted_modulus_digit(numbers, weights[0], 11, True)
70+
if modulus1 < 10:
71+
return modulus1
72+
modulus2 = weighted_modulus_digit(numbers, weights[1], 11, True)
73+
return modulus2 if modulus2 < 10 else 0

tests/nationalid/test_BGR.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from unittest import TestCase, main
1+
from unittest import TestCase
22
from datetime import date
33

44
from idnumbers.nationalid import BGR
@@ -25,6 +25,9 @@ def test_parse(self):
2525
self.assertEqual(Gender.MALE, result['gender'])
2626
self.assertEqual(5, result['checksum'])
2727

28-
29-
if __name__ == '__main__':
30-
main()
28+
def test_tin_cases(self):
29+
self.assertTrue(BGR.TIN.individual.validate('7501020018'))
30+
# test cases: https://papagal.bg/bg/
31+
self.assertTrue(BGR.TIN.entity.validate('207258749'))
32+
self.assertTrue(BGR.TIN.entity.validate('207271885'))
33+
self.assertTrue(BGR.TIN.entity.validate('114635815'))

0 commit comments

Comments
 (0)