Source code for localflavor.si.forms

"""Slovenian specific form helpers."""

import datetime
import re

from django.forms import ValidationError
from django.forms.fields import CharField, ChoiceField, Select
from django.utils.translation import gettext_lazy as _

from .si_postalcodes import SI_POSTALCODES_CHOICES


[docs]class SIEMSOField(CharField): """ A form for validating Slovenian personal identification number. Additionally stores gender, nationality and birthday to self.info dictionary. """ default_error_messages = { 'invalid': _('This field should contain exactly 13 digits.'), 'date': _('The first 7 digits of the EMSO must represent a valid past date.'), 'checksum': _('The EMSO is not valid.'), } emso_regex = re.compile(r'^(\d{2})(\d{2})(\d{3})(\d{2})(\d{3})(\d)$')
[docs] def clean(self, value): value = super().clean(value) if value in self.empty_values: return value m = self._regex_match(value) day, month, year, nationality, gender, checksum = [int(i) for i in m.groups()] self._validate_emso(checksum, value) birthday = self._validate_birthday(day, month, year) self.info = { 'gender': gender < 500 and 'male' or 'female', 'birthdate': birthday, 'nationality': nationality, } return value
def _regex_match(self, value): m = self.emso_regex.match(value) if m is None: raise ValidationError(self.error_messages['invalid'], code='invalid') return m def _validate_birthday(self, day, month, year): if year < 890: year += 2000 else: year += 1000 try: birthday = datetime.date(year, month, day) except ValueError: raise ValidationError(self.error_messages['date'], code='date') if datetime.date.today() < birthday: raise ValidationError(self.error_messages['date'], code='date') return birthday def _validate_emso(self, checksum, value): s = 0 int_values = [int(i) for i in value] for a, b in zip(int_values, list(range(7, 1, -1)) * 2): s += a * b chk = s % 11 if chk == 0: k = 0 else: k = 11 - chk if k == 10 or checksum != k: raise ValidationError(self.error_messages['checksum'], code='checksum')
[docs]class SITaxNumberField(CharField): """ Slovenian tax number field. Valid input is SIXXXXXXXX or XXXXXXXX where X is a number. http://zylla.wipos.p.lodz.pl/ut/translation.html#PZSI """ default_error_messages = { 'invalid': _('Enter a valid tax number in form SIXXXXXXXX'), } sitax_regex = re.compile(r'^(?:SI)?([1-9]\d{7})$')
[docs] def clean(self, value): value = super().clean(value) if value in self.empty_values: return value m = self.sitax_regex.match(value) if m is None: raise ValidationError(self.error_messages['invalid'], code='invalid') value = m.groups()[0] # Validate Tax number s = 0 int_values = [int(i) for i in value] for a, b in zip(int_values, range(8, 1, -1)): s += a * b chk = 11 - (s % 11) if chk == 10: chk = 0 if int_values[-1] != chk: raise ValidationError(self.error_messages['invalid'], code='invalid') return value
[docs]class SIPostalCodeField(ChoiceField): """Slovenian post codes field.""" def __init__(self, **kwargs): kwargs.setdefault('choices', SI_POSTALCODES_CHOICES) super().__init__(**kwargs)
[docs]class SIPostalCodeSelect(Select): """A Select widget that uses Slovenian postal codes as its choices.""" def __init__(self, attrs=None): super().__init__(attrs, choices=SI_POSTALCODES_CHOICES)