ソースを参照

done with the validations

Radu Boncea 6 年 前
コミット
9261adaa3d

+ 23 - 0
README.md

@@ -1 +1,24 @@
 # A library for checking on European VAT formats
+
+[![Build Status](https://travis-ci.com/agilegeeks/pyVat.svg?branch=master)](https://travis-ci.com/agilegeeks/pyVat)
+
+pyVat is a complete library that validates vat number formats in EU member countries. The algorithms used are described in /doc/VIES-VAT Validation Routines-v15.0.doc
+
+## Compatibility
+Python >= 2.7
+
+## Installation
+    $ pip install pyvat-format-checker
+
+## Usage
+```python
+from pyVat.api import Validator
+validator = Validator('ATU10223006')
+if validator.validate() is True:
+    print ("The VAT number has a valid format")
+else:
+    print ("Invalid VAT number format for country %s" % validator.country_code)
+
+```
+## Issues
+- The Croatian format is missing the algorithm. The validations is done purely based on regular expressions.

+ 31 - 34
pyVat/api.py

@@ -24,39 +24,36 @@ import re
 import sys
 
 
-VAT_NUMBER_REGEXPS = {
-    'AT': re.compile(r'^U\d{8}$', re.IGNORECASE),
-    'BE': re.compile(r'^\d{9,10}$'),
-    'BG': re.compile(r'^\d{9,10}$'),
-    'CY': re.compile(r'^\d{8}[a-z]$', re.IGNORECASE),
-    'CZ': re.compile(r'^\d{8,10}$'),
-    'DE': re.compile(r'^\d{9}$'),
-    'DK': re.compile(r'^\d{8}$'),
-    'EE': re.compile(r'^\d{9}$'),
-    'ES': re.compile(r'^[\da-z]\d{7}[\da-z]$', re.IGNORECASE),
-    'FI': re.compile(r'^\d{8}$'),
-    'FR': re.compile(r'^[\da-z]{2}\d{9}$', re.IGNORECASE),
-    'GB': re.compile(r'^((\d{9})|(\d{12})|(GD\d{3})|(HA\d{3}))$',
-                     re.IGNORECASE),
-    'GR': re.compile(r'^\d{9}$'),
-    'HR': re.compile(r'^\d{11}$'),
-    'HU': re.compile(r'^\d{8}$'),
-    'IE': re.compile(r'^((\d{7}[a-z])|(\d[a-z]\d{5}[a-z])|(\d{6,7}[a-z]{2}))$',
-                     re.IGNORECASE),
-    'IT': re.compile(r'^\d{11}$'),
-    'LT': re.compile(r'^((\d{9})|(\d{12}))$'),
-    'LU': re.compile(r'^\d{8}$'),
-    'LV': re.compile(r'^\d{11}$'),
-    'MT': re.compile(r'^\d{8}$'),
-    'NL': re.compile(r'^\d{9}B\d{2,3}$', re.IGNORECASE),
-    'PL': re.compile(r'^\d{10}$'),
-    'PT': re.compile(r'^\d{9}$'),
-    'RO': re.compile(r'^\d{2,10}$'),
-    'SE': re.compile(r'^\d{12}$'),
-    'SI': re.compile(r'^\d{8}$'),
-    'SK': re.compile(r'^\d{10}$'),
-}
-
+EU_COUNTRIES = [
+    'AT',
+    'BE',
+    'BG',
+    'CY',
+    'CZ',
+    'DK',
+    'EE',
+    'FI',
+    'FR',
+    'DE',
+    'GR',
+    'HR',
+    'HU',
+    'IE',
+    'IT',
+    'LV',
+    'LT',
+    'LU',
+    'MT',
+    'NL',
+    'PL',
+    'PT',
+    'RO',
+    'SK',
+    'SI',
+    'ES',
+    'SE',
+    'GB'
+]
 def load_class(module_name, class_name):
     mod = __import__(module_name, fromlist=[class_name])
     klass = getattr(mod, class_name)
@@ -115,7 +112,7 @@ class Validator(object):
         if vat_country_code == 'EL':
             vat_country_code = 'GR'
 
-        if vat_country_code not in VAT_NUMBER_REGEXPS.keys():
+        if vat_country_code not in EU_COUNTRIES:
             raise VatValidationError('Invalid VAT country')
 
         if len(vat_number)>2:

+ 2 - 2
pyVat/validators/at.py

@@ -37,7 +37,7 @@ class Validator(GenericValidator):
 
         vat_number = str(vat_number)
 
-        checknum = int (vat_number[8])
+        checksum = int (vat_number[8])
 
         r = 0
         for i in range(3,8,2):
@@ -50,4 +50,4 @@ class Validator(GenericValidator):
 
         c9 = (10 - (r+c)%10) % 10
 
-        return checknum == c9
+        return checksum == c9

+ 2 - 2
pyVat/validators/be.py

@@ -37,7 +37,7 @@ class Validator(GenericValidator):
 
         vat_number = str(vat_number)
 
-        checknum = int(vat_number[8:10])
+        checksum = int(vat_number[8:10])
         checkval = 97 - ( int(vat_number[:8]) % 97 )
 
-        return checkval == checknum
+        return checkval == checksum

+ 8 - 8
pyVat/validators/bg.py

@@ -40,7 +40,7 @@ class Validator(GenericValidator):
 
         # if is legal entity
         if (len(vat_number)==9):
-            checknum = int(vat_number[8])
+            checksum = int(vat_number[8])
             a1 = self.sum_weights(list(range(1,9)), vat_number[:8])
             r1 = a1 % 11
 
@@ -54,10 +54,10 @@ class Validator(GenericValidator):
             else:
                 r = r1
 
-            return checknum == r
+            return checksum == r
 
         # physical person
-        checknum = int(vat_number[9])
+        checksum = int(vat_number[9])
         weights = [2, 4, 8, 5, 10, 9, 7, 3, 6]
         a1 = self.sum_weights(weights, vat_number[:9])
         r1 = a1 % 11
@@ -65,19 +65,19 @@ class Validator(GenericValidator):
             r = 0
         else:
             r = r1
-        if checknum == r:
+        if checksum == r:
             return True
 
         # foreigners
-        checknum = int(vat_number[9])
+        checksum = int(vat_number[9])
         weights = [21, 19, 17, 13, 11, 9, 7, 3, 1]
         a1 = self.sum_weights(weights, vat_number[:9])
         r = a1 % 10
-        if checknum == r:
+        if checksum == r:
             return True
 
         # others
-        checknum = int(vat_number[9])
+        checksum = int(vat_number[9])
         weights = [4, 3, 2, 7, 6, 5, 4, 3, 2]
         a1 = self.sum_weights(weights, vat_number[:9])
         r1 = 11 - a1 % 11
@@ -87,7 +87,7 @@ class Validator(GenericValidator):
             return False
         else:
             r = r1
-        if checknum == r:
+        if checksum == r:
             return True
 
         return False

+ 4 - 4
pyVat/validators/cz.py

@@ -43,7 +43,7 @@ class Validator(GenericValidator):
         if len(vat_number) == 8:
             if vat_number[0] == str('9'):
                 return False
-            checknum = int (vat_number[7])
+            checksum = int (vat_number[7])
             a1 = self.sum_weights(list(range(8,1,-1)), vat_number[:8])
             if a1 % 11 == 0:
                 a2 = a1 + 11
@@ -51,14 +51,14 @@ class Validator(GenericValidator):
                 a2 = math.ceil(a1/11) * 11
             c8 = (a2 - a1) % 10
 
-            return checknum == c8
+            return checksum == c8
 
         # individuals
         if len(vat_number) == 9:
 
             # special cases
             if vat_number[0] == str('6'):
-                checknum = int(vat_number[8])
+                checksum = int(vat_number[8])
                 a1 = self.sum_weights(list(range(8, 1, -1)), vat_number[1:8])
                 if a1 % 11 == 0:
                     a2 = a1 + 11
@@ -78,7 +78,7 @@ class Validator(GenericValidator):
                     10: 9,
                     11: 8
                 }
-                return checknum == last_digit_mapping[d]
+                return checksum == last_digit_mapping[d]
             else:
                 # common individuals
                 if int(vat_number[:2])>53:

+ 2 - 2
pyVat/validators/de.py

@@ -37,7 +37,7 @@ class Validator(GenericValidator):
 
         vat_number = str(vat_number)
 
-        checknum = int (vat_number[8])
+        checksum = int (vat_number[8])
 
         if vat_number[0] == str('0'):
             return False
@@ -55,4 +55,4 @@ class Validator(GenericValidator):
         else:
             c9 = r
 
-        return checknum == c9
+        return checksum == c9

+ 2 - 2
pyVat/validators/ee.py

@@ -41,10 +41,10 @@ class Validator(GenericValidator):
         if vat_number[:2] != str('10'):
             return False
 
-        checknum = int(vat_number[8])
+        checksum = int(vat_number[8])
 
         a1 = self.sum_weights([3, 7, 1, 3, 7, 1, 3, 7], vat_number)
         a2 = math.ceil(a1 / 10) * 10
         c9 = a2 - a1
 
-        return checknum == c9
+        return checksum == c9

+ 5 - 5
pyVat/validators/es.py

@@ -37,7 +37,7 @@ class Validator(GenericValidator):
             return False
 
         vat_number = str(vat_number)
-        checknum = vat_number[8].upper()
+        checksum = vat_number[8].upper()
 
         try:
             int( vat_number[8] )
@@ -83,7 +83,7 @@ class Validator(GenericValidator):
                 9: 'I',
                 10: 'J'
             }
-            if checknum == last_digit_mapping[r]:
+            if checksum == last_digit_mapping[r]:
                 return True
 
         # # Physical persons
@@ -132,11 +132,11 @@ class Validator(GenericValidator):
                     22: 'K',
                     23: 'E'
                 }
-                if checknum == last_digit_mapping[r]:
+                if checksum == last_digit_mapping[r]:
                     return True
 
         if c9_is_number:
-            checknum = int(vat_number[8])
+            checksum = int(vat_number[8])
             s1 = int(vat_number[2]) + int(vat_number[4]) + int(vat_number[6])
             s2 = 0
             for i in range(1, 8, 2):
@@ -144,7 +144,7 @@ class Validator(GenericValidator):
                 s2 = s2 + int(digit / 5) + (2 * digit) % 10
             r = 10 - (s1 + s2) % 10
 
-            return checknum == (r % 10)
+            return checksum == (r % 10)
 
         return False
 

+ 3 - 3
pyVat/validators/fi.py

@@ -37,13 +37,13 @@ class Validator(GenericValidator):
 
         vat_number = str(vat_number)
 
-        checknum = int(vat_number[7])
+        checksum = int(vat_number[7])
 
         r = 11 - self.sum_weights([7,9,10,5,8,4,2], vat_number) % 11
         if r == 0:
             return False
         elif r == 11:
-            if checknum != 0:
+            if checksum != 0:
                 return False
         else:
-            return checknum == r
+            return checksum == r

+ 2 - 2
pyVat/validators/gr.py

@@ -38,10 +38,10 @@ class Validator(GenericValidator):
 
         vat_number = str(vat_number)
 
-        checknum = int(vat_number[8])
+        checksum = int(vat_number[8])
 
         a1 = self.sum_weights([256, 128, 64, 32, 16, 8, 4, 2], vat_number)
         a2 = a1 % 11
         c9 = a2 % 10
 
-        return checknum == c9
+        return checksum == c9

+ 39 - 0
pyVat/validators/hr.py

@@ -0,0 +1,39 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{11}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        return True

+ 49 - 0
pyVat/validators/hu.py

@@ -0,0 +1,49 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{8}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        checksum = vat_number[7]
+        a1 = str(self.sum_weights([9,7,3,1,9,7,3],vat_number))
+        if a1[-1] == '0':
+            checkval = '0'
+        else:
+            checkval = str(10 - int(a1[-1]))
+        return checkval == checksum
+
+
+

+ 2 - 2
pyVat/validators/ie.py

@@ -63,7 +63,7 @@ class Validator(GenericValidator):
             return False
 
         vat_number = str(vat_number)
-        checknum = vat_number[7]
+        checksum = vat_number[7]
 
         #check for old style - second char sould be a letter
         try:
@@ -79,4 +79,4 @@ class Validator(GenericValidator):
         else:
             r = r = self.sum_weights(list(range(8,1,-1)), vat_number) % 23
 
-        return checknum == Validator.check_char_mapping[r]
+        return checksum == Validator.check_char_mapping[r]

+ 2 - 2
pyVat/validators/it.py

@@ -37,7 +37,7 @@ class Validator(GenericValidator):
             return False
 
         vat_number = str(vat_number)
-        checknum = int(vat_number[10])
+        checksum = int(vat_number[10])
 
         c8910 = int(vat_number[7:10])
         if c8910 not in range(1, 102) and c8910 not in [120, 121, 999, 888]:
@@ -54,4 +54,4 @@ class Validator(GenericValidator):
 
         checkval = (10 - (s1 + s2) % 10) % 10
 
-        return checknum == checkval
+        return checksum == checkval

+ 5 - 5
pyVat/validators/lt.py

@@ -40,7 +40,7 @@ class Validator(GenericValidator):
 
         # Legal entities
         if len(vat_number) == 9:
-            checknum = int(vat_number[8])
+            checksum = int(vat_number[8])
             if int(vat_number[7]) != 1:
                 return False
             r1 = self.sum_weights(list(range(1,9)), vat_number) % 11
@@ -55,19 +55,19 @@ class Validator(GenericValidator):
                     checkval = r2
         else:
             # Temporarily registered taxpayers
-            checknum = int(vat_number[11])
+            checksum = int(vat_number[11])
             if int(vat_number[10]) != 1:
                 return False
 
-            rng = list(range(1,10) + range(1,3))
+            rng = list(range(1,10)) + list(range(1,3))
             r1 = self.sum_weights(rng, vat_number) % 11
             if r1 != 10:
                 checkval = r1
             else:
-                rng = list(range(3, 10) + range(1,5))
+                rng = list(range(3, 10)) + list(range(1,5))
                 r2 = self.sum_weights(rng, vat_number) % 11
                 if r2 == 10:
                     checkval = 0
                 else:
                     checkval = r2
-        return checknum == checkval
+        return checksum == checkval

+ 3 - 17
pyVat/validators/lu.py

@@ -37,21 +37,7 @@ class Validator(GenericValidator):
             return False
 
         vat_number = str(vat_number)
-        checknum = int(vat_number[10])
+        checksum = int(vat_number[6:])
+        checkval = int(vat_number[:6]) % 89
+        return checksum == checkval
 
-        c8910 = int(vat_number[7:10])
-        if c8910 not in range(1, 102) and c8910 not in [120, 121, 999, 888]:
-            return False
-
-        s1 = 0
-        for i in range(0,9,2):
-            s1 = s1 + int(vat_number[i])
-
-        s2 = 0
-        for i in range(1,10,2):
-            n = int(vat_number[i])
-            s2 = s2 + int(n/5) + (2 * n) % 10
-
-        checkval = (10 - (s1 + s2) % 10) % 10
-
-        return checknum == checkval

+ 65 - 0
pyVat/validators/lv.py

@@ -0,0 +1,65 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+import datetime
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{11}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        # Legal entities
+        if int(vat_number[0]) > 3:
+            checksum = int(vat_number[10])
+            a1 = self.sum_weights([9,1,4,8,3,10,2,5,7,6], vat_number)
+            r = 3 - a1 % 11
+            if r < -1:
+                checkval = r + 11
+            elif r > 1:
+                checkval = r
+            else:
+                return False
+
+            return checkval == checksum
+        # Natural persons
+        else:
+            try:
+                datetime.datetime.strptime(vat_number[:6], '%d%m%y')
+            except:
+                return False
+            else:
+                return True
+
+
+

+ 52 - 0
pyVat/validators/mt.py

@@ -0,0 +1,52 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{8}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+        checksum = int(vat_number[6:])
+
+        if int(vat_number[:6])<= 100000:
+            return False
+
+        a1 = self.sum_weights([3,4,6,7,8,9], vat_number)
+        r = 37 - a1 % 37
+        if r == 0:
+            checkval = 37
+        else:
+            checkval = r
+        return checksum == checkval
+

+ 52 - 0
pyVat/validators/nl.py

@@ -0,0 +1,52 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{9}B\d{2}$', re.IGNORECASE)
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        if vat_number[10:] == '00':
+            return False
+
+        checksum = int(vat_number[8])
+
+        a1 = self.sum_weights(list(range(9,1,-1)), vat_number)
+        a2 = a1 % 11
+        if a2 == 10:
+            return False
+
+        return checksum == a2
+

+ 48 - 0
pyVat/validators/pl.py

@@ -0,0 +1,48 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{10}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        checksum = int(vat_number[9])
+
+        a1 = self.sum_weights([6,5,7,2,3,4,5,6,7], vat_number)
+        r = a1 % 11
+        if r == 10:
+            return False
+
+        return checksum == r

+ 50 - 0
pyVat/validators/pt.py

@@ -0,0 +1,50 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{9}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        if vat_number[0] == '0':
+            return False
+
+        checksum = int(vat_number[8])
+        a1 = self.sum_weights(list(range(9,1,-1)), vat_number)
+        r = 11 - a1 % 11
+        if r in [10,11]:
+            r = 0
+        return checksum == r
+

+ 3 - 0
pyVat/validators/ro.py

@@ -43,6 +43,9 @@ class Validator(GenericValidator):
 
         vat_number = str(vat_number)
 
+        if vat_number[0] == '0':
+            return False
+
         vat_number = vat_number.rjust(10,str('0'))
         checksum = int (vat_number[9])
         weights = [7, 5, 3, 2, 1, 7, 5, 3, 2]

+ 53 - 0
pyVat/validators/se.py

@@ -0,0 +1,53 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{12}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        if int(vat_number[10:]) not in range(1,95):
+            return False
+
+        checksum = int(vat_number[9])
+        r = 0
+        for i in range(0,9,2):
+            n = int(vat_number[i])
+            r = r + int(n / 5) + (2 * n) % 10
+        c = 0
+        for i in (range(1,8,2)):
+            c = c + int(vat_number[i])
+        checkval = (10 - (r + c) % 10) % 10
+        return checksum == checkval

+ 54 - 0
pyVat/validators/si.py

@@ -0,0 +1,54 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{8}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        if int(vat_number[:7])<1000000:
+            return False
+
+        checksum = int(vat_number[7])
+        a1 = self.sum_weights(list(range(8,1,-1)), vat_number)
+        r = 11 - a1 % 11
+        if r == 10:
+            checkval = 0
+        elif r == 11:
+            return False
+        else:
+            checkval = r
+
+        return checksum == checkval

+ 48 - 0
pyVat/validators/sk.py

@@ -0,0 +1,48 @@
+# Copyright 2018 Agile Geeks
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+# and associated documentation files (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge, publish, distribute,
+# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
+# is furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in all copies or substantial
+# portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from __future__ import (
+    unicode_literals,
+    print_function,
+    division
+)
+import re
+from .generic import GenericValidator
+
+
+class Validator(GenericValidator):
+    """
+    For rules see /docs/VIES-VAT Validation Routines-v15.0.doc
+    """
+
+    def __init__(self):
+        self.regexp = re.compile(r'^\d{10}$')
+
+    def validate(self, vat_number):
+        if super(Validator, self).validate(vat_number) is False:
+            return False
+
+        vat_number = str(vat_number)
+
+        if int(vat_number[0]) == 0:
+            return False
+
+        if int(vat_number[2]) not in [2,3,4,7,8,9]:
+            return False
+
+        r = int(vat_number) % 11
+        return r == 0

+ 106 - 16
tests/test_validator.py

@@ -21,21 +21,6 @@ from pyVat.api import Validator
 
 class TestValidator(unittest.TestCase):
 
-    def test_ro(self):
-        validator = Validator('RO2785503')
-        self.assertTrue( validator.validate() )
-        self.assertEqual( validator.country_code, 'RO' )
-        self.assertEqual( validator.vat_number, '2785503' )
-        validator = Validator('2785503', 'RO')
-        self.assertTrue(validator.validate())
-
-        validator = Validator('ro 278  5503')
-        self.assertTrue(validator.validate())
-        self.assertEqual(validator.country_code, 'RO')
-
-        validator = Validator('RO2785500')
-        self.assertFalse(validator.validate())
-
     def test_at(self):
         validator = Validator('ATU10223006')
         self.assertTrue(validator.validate())
@@ -265,6 +250,22 @@ class TestValidator(unittest.TestCase):
         validator = Validator('GB434031494')
         self.assertTrue(validator.validate())
 
+    def test_hr(self):
+        validator = Validator('HR99999999999')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'HR')
+        validator = Validator('HR9999999999')
+        self.assertFalse(validator.validate())
+
+    def test_hu(self):
+        # format 1 - 5 chars
+        validator = Validator('HU21376414')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'HU')
+        validator = Validator('hu 10597190')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'HU')
+
 
     def test_ie(self):
         # old style format
@@ -286,7 +287,7 @@ class TestValidator(unittest.TestCase):
         self.assertFalse(validator.validate())
 
     def test_lt(self):
-        #juridical entities
+        # juridical entities
         validator = Validator('LT213179412')
         self.assertTrue(validator.validate())
         self.assertEqual(validator.country_code, 'LT')
@@ -299,5 +300,94 @@ class TestValidator(unittest.TestCase):
         validator = Validator('LT290061371324')
         self.assertFalse(validator.validate())
 
+    def test_lu(self):
+        validator = Validator('LU10000356')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'LU')
+        validator = Validator('LU14516304')
+        self.assertTrue(validator.validate())
+        validator = Validator('LU10000355')
+        self.assertFalse(validator.validate())
+
+    def test_lv(self):
+        # juridical entities
+        validator = Validator('LV40003009497')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'LV')
+        validator = Validator('LV40003009498')
+        self.assertFalse(validator.validate())
+
+        # natural persons
+        validator = Validator('LV07091910933')
+        self.assertTrue(validator.validate())
+        validator = Validator('LV32091910933')
+        self.assertFalse(validator.validate())
+
+    def test_mt(self):
+        validator = Validator('MT15121333')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'MT')
+        validator = Validator('MT15121332')
+        self.assertFalse(validator.validate())
+
+    def test_nl(self):
+        validator = Validator('NL010000446B01')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'NL')
+        validator = Validator('NL000000446B01')
+        self.assertFalse(validator.validate())
+
+    def test_pl(self):
+        validator = Validator('PL5260001246')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'PL')
+        validator = Validator('PL5260001244')
+        self.assertFalse(validator.validate())
+
+    def test_pt(self):
+        validator = Validator('PT502757191')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'PT')
+        validator = Validator('PT502757190')
+        self.assertFalse(validator.validate())
+
+    def test_ro(self):
+        validator = Validator('RO2785503')
+        self.assertTrue( validator.validate() )
+        self.assertEqual( validator.country_code, 'RO' )
+        self.assertEqual( validator.vat_number, '2785503' )
+        validator = Validator('2785503', 'RO')
+        self.assertTrue(validator.validate())
+
+        validator = Validator('ro 99 908')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'RO')
+
+        validator = Validator('RO2785500')
+        self.assertFalse(validator.validate())
+
+    def test_se(self):
+        validator = Validator('SE556188840401')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'SE')
+        validator = Validator('SE556183840407')
+        self.assertFalse(validator.validate())
+
+    def test_si(self):
+        validator = Validator('SI15012557')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'SI')
+        validator = Validator('SI15012556')
+        self.assertFalse(validator.validate())
+
+    def test_sk(self):
+        validator = Validator('SK4030000007')
+        self.assertTrue(validator.validate())
+        self.assertEqual(validator.country_code, 'SK')
+        validator = Validator('SK5407062531')
+        self.assertFalse(validator.validate())
+        validator = Validator('SK0407062531')
+        self.assertFalse(validator.validate())
+
 if __name__ == '__main__':
     unittest.main()