Repository: identique/idnumbers (language: python)

Issue:
id number for Venezuela
https://en.wikipedia.org/wiki/National_identification_number#Venezuela


Discussion / hints:
According to the sample doc, like below, it contains 8 digits with 2 dots. I don't know if the leading `V` is a matter.
![image](https://user-images.githubusercontent.com/120368198/224197390-b531d6d0-3b2e-4572-8844-d356829655e5.png)

Another ID is the fiscal id number:
```
Private companies and public entities are assigned a RIF (Fiscal Information Registry) number for taxable purposes. For natural persons, it is their ID number + checksum digit.
```


Fix patch:
diff --git a/idnumbers/nationalid/USA.py b/idnumbers/nationalid/USA.py
index bc38c169..6bcf2524 100644
--- a/idnumbers/nationalid/USA.py
+++ b/idnumbers/nationalid/USA.py
@@ -20,7 +20,7 @@ class SocialSecurityNumber:
         # has checksum function
         'checksum': False,
         # regular expression to validate the id
-        'regexp': re.compile("^(?!666|000|9\\d{2})\\d{3}-(?!00)\\d{2}-(?!0{4})\\d{4}$")
+        'regexp': re.compile(r'^(?!666|000|9\d{2})\d{3}-(?!00)\d{2}-(?!0{4})\d{4}$')
     })
 
     @staticmethod
diff --git a/idnumbers/nationalid/VEN.py b/idnumbers/nationalid/VEN.py
new file mode 100644
index 00000000..470f2b78
--- /dev/null
+++ b/idnumbers/nationalid/VEN.py
@@ -0,0 +1,89 @@
+import re
+from types import SimpleNamespace
+
+from .util import validate_regexp, weighted_modulus_digit
+
+
+def normalize(id_number):
+    """strip out useless characters/whitespaces"""
+    return re.sub(r'[ \-.]', '', id_number)
+
+
+class IDCardNumber:
+    """
+    Venezuela ID card number
+    https://en.wikipedia.org/wiki/National_identification_number#Venezuela
+    """
+    METADATA = SimpleNamespace(**{
+        'iso3166_alpha2': 'VE',
+        # length without insignificant chars
+        'min_length': 9,
+        'max_length': 9,
+        # has parse function
+        'parsable': False,
+        # has checksum function
+        'checksum': False,
+        # regular expression to validate the id
+        'regexp': re.compile(r'^V ?\d{2}\.?\d{3}\.?\d{3}$')
+    })
+
+    @staticmethod
+    def validate(id_number: str) -> bool:
+        """
+        Validate
+        """
+        return validate_regexp(id_number, IDCardNumber.METADATA.regexp)
+
+
+class FiscalInformationNumber:
+    """
+    Venezuela RIF (Fiscal Information Registry) number, Registro de Informacion Fiscal
+    https://en.wikipedia.org/wiki/National_identification_number#Venezuela
+    python version of
+    https://github.com/anghelvalentin/CountryValidator/blob/master/CountryValidator/CountriesValidators/VenezuelaAfricaValidator.cs
+    """
+    METADATA = SimpleNamespace(**{
+        'iso3166_alpha2': 'VE',
+        # length without insignificant chars
+        'min_length': 10,
+        'max_length': 10,
+        # has parse function
+        'parsable': False,
+        # has checksum function
+        'checksum': True,
+        # regular expression to validate the id
+        'regexp': re.compile(r'^[VEJPG]-?\d{8}-?\d$')
+    })
+
+    WEIGHTS = [1, 3, 2, 7, 6, 5, 4, 3, 2]
+    TYPE_MAP = {
+        'V': 4,
+        'E': 8,
+        'J': 12,
+        'P': 16,
+        'G': 20
+    }
+
+    @staticmethod
+    def validate(id_number: str) -> bool:
+        """
+        Validate
+        """
+        return FiscalInformationNumber.checksum(id_number)
+
+    @staticmethod
+    def checksum(id_number: str) -> bool:
+        """algorithm: https://github.com/therezor/ua-tax-number/blob/main/src/Decoder.php"""
+        if not validate_regexp(id_number, FiscalInformationNumber.METADATA.regexp):
+            return False
+        normalized = normalize(id_number)
+        numbers = [FiscalInformationNumber.TYPE_MAP[normalized[0]]] + [int(char) for char in list(normalized[1:])]
+        modulus = weighted_modulus_digit(numbers[:-1], FiscalInformationNumber.WEIGHTS, 11)
+        modulus = modulus if modulus < 10 else 0
+        return modulus == numbers[-1]
+
+
+NationalID = IDCardNumber
+"""alias of IDCardNumber"""
+RIF = FiscalInformationNumber
+"""alias of FiscalInformationNumber"""


Test patch:
diff --git a/tests/nationalid/test_VEN.py b/tests/nationalid/test_VEN.py
new file mode 100644
index 00000000..678afd94
--- /dev/null
+++ b/tests/nationalid/test_VEN.py
@@ -0,0 +1,14 @@
+from unittest import TestCase
+from idnumbers.nationalid import VEN
+
+
+class TestVENValidation(TestCase):
+    def test_normal_case(self):
+        self.assertTrue(VEN.IDCardNumber.validate('V13.150.575'))
+        self.assertTrue(VEN.FiscalInformationNumber.validate('V-05892464-0'))
+        self.assertTrue(VEN.FiscalInformationNumber.validate('J-07013380-5'))
+        self.assertTrue(VEN.FiscalInformationNumber.validate('G-20000041-4'))
+
+    def test_error_case(self):
+        self.assertFalse(VEN.IDCardNumber.validate('X13.150.575'))
+        self.assertFalse(VEN.FiscalInformationNumber.validate('V-12345678-0'))