Source code for

"""Kuwait-specific Form helpers."""
import re
import textwrap
from datetime import date

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

from .kw_areas import AREA_CHOICES
from .kw_governorates import GOVERNORATE_CHOICES

id_re = re.compile(r'''^(?P<initial>\d)
                       (?P<checksum>\d)''', re.VERBOSE)

def is_valid_kw_civilid_checksum(value):
    weight = (2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
    calculated_checksum = 0
    for i in range(11):
        calculated_checksum += int(value[i]) * weight[i]

    remainder = calculated_checksum % 11
    checkdigit = 11 - remainder
    if checkdigit != int(value[11]):
        return False
    return True

[docs]class KWCivilIDNumberField(RegexField): """ Kuwaiti Civil ID numbers are 12 digits, second to seventh digits represents the person's birthdate. Checks the following rules to determine the validity of the number: * The number consist of 12 digits. * The birthdate of the person is a valid date. * The calculated checksum equals to the last digit of the Civil ID. """ default_error_messages = { 'invalid': _('Enter a valid Kuwaiti Civil ID number'), } def __init__(self, max_length=12, min_length=12, **kwargs): super().__init__( r'\d{12}', max_length=max_length, min_length=min_length, **kwargs )
[docs] def clean(self, value): value = super().clean(value) if value in self.empty_values: return value cc = value[0] # Century value yy, mm, dd = textwrap.wrap(value[1:7], 2) # pylint: disable=unbalanced-tuple-unpacking # Fix the dates so that those born # in 2000+ pass the validation check if int(cc) == 3: yy = '20{}'.format(yy) elif int(cc) == 2: yy = '19{}'.format(yy) try: date(int(yy), int(mm), int(dd)) except ValueError: raise ValidationError(self.error_messages['invalid'], code='invalid') if not is_valid_kw_civilid_checksum(value): raise ValidationError(self.error_messages['invalid'], code='invalid') return value
[docs]class KWGovernorateSelect(Select): """ A Select widget that uses a list of Kuwait governorates as its choices. """ def __init__(self, attrs=None): super().__init__(attrs, choices=GOVERNORATE_CHOICES)
[docs]class KWAreaSelect(Select): """ A Select widget that uses a list of Kuwait areas as its choices. .. versionadded:: 1.6 """ def __init__(self, attrs=None): super().__init__(attrs, choices=AREA_CHOICES)