You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
2.7 KiB
81 lines
2.7 KiB
""" |
|
Norwegian-specific Form helpers |
|
""" |
|
|
|
import re, datetime |
|
from django.forms import ValidationError |
|
from django.forms.fields import Field, RegexField, Select, EMPTY_VALUES |
|
from django.utils.translation import ugettext_lazy as _ |
|
|
|
class NOZipCodeField(RegexField): |
|
default_error_messages = { |
|
'invalid': _('Enter a zip code in the format XXXX.'), |
|
} |
|
|
|
def __init__(self, *args, **kwargs): |
|
super(NOZipCodeField, self).__init__(r'^\d{4}$', |
|
max_length=None, min_length=None, *args, **kwargs) |
|
|
|
class NOMunicipalitySelect(Select): |
|
""" |
|
A Select widget that uses a list of Norwegian municipalities (fylker) |
|
as its choices. |
|
""" |
|
def __init__(self, attrs=None): |
|
from no_municipalities import MUNICIPALITY_CHOICES |
|
super(NOMunicipalitySelect, self).__init__(attrs, choices=MUNICIPALITY_CHOICES) |
|
|
|
class NOSocialSecurityNumber(Field): |
|
""" |
|
Algorithm is documented at http://no.wikipedia.org/wiki/Personnummer |
|
""" |
|
default_error_messages = { |
|
'invalid': _(u'Enter a valid Norwegian social security number.'), |
|
} |
|
|
|
def clean(self, value): |
|
super(NOSocialSecurityNumber, self).clean(value) |
|
if value in EMPTY_VALUES: |
|
return u'' |
|
|
|
if not re.match(r'^\d{11}$', value): |
|
raise ValidationError(self.error_messages['invalid']) |
|
|
|
day = int(value[:2]) |
|
month = int(value[2:4]) |
|
year2 = int(value[4:6]) |
|
|
|
inum = int(value[6:9]) |
|
self.birthday = None |
|
try: |
|
if 000 <= inum < 500: |
|
self.birthday = datetime.date(1900+year2, month, day) |
|
if 500 <= inum < 750 and year2 > 54: |
|
self.birthday = datetime.date(1800+year2, month, day) |
|
if 500 <= inum < 1000 and year2 < 40: |
|
self.birthday = datetime.date(2000+year2, month, day) |
|
if 900 <= inum < 1000 and year2 > 39: |
|
self.birthday = datetime.date(1900+year2, month, day) |
|
except ValueError: |
|
raise ValidationError(self.error_messages['invalid']) |
|
|
|
sexnum = int(value[8]) |
|
if sexnum % 2 == 0: |
|
self.gender = 'F' |
|
else: |
|
self.gender = 'M' |
|
|
|
digits = map(int, list(value)) |
|
weight_1 = [3, 7, 6, 1, 8, 9, 4, 5, 2, 1, 0] |
|
weight_2 = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2, 1] |
|
|
|
def multiply_reduce(aval, bval): |
|
return sum([(a * b) for (a, b) in zip(aval, bval)]) |
|
|
|
if multiply_reduce(digits, weight_1) % 11 != 0: |
|
raise ValidationError(self.error_messages['invalid']) |
|
if multiply_reduce(digits, weight_2) % 11 != 0: |
|
raise ValidationError(self.error_messages['invalid']) |
|
|
|
return value |
|
|
|
|