diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2007-04-26 13:11:07 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2007-04-26 13:11:07 +0000 |
| commit | 6c02565e4fb92c4cc3bfb45bcc89eb9aa299efdc (patch) | |
| tree | 2c920befa38aef91249b7b1ab36fcca60ed01149 | |
| parent | b24c860fa21790bfe04f5afc7c8bcccb70902f83 (diff) | |
Fixed #3957, #3945 -- Added CPF and CNPJ (some Brazilian identity numbers)
fields to the Brazilian localflavor. Thanks, onaiort@gmail.com and
danielvaz@gmail.com.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5089 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/contrib/localflavor/br/forms.py | 84 | ||||
| -rw-r--r-- | tests/regressiontests/forms/localflavor.py | 34 |
3 files changed, 117 insertions, 2 deletions
@@ -168,6 +168,7 @@ answer newbie questions, and generally made Django that much better: Sam Newman <http://www.magpiebrain.com/> Neal Norwitz <nnorwitz@google.com> oggie rob <oz.robharvey@gmail.com> + onaiort@gmail.com Jay Parlar <parlar@gmail.com> pavithran s <pavithran.s@gmail.com> Barry Pederson <bp@barryp.org> diff --git a/django/contrib/localflavor/br/forms.py b/django/contrib/localflavor/br/forms.py index 29ad4df53d..0ec370546f 100644 --- a/django/contrib/localflavor/br/forms.py +++ b/django/contrib/localflavor/br/forms.py @@ -4,7 +4,7 @@ BR-specific Form helpers """ from django.newforms import ValidationError -from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES +from django.newforms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES from django.utils.encoding import smart_unicode from django.utils.translation import gettext import re @@ -15,7 +15,7 @@ class BRZipCodeField(RegexField): def __init__(self, *args, **kwargs): super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$', max_length=None, min_length=None, - error_message=gettext(u'Enter a zip code in the format XXXXX-XXX.'), + error_message=gettext('Enter a zip code in the format XXXXX-XXX.'), *args, **kwargs) class BRPhoneNumberField(Field): @@ -37,3 +37,83 @@ class BRStateSelect(Select): def __init__(self, attrs=None): from br_states import STATE_CHOICES # relative import super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES) + + +def DV_maker(v): + if v >= 2: + return 11 - v + return 0 + +class BRCPFField(CharField): + """ + This field validate a CPF number or a CPF string. A CPF number is + compounded by XXX.XXX.XXX-VD, the two last digits are check digits. + + More information: + http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas + """ + def __init__(self, *args, **kwargs): + super(BRCPFField, self).__init__(max_length=14, min_length=11, *args, **kwargs) + + def clean(self, value): + """ + Value can be either a string in the format XXX.XXX.XXX-XX or an + 11-digit number. + """ + value = super(BRCPFField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + orig_value = value[:] + if not value.isdigit(): + value = re.sub("[-\.]", "", value) + try: + int(value) + except ValueError: + raise ValidationError(gettext("This field requires only numbers")) + if len(value) != 11: + raise ValidationError(gettext("This field requires at most 11 digits or 14 characters.")) + orig_dv = value[-2:] + + new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))]) + new_1dv = DV_maker(new_1dv % 11) + value = value[:-2] + str(new_1dv) + value[-1] + new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(11, 1, -1))]) + new_2dv = DV_maker(new_2dv % 11) + value = value[:-1] + str(new_2dv) + if value[-2:] != orig_dv: + raise ValidationError(gettext("Invalid CPF number.")) + + return orig_value + +class BRCNPJField(Field): + def clean(self, value): + """ + Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a + group of 14 characters. + """ + value = super(BRCNPJField, self).clean(value) + if value in EMPTY_VALUES: + return u'' + orig_value = value[:] + if not value.isdigit(): + value = re.sub("[-/\.]", "", value) + try: + int(value) + except ValueError: + raise ValidationError("This field requires only numbers") + if len(value) != 14: + raise ValidationError( + gettext("This field requires at least 14 digits")) + orig_dv = value[-2:] + + new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))]) + new_1dv = DV_maker(new_1dv % 11) + value = value[:-2] + str(new_1dv) + value[-1] + new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(6, 1, -1) + range(9, 1, -1))]) + new_2dv = DV_maker(new_2dv % 11) + value = value[:-1] + str(new_2dv) + if value[-2:] != orig_dv: + raise ValidationError(gettext("Invalid CNPJ number")) + + return orig_value + diff --git a/tests/regressiontests/forms/localflavor.py b/tests/regressiontests/forms/localflavor.py index 1747a0a61c..d339eb089d 100644 --- a/tests/regressiontests/forms/localflavor.py +++ b/tests/regressiontests/forms/localflavor.py @@ -840,6 +840,40 @@ ValidationError: [u'Enter a zip code in the format XXXXX-XXX.'] >>> f.clean('12345-123') u'12345-123' +# BRCNPJField ############################################################ + +>>> from django.contrib.localflavor.br.forms import BRCNPJField +>>> f = BRCNPJField(required=True) +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('12-345-678/9012-10') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CNPJ number'] +>>> f.clean('12.345.678/9012-10') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CNPJ number'] +>>> f.clean('12345678/9012-10') +Traceback (most recent call last): +... +ValidationError: [u'Invalid CNPJ number'] +>>> f.clean('64.132.916/0001-88') +'64.132.916/0001-88' +>>> f.clean('64-132-916/0001-88') +'64-132-916/0001-88' +>>> f.clean('64132916/0001-88') +'64132916/0001-88' +>>> f.clean('64.132.916/0001-XX') +Traceback (most recent call last): +... +ValidationError: [u'This field requires only numbers'] +>>> f = BRCNPJField(required=False) +>>> f.clean('') +u'' + # BRPhoneNumberField ######################################################### >>> from django.contrib.localflavor.br.forms import BRPhoneNumberField |
