Launchpad automatic translations update.
[odoo/odoo.git] / addons / base_vat / base_vat.py
index 5cba9ea..6393c0a 100644 (file)
 import string
 
 from osv import osv, fields
-from tools.func import partial
 from tools.translate import _
+from tools.misc import ustr
+import re
+import datetime
 
 _ref_vat = {
     'be': 'BE0477472701', 'at': 'ATU12345675',
@@ -39,7 +41,9 @@ _ref_vat = {
     'nl': 'NL123456782B90', 'pl': 'PL1234567883',
     'pt': 'PT123456789', 'ro': 'RO1234567897',
     'se': 'SE123456789701', 'si': 'SI12345679',
-    'sk': 'SK0012345675', 'el': 'EL12345670'
+    'sk': 'SK0012345675', 'el': 'EL12345670',
+    'mx': 'MXABCD831230T1B',
+
             }
 
 def mult_add(i, j):
@@ -53,16 +57,22 @@ class res_partner(osv.osv):
         vat_country, vat_number = vat[:2].lower(), vat[2:].replace(' ', '')
         return vat_country, vat_number
 
-    def check_vat(self, cr, uid, ids):
+    def check_vat(self, cr, uid, ids, context=None):
         '''
         Check the VAT number depending of the country.
         http://sima-pc.com/nif.php
         '''
-        for partner in self.browse(cr, uid, ids):
+        country_obj = self.pool.get('res.country')
+        for partner in self.browse(cr, uid, ids, context=context):
             if not partner.vat:
                 continue
             vat_country, vat_number = self._split_vat(partner.vat)
             if not hasattr(self, 'check_vat_' + vat_country):
+                #We didn't find the validation method for the country code. If that country code can be found in openerp, this means that it is a valid country code 
+                #and we simply didn't have implemented that function. In that case we continue.
+                if country_obj.search(cr, uid, [('code', 'ilike', vat_country)], context=context):
+                    continue
+                #Otherwise, it means that the country code isn't valid and we return False.
                 return False
             check = getattr(self, 'check_vat_' + vat_country)
             if not check(vat_number):
@@ -76,13 +86,12 @@ class res_partner(osv.osv):
         'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement.")
     }
 
-    def _construct_constraint_msg(self, cr, uid, ids):
+    def _construct_constraint_msg(self, cr, uid, ids, context=None):
         def default_vat_check(cn, vn):
             # by default, a VAT number is valid if:
             #  it starts with 2 letters
             #  has more than 3 characters
             return cn[0] in string.ascii_lowercase and cn[1] in string.ascii_lowercase
-
         vat_country, vat_number = self._split_vat(self.browse(cr, uid, ids)[0].vat)
         if default_vat_check(vat_country, vat_number):
             vat_no = vat_country in _ref_vat and _ref_vat[vat_country] or 'Country Code + Vat Number'
@@ -151,10 +160,6 @@ class res_partner(osv.osv):
         check = 11 - (sum % 11)
         if check == 11:
             check = 0
-#        if check == 10:
-#            return False
-#        if check != int(vat[9]):
-#            return False
         return True
 
     def check_vat_cy(self, vat):
@@ -413,8 +418,6 @@ class res_partner(osv.osv):
             check = 10 - (sum % 10)
             if check == 10:
                 check = 0
-#            if check != int(vat[8]):
-#                return False
             return True
         #Legal persons with non-profit aim
         elif vat[0] in ('N', 'P', 'Q', 'R', 'S', 'W'):
@@ -570,8 +573,12 @@ class res_partner(osv.osv):
             sum = 8 * int(vat[0]) + 7 * int(vat[1]) + 6 * int(vat[2]) + \
                     5 * int(vat[3]) + 4 * int(vat[4]) + 3 * int(vat[5]) + \
                     2 * int(vat[6]) + 10 * int(vat[7]) + int(vat[8])
-            if sum % 97 != 0:
-                return False
+            if int(vat[0:3]) > 100:
+                if sum % 97 not in (0, 55, 42):
+                    return False
+            else:
+                if sum % 97 != 0:
+                    return False
             return True
         elif len(vat) in (12, 13):
             try:
@@ -715,8 +722,6 @@ class res_partner(osv.osv):
             return False
         if int(vat[7:10]) > 100 and int(vat[7:10]) < 120:
             return False
-        if int(vat[7:10]) > 121:
-            return False
 
         sum = int(vat[0]) + mult_add(2, int(vat[1])) + int(vat[2]) + \
                 mult_add(2, int(vat[3])) + int(vat[4]) + \
@@ -924,8 +929,6 @@ class res_partner(osv.osv):
         check = 11 - (sum % 11)
         if check == 10 or check == 11:
             check = 0
-#        if check != int(vat[8]):
-#            return False
         return True
 
     def check_vat_ro(self, vat):
@@ -992,9 +995,6 @@ class res_partner(osv.osv):
         if int(vat[9:11]) < 0:
             return False
 
-#        if int(vat[-2:]) != 1:
-#            return False
-
         sum = mult_add(2, int(vat[0])) + int(vat[1]) + \
                 mult_add(2, int(vat[2])) + int(vat[3]) + \
                 mult_add(2, int(vat[4])) + int(vat[5]) + \
@@ -1043,7 +1043,7 @@ class res_partner(osv.osv):
         if len(vat) not in(9, 10):
             return False
 
-        if int(vat[0:2]) == 0 and len(vat) == 10:
+        if int(vat[0:2]) in (0, 10, 20) and len(vat) == 10:
             return True
 
         if len(vat) == 10:
@@ -1075,6 +1075,36 @@ class res_partner(osv.osv):
                 return False
         return True
 
+    __check_vat_mx_re = re.compile(r"(?P<primeras>[A-Za-z\xd1\xf1&]{3,4})" \
+                                    r"[ \-_]?" \
+                                    r"(?P<ano>[0-9]{2})(?P<mes>[01][0-9])(?P<dia>[0-3][0-9])" \
+                                    r"[ \-_]?" \
+                                    r"(?P<code>[A-Za-z0-9&\xd1\xf1]{3})$")
+    
+    def check_vat_mx(self, vat):
+        ''' Mexican VAT verification
+        
+        Verificar RFC México
+        '''
+        # we convert to 8-bit encoding, to help the regex parse only bytes
+        vat = ustr(vat).encode('iso8859-1')
+        m = self.__check_vat_mx_re.match(vat)
+        if not m:
+            #No valid format
+            return False
+        try:
+            ano = int(m.group('ano'))
+            if ano > 30:
+                ano = 1900 + ano
+            else:
+                ano = 2000 + ano
+            datetime.date(ano, int(m.group('mes')), int(m.group('dia')))
+        except ValueError:
+            return False
+        
+        #Valid format and valid date
+        return True
+        
 res_partner()
 
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: