Skip to content

Commit

Permalink
Add ARCBUField form field for Argentina
Browse files Browse the repository at this point in the history
  • Loading branch information
Agustin Scaramuzza committed Apr 15, 2016
1 parent 8ffa807 commit 8ba4501
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 2 deletions.
3 changes: 2 additions & 1 deletion docs/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Authors
* Aaron Boman
* Adam Taylor
* Adrian Holovaty
* Agustín Scaramuzza
* Alex Butum
* Alex Gaynor
* Alex Hill
Expand Down Expand Up @@ -71,4 +72,4 @@ Authors
* d.merc
* luyikei
* tadeo
* Łukasz Langa
* Łukasz Langa
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ New flavors:

New fields for existing flavors:

- Added ARCBUField form field.
(`gh-151 <https://github.com/django/django-localflavor/pull/151>`_).
- Added NLZipCodeField, NLProvinceField, NLSoFiNumberField, NLPhoneNumberField model fields.
(`gh-152 <https://github.com/django/django-localflavor/pull/152>`_).

Expand Down
61 changes: 61 additions & 0 deletions localflavor/ar/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,64 @@ def _format(self, cuit, check_digit=None):
check_digit = cuit[-1]
cuit = cuit[:-1]
return '%s-%s-%s' % (cuit[:2], cuit[2:], check_digit)


class ARCBUField(CharField):
"""
This field validates a CBU (Clave Bancaria Uniforme). A CBU is a 22-digits long
number. The first 8 digits denote bank and branch number, plus a verifying digit.
The remaining 14 digits denote an account number, plus a verifying digit.
More info:
https://es.wikipedia.org/wiki/Clave_Bancaria_Uniforme
.. versionadded:: 1.3
"""
default_error_messages = {
'invalid': _('Enter a valid CBU in XXXXXXXXXXXXXXXXXXXXXX format.'),
'max_length': _('CBU must be exactly 22 digits long.'),
'min_length': _('CBU must be exactly 22 digits long.'),
'checksum': _('Invalid CBU.'),
}

def __init__(self, *args, **kwargs):
kwargs['min_length'] = kwargs['max_length'] = 22
super(ARCBUField, self).__init__(*args, **kwargs)

def _valid_block(self, block, ponderator):
number = block[:-1]
v_digit = int(block[-1])

block_sum = sum(x * int(y) for x, y in zip(ponderator, number))
remainder = block_sum % 10

# The verification digit and the result of the calculation must be the same.
# In the edge case that the remainder is 0, the verification digit must be 0 too.
if remainder == 0:
return v_digit == remainder

return v_digit == (10 - remainder)

def _checksum(self, value):
block_1 = value[0:8]
block_2 = value[8:22]

PONDERATOR_1 = (9, 7, 1, 3, 9, 7, 1, 3)
PONDERATOR_2 = (3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3)

is_valid_1 = self._valid_block(block_1, PONDERATOR_1)
is_valid_2 = self._valid_block(block_2, PONDERATOR_2)
return is_valid_1 and is_valid_2

def clean(self, value):
"""
Value must be a 22 digits long number.
"""
value = super(ARCBUField, self).clean(value)
if value in EMPTY_VALUES:
return ''
if not value.isdigit():
raise ValidationError(self.error_messages['invalid'])
if not self._checksum(value):
raise ValidationError(self.error_messages['checksum'])
return value
29 changes: 28 additions & 1 deletion tests/test_ar.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.test import SimpleTestCase

from localflavor.ar.forms import (ARProvinceSelect, ARPostalCodeField,
ARDNIField, ARCUITField)
ARDNIField, ARCUITField, ARCBUField)


class ARLocalFlavorTests(SimpleTestCase):
Expand Down Expand Up @@ -104,3 +104,30 @@ def test_ARCUITField(self):
'11211111110': error_legal_type,
}
self.assertFieldOutput(ARCUITField, valid, invalid)

def test_ARCBUField(self):
error_format = ['Enter a valid CBU in XXXXXXXXXXXXXXXXXXXXXX format.']
error_length = ['CBU must be exactly 22 digits long.']
error_checksum = ['Invalid CBU.']
valid = {
'2237628810898098715378': '2237628810898098715378',
'5433758936130717465023': '5433758936130717465023',
'5729195067928761667584': '5729195067928761667584',
'9498175528566296510521': '9498175528566296510521',
'7362966507842824472644': '7362966507842824472644',
'8693513393883886497274': '8693513393883886497274',
'1542952861593836535608': '1542952861593836535608',
'5833008953419074707467': '5833008953419074707467',
'9687027721961737239525': '9687027721961737239525',
'8048819274216931992586': '8048819274216931992586'
}

invalid = {
'abc123def456-9024-2313': error_format,
'142512591859898123123': error_length,
'12312452521512526125566': error_length,
'1234567891234567891234': error_checksum,
'1234562374545894589234': error_checksum,
'0987653759257883891234': error_checksum,
}
self.assertFieldOutput(ARCBUField, valid, invalid)

0 comments on commit 8ba4501

Please sign in to comment.