Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactoring field to inherit from RegexField #232

Merged
merged 2 commits into from
Nov 5, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 32 additions & 27 deletions localflavor/kw/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,39 @@
from __future__ import unicode_literals

import re
import textwrap
from datetime import date

from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, Select
from django.forms.fields import RegexField, Select
from django.utils.translation import gettext_lazy as _

from .kw_governorates import GOVERNORATE_CHOICES

id_re = re.compile(r'''^(?P<initial>\d{1})

id_re = re.compile(r'''^(?P<initial>\d)
(?P<yy>\d\d)
(?P<mm>\d\d)
(?P<dd>\d\d)
(?P<mid>\d{4})
(?P<checksum>\d{1})''', re.VERBOSE)
(?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

class KWCivilIDNumberField(Field):

class KWCivilIDNumberField(RegexField):
"""
Kuwaiti Civil ID numbers are 12 digits, second to seventh digits
represents the person's birthdate.
Expand All @@ -35,43 +50,32 @@ class KWCivilIDNumberField(Field):
'invalid': _('Enter a valid Kuwaiti Civil ID number'),
}

def has_valid_checksum(self, 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
def __init__(self, max_length=12, min_length=12, *args, **kwargs):
super(KWCivilIDNumberField, self).__init__(r'\d{12}',
max_length,
min_length, *args, **kwargs)

def clean(self, value):
super(KWCivilIDNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''

match = re.match(id_re, value)

if not match:
raise ValidationError(self.error_messages['invalid'])

gd = match.groupdict()
cc = value[0] # Century value
yy, mm, dd = textwrap.wrap(value[1:7], 2) # Date parts

# Fix the dates so that those born
# in 2000+ pass the validation check
if int(value[0]) == 3:
gd['yy'] = '20{}'.format(gd['yy'])
elif int(value[0]) == 2:
gd['yy'] = '19{}'.format(gd['yy'])
if int(cc) == 3:
yy = '20{}'.format(yy)
elif int(cc) == 2:
yy = '19{}'.format(yy)

try:
date(int(gd['yy']), int(gd['mm']), int(gd['dd']))
date(int(yy), int(mm), int(dd))
except ValueError:
raise ValidationError(self.error_messages['invalid'])

if not self.has_valid_checksum(value):
if not is_valid_kw_civilid_checksum(value):
raise ValidationError(self.error_messages['invalid'])

return value
Expand All @@ -82,6 +86,7 @@ class KWGovernorateSelect(Select):
A Select widget that uses a list of Kuwait governorates
as its choices.
"""

def __init__(self, attrs=None):
super(KWGovernorateSelect, self).__init__(attrs,
choices=GOVERNORATE_CHOICES)