Ticket #11768: forms.py

File forms.py, 3.8 KB (added by marcoslhc, 6 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