web/lib/django/contrib/localflavor/ro/forms.py
changeset 0 0d40e90630ef
child 29 cc9b7e14412b
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 # -*- coding: utf-8 -*-
       
     2 """
       
     3 Romanian specific form helpers.
       
     4 """
       
     5 
       
     6 import re
       
     7 
       
     8 from django.forms import ValidationError, Field, RegexField, Select
       
     9 from django.forms.fields import EMPTY_VALUES
       
    10 from django.utils.translation import ugettext_lazy as _
       
    11 
       
    12 class ROCIFField(RegexField):
       
    13     """
       
    14     A Romanian fiscal identity code (CIF) field
       
    15 
       
    16     For CIF validation algorithm see http://www.validari.ro/cui.html
       
    17     """
       
    18     default_error_messages = {
       
    19         'invalid': _("Enter a valid CIF."),
       
    20     }
       
    21 
       
    22     def __init__(self, *args, **kwargs):
       
    23         super(ROCIFField, self).__init__(r'^[0-9]{2,10}', max_length=10,
       
    24                 min_length=2, *args, **kwargs)
       
    25 
       
    26     def clean(self, value):
       
    27         """
       
    28         CIF validation
       
    29         """
       
    30         value = super(ROCIFField, self).clean(value)
       
    31         if value in EMPTY_VALUES:
       
    32             return u''
       
    33         # strip RO part
       
    34         if value[0:2] == 'RO':
       
    35             value = value[2:]
       
    36         key = '753217532'[::-1]
       
    37         value = value[::-1]
       
    38         key_iter = iter(key)
       
    39         checksum = 0
       
    40         for digit in value[1:]:
       
    41             checksum += int(digit) * int(key_iter.next())
       
    42         checksum = checksum * 10 % 11
       
    43         if checksum == 10:
       
    44             checksum = 0
       
    45         if checksum != int(value[0]):
       
    46             raise ValidationError(self.error_messages['invalid'])
       
    47         return value[::-1]
       
    48 
       
    49 class ROCNPField(RegexField):
       
    50     """
       
    51     A Romanian personal identity code (CNP) field
       
    52 
       
    53     For CNP validation algorithm see http://www.validari.ro/cnp.html
       
    54     """
       
    55     default_error_messages = {
       
    56         'invalid': _("Enter a valid CNP."),
       
    57     }
       
    58 
       
    59     def __init__(self, *args, **kwargs):
       
    60         super(ROCNPField, self).__init__(r'^[1-9][0-9]{12}', max_length=13,
       
    61             min_length=13, *args, **kwargs)
       
    62 
       
    63     def clean(self, value):
       
    64         """
       
    65         CNP validations
       
    66         """
       
    67         value = super(ROCNPField, self).clean(value)
       
    68         # check birthdate digits
       
    69         import datetime
       
    70         try:
       
    71             datetime.date(int(value[1:3]),int(value[3:5]),int(value[5:7]))
       
    72         except:
       
    73             raise ValidationError(self.error_messages['invalid'])
       
    74         # checksum
       
    75         key = '279146358279'
       
    76         checksum = 0
       
    77         value_iter = iter(value)
       
    78         for digit in key:
       
    79             checksum += int(digit) * int(value_iter.next())
       
    80         checksum %= 11
       
    81         if checksum == 10:
       
    82             checksum = 1
       
    83         if checksum != int(value[12]):
       
    84             raise ValidationError(self.error_messages['invalid'])
       
    85         return value
       
    86 
       
    87 class ROCountyField(Field):
       
    88     """
       
    89     A form field that validates its input is a Romanian county name or
       
    90     abbreviation. It normalizes the input to the standard vehicle registration
       
    91     abbreviation for the given county
       
    92 
       
    93     WARNING: This field will only accept names written with diacritics; consider
       
    94     using ROCountySelect if this behavior is unnaceptable for you
       
    95     Example:
       
    96         Argeş => valid
       
    97         Arges => invalid
       
    98     """
       
    99     default_error_messages = {
       
   100         'invalid': u'Enter a Romanian county code or name.',
       
   101     }
       
   102 
       
   103     def clean(self, value):
       
   104         from ro_counties import COUNTIES_CHOICES
       
   105         super(ROCountyField, self).clean(value)
       
   106         if value in EMPTY_VALUES:
       
   107             return u''
       
   108         try:
       
   109             value = value.strip().upper()
       
   110         except AttributeError:
       
   111             pass
       
   112         # search for county code
       
   113         for entry in COUNTIES_CHOICES:
       
   114             if value in entry:
       
   115                 return value
       
   116         # search for county name
       
   117         normalized_CC = []
       
   118         for entry in COUNTIES_CHOICES:
       
   119             normalized_CC.append((entry[0],entry[1].upper()))
       
   120         for entry in normalized_CC:
       
   121             if entry[1] == value:
       
   122                 return entry[0]
       
   123         raise ValidationError(self.error_messages['invalid'])
       
   124 
       
   125 class ROCountySelect(Select):
       
   126     """
       
   127     A Select widget that uses a list of Romanian counties (judete) as its
       
   128     choices.
       
   129     """
       
   130     def __init__(self, attrs=None):
       
   131         from ro_counties import COUNTIES_CHOICES
       
   132         super(ROCountySelect, self).__init__(attrs, choices=COUNTIES_CHOICES)
       
   133 
       
   134 class ROIBANField(RegexField):
       
   135     """
       
   136     Romanian International Bank Account Number (IBAN) field
       
   137 
       
   138     For Romanian IBAN validation algorithm see http://validari.ro/iban.html
       
   139     """
       
   140     default_error_messages = {
       
   141         'invalid': _('Enter a valid IBAN in ROXX-XXXX-XXXX-XXXX-XXXX-XXXX format'),
       
   142     }
       
   143 
       
   144     def __init__(self, *args, **kwargs):
       
   145         super(ROIBANField, self).__init__(r'^[0-9A-Za-z\-\s]{24,40}$',
       
   146                 max_length=40, min_length=24, *args, **kwargs)
       
   147 
       
   148     def clean(self, value):
       
   149         """
       
   150         Strips - and spaces, performs country code and checksum validation
       
   151         """
       
   152         value = super(ROIBANField, self).clean(value)
       
   153         value = value.replace('-','')
       
   154         value = value.replace(' ','')
       
   155         value = value.upper()
       
   156         if value[0:2] != 'RO':
       
   157             raise ValidationError(self.error_messages['invalid'])
       
   158         numeric_format = ''
       
   159         for char in value[4:] + value[0:4]:
       
   160             if char.isalpha():
       
   161                 numeric_format += str(ord(char) - 55)
       
   162             else:
       
   163                 numeric_format += char
       
   164         if int(numeric_format) % 97 != 1:
       
   165             raise ValidationError(self.error_messages['invalid'])
       
   166         return value
       
   167 
       
   168 class ROPhoneNumberField(RegexField):
       
   169     """Romanian phone number field"""
       
   170     default_error_messages = {
       
   171         'invalid': _('Phone numbers must be in XXXX-XXXXXX format.'),
       
   172     }
       
   173 
       
   174     def __init__(self, *args, **kwargs):
       
   175         super(ROPhoneNumberField, self).__init__(r'^[0-9\-\(\)\s]{10,20}$',
       
   176                 max_length=20, min_length=10, *args, **kwargs)
       
   177 
       
   178     def clean(self, value):
       
   179         """
       
   180         Strips -, (, ) and spaces. Checks the final length.
       
   181         """
       
   182         value = super(ROPhoneNumberField, self).clean(value)
       
   183         value = value.replace('-','')
       
   184         value = value.replace('(','')
       
   185         value = value.replace(')','')
       
   186         value = value.replace(' ','')
       
   187         if len(value) != 10:
       
   188             raise ValidationError(self.error_messages['invalid'])
       
   189         return value
       
   190 
       
   191 class ROPostalCodeField(RegexField):
       
   192     """Romanian postal code field."""
       
   193     default_error_messages = {
       
   194         'invalid': _('Enter a valid postal code in the format XXXXXX'),
       
   195     }
       
   196 
       
   197     def __init__(self, *args, **kwargs):
       
   198         super(ROPostalCodeField, self).__init__(r'^[0-9][0-8][0-9]{4}$',
       
   199                 max_length=6, min_length=6, *args, **kwargs)
       
   200