Repository: identique/idnumbers (language: python)

Issue:
[NationalID] Bulgaria TIN
## basic data
* Country ISO-3166 code: BGR
* Links to National IDs
    * TIN: #239 




Discussion / hints:

Fix patch:
diff --git a/idnumbers/nationalid/BGR.py b/idnumbers/nationalid/BGR.py
index 7bce5627..3ccfa588 100644
--- a/idnumbers/nationalid/BGR.py
+++ b/idnumbers/nationalid/BGR.py
@@ -1,5 +1,11 @@
+from types import SimpleNamespace
 from .bgr.uniform_civil import UniformCivilNumber
+from .bgr.unifed_id_code import UnifiedIdCode
 from .util import alias_of
 
 NationalID = alias_of(UniformCivilNumber)
 """alias of UniformCivilNumber"""
+TIN = SimpleNamespace(**{
+    'individual': UniformCivilNumber,
+    'entity': UnifiedIdCode
+})
diff --git a/idnumbers/nationalid/bgr/unifed_id_code.py b/idnumbers/nationalid/bgr/unifed_id_code.py
new file mode 100644
index 00000000..df55d698
--- /dev/null
+++ b/idnumbers/nationalid/bgr/unifed_id_code.py
@@ -0,0 +1,73 @@
+import re
+from types import SimpleNamespace
+from typing import Optional
+
+from ..util import validate_regexp, CHECK_DIGIT, weighted_modulus_digit
+
+
+class UnifiedIdCode:
+    """
+    Bulgaria unified identification code, UIC
+    https://validatetin.com/bulgaria/
+    """
+    METADATA = SimpleNamespace(**{
+        'iso3166_alpha2': 'BG',
+        # length without insignificant chars
+        'min_length': 9,
+        'max_length': 13,
+        'parsable': False,
+        'checksum': True,
+        'regexp': re.compile(r'^(\d{9}|\d{13})$'),
+        'alias_of': None,
+        'names': ['Unified Identification Code',
+                  'UIC',
+                  'EIK',
+                  'BULSTAT',
+                  'ЕИК',
+                  'БУЛСТАТ'],
+        'links': ['https://validatetin.com/bulgaria/',
+                  'https://taxid.pro/docs/countries/bulgaria',
+                  'https://www.wikidata.org/wiki/Property:P8894',
+                  'https://www.wikidata.org/wiki/Wikidata:Property_proposal/EIK',
+                  'https://bg.wikipedia.org/wiki/%D0%95%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD_'
+                  '%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_'
+                  '%D0%BA%D0%BE%D0%B4'],
+        'deprecated': False
+    })
+
+    WEIGHTS9_1 = [1, 2, 3, 4, 5, 6, 7, 8]
+    WEIGHTS9_2 = [3, 4, 5, 6, 7, 8, 9, 10]
+    WEIGHTS13_1 = [2, 7, 3, 5]
+    WEIGHTS13_2 = [4, 9, 5, 7]
+
+    @staticmethod
+    def validate(id_number: str) -> bool:
+        """
+        Validate the BGR id number
+        """
+        if not validate_regexp(id_number, UnifiedIdCode.METADATA.regexp):
+            return False
+        check = UnifiedIdCode.checksum(id_number)
+        return check is not None and str(check) == id_number[-1]
+
+    @staticmethod
+    def checksum(id_number: str) -> Optional[CHECK_DIGIT]:
+        if not validate_regexp(id_number, UnifiedIdCode.METADATA.regexp):
+            return None
+        """
+        Get the checksum digit
+        python version of:
+        https://github.com/mirovit/eik-validator/blob/master/src/EIKValidator/EIKValidator.php
+        """
+        if len(id_number) == 9:
+            numbers = [int(i) for i in id_number[:-1]]
+            weights = [UnifiedIdCode.WEIGHTS9_1, UnifiedIdCode.WEIGHTS9_2]
+        else:
+            numbers = [int(i) for i in id_number[0:4]]
+            weights = [UnifiedIdCode.WEIGHTS13_1, UnifiedIdCode.WEIGHTS13_2]
+
+        modulus1 = weighted_modulus_digit(numbers, weights[0], 11, True)
+        if modulus1 < 10:
+            return modulus1
+        modulus2 = weighted_modulus_digit(numbers, weights[1], 11, True)
+        return modulus2 if modulus2 < 10 else 0


Test patch:
diff --git a/tests/nationalid/test_BGR.py b/tests/nationalid/test_BGR.py
index 7c560388..986cb046 100644
--- a/tests/nationalid/test_BGR.py
+++ b/tests/nationalid/test_BGR.py
@@ -1,4 +1,4 @@
-from unittest import TestCase, main
+from unittest import TestCase
 from datetime import date
 
 from idnumbers.nationalid import BGR
@@ -25,6 +25,9 @@ def test_parse(self):
         self.assertEqual(Gender.MALE, result['gender'])
         self.assertEqual(5, result['checksum'])
 
-
-if __name__ == '__main__':
-    main()
+    def test_tin_cases(self):
+        self.assertTrue(BGR.TIN.individual.validate('7501020018'))
+        # test cases: https://papagal.bg/bg/
+        self.assertTrue(BGR.TIN.entity.validate('207258749'))
+        self.assertTrue(BGR.TIN.entity.validate('207271885'))
+        self.assertTrue(BGR.TIN.entity.validate('114635815'))