Ticket #11768: forms.py

File forms.py, 3.8 KB (added by marcoslhc, 15 years ago)
Line 
1# -*- coding: utf-8 -*-
2"""
3VE-specific Form helpers.
4"""
5
6from django.forms import ValidationError
7from django.forms.fields import RegexField, CharField, Select, EMPTY_VALUES
8from django.utils.encoding import smart_unicode
9from django.utils.translation import ugettext_lazy as _
10
11class VEStateSelect(Select):
12 """
13 A Select widget that uses a list of Venezuelan States
14 as its choices.
15 """
16 def __init__(self, attrs=None):
17 from ve_states import STATE_CHOICES
18 super(VEStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
19
20class VEPostalCodeField(RegexField):
21 """
22 A field that accepts a 'classic' XXXX Postal Code
23 """
24 default_error_messages = {
25 'invalid': _("Enter a postal code in the format XXXX."),
26 }
27
28 def __init__(self, *args, **kwargs):
29 super(ARPostalCodeField, self).__init__(r'^\d{4}$',
30 min_length=4, max_length=4, *args, **kwargs)
31
32 def clean(self, value):
33 value = super(VEPostalCodeField, self).clean(value)
34 if value in EMPTY_VALUES:
35 return u''
36 if len(value) not in (4, 8):
37 raise ValidationError(self.error_messages['invalid'])
38 if len(value) == 4:
39 return u'%s' % (value)
40 return value
41
42class CIField(CharField):
43 """
44 A field that validates 'Cédula de Identidad' (CI) numbers.
45 """
46 default_error_messages = {
47 'invalid': _("This field requires only numbers."),
48 'max_digits': _("This field requires 7 or 8 digits."),
49 }
50
51 def __init__(self, *args, **kwargs):
52 super(CIField, self).__init__(max_length=10, min_length=7, *args,
53 **kwargs)
54
55 def clean(self, value):
56 """
57 Value can be a string either in the [X]X.XXX.XXX or [X]XXXXXXX formats.
58 """
59 value = super(CIField, self).clean(value)
60 if value in EMPTY_VALUES:
61 return u''
62 if not value.isdigit():
63 value = value.replace('.', '')
64 if not value.isdigit():
65 raise ValidationError(self.error_messages['invalid'])
66 if len(value) not in (7, 8):
67 raise ValidationError(self.error_messages['max_digits'])
68
69 return value
70
71class RIFField(RegexField):
72 """
73 This field validates a RIF (Registro de Información Fiscal). A
74 RIF is of the form A-XXXXXXXX-X. The last digit is a check digit.
75 """
76 rif_first_char = {
77 'v':'1',
78 'e':'2',
79 'j':'3',
80 'p':'4',
81 'g':'5',
82 }
83 default_error_messages = {
84 'invalid': _('Enter a valid RIF in A-XXXXXXXX-X or AXXXXXXXXX format.'),
85 'checksum': _("Invalid RIF."),
86 }
87
88 def __init__(self, *args, **kwargs):
89 super(RIFField, self).__init__(r'^[jJ|vV|eE]-\d{8}-\d$',*args, **kwargs)
90
91 def clean(self, value):
92 """Value can be either a string in A-XXXXXXXX-X or AXXXXXXXXX format"""
93 value = super(RIFField, self).clean(value)
94 if value in EMPTY_VALUES:
95 return u''
96 value, cd = self._canon(value)
97 if self._calc_cd(value) != cd:
98 raise ValidationError(self.error_messages['checksum'])
99 return self._format(value, cd)
100
101 def _canon(self, rif):
102 rif = rif.replace('-', '')
103 if rif[0].lower() in self.rif_first_char:
104 rif = rif.replace(rif[0], self.rif_first_char[rif[0]])
105 else:
106 raise ValidationError(self.error_messages['invalid'])
107 return rif[:-1], rif[-1]
108
109 def _calc_cd(self, rif):
110 mults = (4, 3, 2, 7, 6, 5, 4, 3, 2)
111 tmp = sum([m * int(rif[idx]) for idx, m in enumerate(mults)])
112 return str(11 - tmp % 11)
113
114 def _format(self, rif, check_digit=None):
115 if check_digit == None:
116 check_digit = rif[-1]
117 rif = rif[:-1]
118 return u'%s%s%s' % (rif[:2], rif[2:], check_digit)
Back to Top