PageRenderTime 29ms CodeModel.GetById 15ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/localflavor/pl/forms.py

https://code.google.com/p/mango-py/
Python | 160 lines | 135 code | 7 blank | 18 comment | 8 complexity | a89b01f47658f349a18a3c009069a89c MD5 | raw file
  1"""
  2Polish-specific form helpers
  3"""
  4
  5import re
  6
  7from django.forms import ValidationError
  8from django.forms.fields import Select, RegexField
  9from django.utils.translation import ugettext_lazy as _
 10from django.core.validators import EMPTY_VALUES
 11
 12class PLProvinceSelect(Select):
 13    """
 14    A select widget with list of Polish administrative provinces as choices.
 15    """
 16    def __init__(self, attrs=None):
 17        from pl_voivodeships import VOIVODESHIP_CHOICES
 18        super(PLProvinceSelect, self).__init__(attrs, choices=VOIVODESHIP_CHOICES)
 19
 20class PLCountySelect(Select):
 21    """
 22    A select widget with list of Polish administrative units as choices.
 23    """
 24    def __init__(self, attrs=None):
 25        from pl_administrativeunits import ADMINISTRATIVE_UNIT_CHOICES
 26        super(PLCountySelect, self).__init__(attrs, choices=ADMINISTRATIVE_UNIT_CHOICES)
 27
 28class PLPESELField(RegexField):
 29    """
 30    A form field that validates as Polish Identification Number (PESEL).
 31
 32    Checks the following rules:
 33        * the length consist of 11 digits
 34        * has a valid checksum
 35
 36    The algorithm is documented at http://en.wikipedia.org/wiki/PESEL.
 37    """
 38    default_error_messages = {
 39        'invalid': _(u'National Identification Number consists of 11 digits.'),
 40        'checksum': _(u'Wrong checksum for the National Identification Number.'),
 41    }
 42
 43    def __init__(self, *args, **kwargs):
 44        super(PLPESELField, self).__init__(r'^\d{11}$',
 45            max_length=None, min_length=None, *args, **kwargs)
 46
 47    def clean(self,value):
 48        super(PLPESELField, self).clean(value)
 49        if value in EMPTY_VALUES:
 50            return u''
 51        if not self.has_valid_checksum(value):
 52            raise ValidationError(self.error_messages['checksum'])
 53        return u'%s' % value
 54
 55    def has_valid_checksum(self, number):
 56        """
 57        Calculates a checksum with the provided algorithm.
 58        """
 59        multiple_table = (1, 3, 7, 9, 1, 3, 7, 9, 1, 3, 1)
 60        result = 0
 61        for i in range(len(number)):
 62            result += int(number[i]) * multiple_table[i]
 63        return result % 10 == 0
 64
 65class PLNIPField(RegexField):
 66    """
 67    A form field that validates as Polish Tax Number (NIP).
 68    Valid forms are: XXX-XXX-YY-YY or XX-XX-YYY-YYY.
 69
 70    Checksum algorithm based on documentation at
 71    http://wipos.p.lodz.pl/zylla/ut/nip-rego.html
 72    """
 73    default_error_messages = {
 74        'invalid': _(u'Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX.'),
 75        'checksum': _(u'Wrong checksum for the Tax Number (NIP).'),
 76    }
 77
 78    def __init__(self, *args, **kwargs):
 79        super(PLNIPField, self).__init__(r'^\d{3}-\d{3}-\d{2}-\d{2}$|^\d{2}-\d{2}-\d{3}-\d{3}$',
 80            max_length=None, min_length=None, *args, **kwargs)
 81
 82    def clean(self,value):
 83        super(PLNIPField, self).clean(value)
 84        if value in EMPTY_VALUES:
 85            return u''
 86        value = re.sub("[-]", "", value)
 87        if not self.has_valid_checksum(value):
 88            raise ValidationError(self.error_messages['checksum'])
 89        return u'%s' % value
 90
 91    def has_valid_checksum(self, number):
 92        """
 93        Calculates a checksum with the provided algorithm.
 94        """
 95        multiple_table = (6, 5, 7, 2, 3, 4, 5, 6, 7)
 96        result = 0
 97        for i in range(len(number)-1):
 98            result += int(number[i]) * multiple_table[i]
 99
100        result %= 11
101        if result == int(number[-1]):
102            return True
103        else:
104            return False
105
106class PLREGONField(RegexField):
107    """
108    A form field that validates its input is a REGON number.
109
110    Valid regon number consists of 9 or 14 digits.
111    See http://www.stat.gov.pl/bip/regon_ENG_HTML.htm for more information.
112    """
113    default_error_messages = {
114        'invalid': _(u'National Business Register Number (REGON) consists of 9 or 14 digits.'),
115        'checksum': _(u'Wrong checksum for the National Business Register Number (REGON).'),
116    }
117
118    def __init__(self, *args, **kwargs):
119        super(PLREGONField, self).__init__(r'^\d{9,14}$',
120            max_length=None, min_length=None, *args, **kwargs)
121
122    def clean(self,value):
123        super(PLREGONField, self).clean(value)
124        if value in EMPTY_VALUES:
125            return u''
126        if not self.has_valid_checksum(value):
127            raise ValidationError(self.error_messages['checksum'])
128        return u'%s' % value
129
130    def has_valid_checksum(self, number):
131        """
132        Calculates a checksum with the provided algorithm.
133        """
134        weights = (
135            (8, 9, 2, 3, 4, 5, 6, 7, -1),
136            (2, 4, 8, 5, 0, 9, 7, 3, 6, 1, 2, 4, 8, -1),
137            (8, 9, 2, 3, 4, 5, 6, 7, -1, 0, 0, 0, 0, 0),
138        )
139
140        weights = [table for table in weights if len(table) == len(number)]
141
142        for table in weights:
143            checksum = sum([int(n) * w for n, w in zip(number, table)])
144            if checksum % 11 % 10:
145                return False
146
147        return bool(weights)
148
149class PLPostalCodeField(RegexField):
150    """
151    A form field that validates as Polish postal code.
152    Valid code is XX-XXX where X is digit.
153    """
154    default_error_messages = {
155        'invalid': _(u'Enter a postal code in the format XX-XXX.'),
156    }
157
158    def __init__(self, *args, **kwargs):
159        super(PLPostalCodeField, self).__init__(r'^\d{2}-\d{3}$',
160            max_length=None, min_length=None, *args, **kwargs)