Ticket #5431: argentinean_localflavor_r6139-2.diff

File argentinean_localflavor_r6139-2.diff, 14.9 KB (added by ramiro, 8 years ago)
  • new file django/contrib/localflavor/ar/ar_provinces.py

    diff -r 36ff13ea73e9 django/contrib/localflavor/ar/ar_provinces.py
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3A list of Argentinean provinces and autonomous cities as `choices` in a
     4formfield. From
     5http://www.argentina.gov.ar/argentina/portal/paginas.dhtml?pagina=425
     6
     7This exists in this standalone file so that it's only imported into memory
     8when explicitly needed.
     9"""
     10
     11PROVINCE_CHOICES = (
     12    ('B', u'Buenos Aires'),
     13    ('K', u'Catamarca'),
     14    ('H', u'Chaco'),
     15    ('U', u'Chubut'),
     16    ('C', u'Ciudad Autónoma de Buenos Aires'),
     17    ('X', u'Córdoba'),
     18    ('W', u'Corrientes'),
     19    ('E', u'Entre Ríos'),
     20    ('P', u'Formosa'),
     21    ('Y', u'Jujuy'),
     22    ('L', u'La Pampa'),
     23    ('F', u'La Rioja'),
     24    ('M', u'Mendoza'),
     25    ('N', u'Misiones'),
     26    ('Q', u'Neuquén'),
     27    ('R', u'Río Negro'),
     28    ('A', u'Salta'),
     29    ('J', u'San Juan'),
     30    ('D', u'San Luis'),
     31    ('Z', u'Santa Cruz'),
     32    ('S', u'Santa Fe'),
     33    ('G', u'Santiago del Estero'),
     34    ('V', u'Tierra del Fuego, Antártida e Islas del Atlántico Sur'),
     35    ('T', u'Tucumán'),
     36)
  • new file django/contrib/localflavor/ar/forms.py

    diff -r 36ff13ea73e9 django/contrib/localflavor/ar/forms.py
    - +  
     1# -*- coding: utf-8 -*-
     2"""
     3AR-specific Form helpers.
     4"""
     5
     6from django.newforms import ValidationError
     7from django.newforms.fields import RegexField, CharField, Select, EMPTY_VALUES
     8from django.utils.encoding import smart_unicode
     9from django.utils.translation import ugettext
     10import re
     11
     12class ARProvinceSelect(Select):
     13    """
     14    A Select widget that uses a list of Argentinean provinces/autonomous
     15    cities as its choices.
     16
     17    """
     18    def __init__(self, attrs=None):
     19        from ar_provinces import PROVINCE_CHOICES
     20        super(ARProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
     21
     22
     23class ARPostalCodeField(RegexField):
     24    """
     25    A field that accepts a `classic´ NNNN Postal Code or a CPA.
     26
     27    See http://www.correoargentino.com.ar/consulta_cpa/home.php
     28
     29    """
     30    def __init__(self, *args, **kwargs):
     31        super(ARPostalCodeField, self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$',
     32            min_length=4, max_length=8,
     33            error_message=ugettext("Enter a postal code in the format NNNN or ANNNNAAA."),
     34                    *args, **kwargs)
     35
     36    def clean(self, value):
     37        value = super(ARPostalCodeField, self).clean(value)
     38        if value in EMPTY_VALUES:
     39            return u''
     40        if len(value) not in (4, 8):
     41            raise ValidationError(ugettext("Enter a postal code in the format NNNN or ANNNNAAA."))
     42        if len(value) == 8:
     43            return u'%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper())
     44        return value
     45
     46
     47class ARDNIField(CharField):
     48    """
     49    A field that validates `Documento Nacional de Identidad´ (DNI)
     50    numbers.
     51
     52    """
     53    def __init__(self, *args, **kwargs):
     54        super(ARDNIField, self).__init__(max_length=10, min_length=7, *args,
     55                **kwargs)
     56
     57    def clean(self, value):
     58        """
     59        Value can be a string either in the [X]X.XXX.XXX or [X]XXXXXXX formats.
     60        """
     61        value = super(ARDNIField, self).clean(value)
     62        if value in EMPTY_VALUES:
     63            return u''
     64        if not value.isdigit():
     65            value = value.replace('.', '')
     66        if not value.isdigit():
     67            raise ValidationError(ugettext("This field requires only numbers."))
     68        if len(value) not in (7, 8):
     69            raise ValidationError(
     70                    ugettext("This field requires 7 or 8 digits."))
     71
     72        return value
     73
     74
     75class ARCUITField(RegexField):
     76    """
     77    This field validates a CUIT (Código Único de Identificación
     78    Tributaria). A CUIT is of the form XX-XXXXXXXX-V. The last digit
     79    is a check digit.
     80
     81    """
     82    def __init__(self, *args, **kwargs):
     83        super(ARCUITField, self).__init__(r'^\d{2}-?\d{8}-?\d$',
     84            error_message=ugettext('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'),
     85            *args, **kwargs)
     86
     87    def clean(self, value):
     88        """
     89        Value can be either a string in the format XX-XXXXXXXX-X or an
     90        11-digit number.
     91        """
     92        value = super(ARCUITField, self).clean(value)
     93        if value in EMPTY_VALUES:
     94            return u''
     95        value, cd = self._canon(value)
     96        if self._calc_cd(value) != cd:
     97            raise ValidationError(ugettext("Invalid CUIT."))
     98        return self._format(value, cd)
     99
     100    def _canon(self, cuit):
     101        cuit = cuit.replace('-', '')
     102        return cuit[:-1], cuit[-1]
     103
     104    def _calc_cd(self, cuit):
     105        mults = (5, 4, 3, 2, 7, 6, 5, 4, 3, 2)
     106        tmp = sum([m * int(cuit[idx]) for idx, m in enumerate(mults)])
     107        return str(11 - tmp % 11)
     108
     109    def _format(self, cuit, check_digit=None):
     110        if check_digit == None:
     111            check_digit = cuit[-1]
     112            cuit = cuit[:-1]
     113        return u'%s-%s-%s' % (cuit[:2], cuit[2:], check_digit)
  • tests/regressiontests/forms/localflavor.py

    diff -r 36ff13ea73e9 tests/regressiontests/forms/localflavor.py
    a b ValidationError: [u'Enter a valid SoFi n 
    15141514>>> s = NLProvinceSelect()
    15151515>>> s.render('provinces', 'OV')
    15161516u'<select name="provinces">\n<option value="DR">Drente</option>\n<option value="FL">Flevoland</option>\n<option value="FR">Friesland</option>\n<option value="GL">Gelderland</option>\n<option value="GR">Groningen</option>\n<option value="LB">Limburg</option>\n<option value="NB">Noord-Brabant</option>\n<option value="NH">Noord-Holland</option>\n<option value="OV" selected="selected">Overijssel</option>\n<option value="UT">Utrecht</option>\n<option value="ZE">Zeeland</option>\n<option value="ZH">Zuid-Holland</option>\n</select>'
     1517
     1518# ARProvinceField #############################################################
     1519
     1520>>> from django.contrib.localflavor.ar.forms import ARProvinceSelect
     1521>>> f = ARProvinceSelect()
     1522>>> f.render('provincias', 'A')
     1523u'<select name="provincias">\n<option value="B">Buenos Aires</option>\n<option value="K">Catamarca</option>\n<option value="H">Chaco</option>\n<option value="U">Chubut</option>\n<option value="C">Ciudad Aut\xf3noma de Buenos Aires</option>\n<option value="X">C\xf3rdoba</option>\n<option value="W">Corrientes</option>\n<option value="E">Entre R\xedos</option>\n<option value="P">Formosa</option>\n<option value="Y">Jujuy</option>\n<option value="L">La Pampa</option>\n<option value="F">La Rioja</option>\n<option value="M">Mendoza</option>\n<option value="N">Misiones</option>\n<option value="Q">Neuqu\xe9n</option>\n<option value="R">R\xedo Negro</option>\n<option value="A" selected="selected">Salta</option>\n<option value="J">San Juan</option>\n<option value="D">San Luis</option>\n<option value="Z">Santa Cruz</option>\n<option value="S">Santa Fe</option>\n<option value="G">Santiago del Estero</option>\n<option value="V">Tierra del Fuego, Ant\xe1rtida e Islas del Atl\xe1ntico Sur</option>\n<option value="T">Tucum\xe1n</option>\n</select>'
     1524
     1525# ARPostalCodeField ###########################################################
     1526
     1527>>> from django.contrib.localflavor.ar.forms import ARPostalCodeField
     1528>>> f = ARPostalCodeField()
     1529>>> f.clean('5000')
     1530u'5000'
     1531>>> f.clean('C1064AAB')
     1532u'C1064AAB'
     1533>>> f.clean('c1064AAB')
     1534u'C1064AAB'
     1535>>> f.clean('C1064aab')
     1536u'C1064AAB'
     1537>>> f.clean(u'4400')
     1538u'4400'
     1539>>> f.clean(u'C1064AAB')
     1540u'C1064AAB'
     1541>>> f.clean('C1064AABB')
     1542Traceback (most recent call last):
     1543...
     1544ValidationError: [u'Ensure this value has at most 8 characters (it has 9).']
     1545>>> f.clean('C1064AA')
     1546Traceback (most recent call last):
     1547...
     1548ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1549>>> f.clean('C106AAB')
     1550Traceback (most recent call last):
     1551...
     1552ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1553>>> f.clean('106AAB')
     1554Traceback (most recent call last):
     1555...
     1556ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1557>>> f.clean('500')
     1558Traceback (most recent call last):
     1559...
     1560ValidationError: [u'Ensure this value has at least 4 characters (it has 3).']
     1561>>> f.clean('5PPP')
     1562Traceback (most recent call last):
     1563...
     1564ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1565>>> f.clean(None)
     1566Traceback (most recent call last):
     1567...
     1568ValidationError: [u'This field is required.']
     1569>>> f.clean('')
     1570Traceback (most recent call last):
     1571...
     1572ValidationError: [u'This field is required.']
     1573>>> f.clean(u'')
     1574Traceback (most recent call last):
     1575...
     1576ValidationError: [u'This field is required.']
     1577
     1578>>> f = ARPostalCodeField(required=False)
     1579>>> f.clean('5000')
     1580u'5000'
     1581>>> f.clean('C1064AAB')
     1582u'C1064AAB'
     1583>>> f.clean('c1064AAB')
     1584u'C1064AAB'
     1585>>> f.clean('C1064aab')
     1586u'C1064AAB'
     1587>>> f.clean(u'4400')
     1588u'4400'
     1589>>> f.clean(u'C1064AAB')
     1590u'C1064AAB'
     1591>>> f.clean('C1064AABB')
     1592Traceback (most recent call last):
     1593...
     1594ValidationError: [u'Ensure this value has at most 8 characters (it has 9).']
     1595>>> f.clean('C1064AA')
     1596Traceback (most recent call last):
     1597...
     1598ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1599>>> f.clean('C106AAB')
     1600Traceback (most recent call last):
     1601...
     1602ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1603>>> f.clean('106AAB')
     1604Traceback (most recent call last):
     1605...
     1606ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1607>>> f.clean('500')
     1608Traceback (most recent call last):
     1609...
     1610ValidationError: [u'Ensure this value has at least 4 characters (it has 3).']
     1611>>> f.clean('5PPP')
     1612Traceback (most recent call last):
     1613...
     1614ValidationError: [u'Enter a postal code in the format NNNN or ANNNNAAA.']
     1615>>> f.clean(None)
     1616u''
     1617>>> f.clean('')
     1618u''
     1619>>> f.clean(u'')
     1620u''
     1621
     1622# ARDNIField ##################################################################
     1623
     1624>>> from django.contrib.localflavor.ar.forms import ARDNIField
     1625>>> f = ARDNIField()
     1626>>> f.clean('20123456')
     1627u'20123456'
     1628>>> f.clean('20.123.456')
     1629u'20123456'
     1630>>> f.clean('9123456')
     1631u'9123456'
     1632>>> f.clean('9.123.456')
     1633u'9123456'
     1634>>> f.clean(u'20123456')
     1635u'20123456'
     1636>>> f.clean(u'20.123.456')
     1637u'20123456'
     1638>>> f.clean('20.123456')
     1639u'20123456'
     1640>>> f.clean('101234566')
     1641Traceback (most recent call last):
     1642...
     1643ValidationError: [u'This field requires 7 or 8 digits.']
     1644>>> f.clean('W0123456')
     1645Traceback (most recent call last):
     1646...
     1647ValidationError: [u'This field requires only numbers.']
     1648>>> f.clean('10,123,456')
     1649Traceback (most recent call last):
     1650...
     1651ValidationError: [u'This field requires only numbers.']
     1652>>> f.clean(None)
     1653Traceback (most recent call last):
     1654...
     1655ValidationError: [u'This field is required.']
     1656>>> f.clean('')
     1657Traceback (most recent call last):
     1658...
     1659ValidationError: [u'This field is required.']
     1660>>> f.clean(u'')
     1661Traceback (most recent call last):
     1662...
     1663ValidationError: [u'This field is required.']
     1664
     1665>>> f = ARDNIField(required=False)
     1666>>> f.clean('20123456')
     1667u'20123456'
     1668>>> f.clean('20.123.456')
     1669u'20123456'
     1670>>> f.clean('9123456')
     1671u'9123456'
     1672>>> f.clean('9.123.456')
     1673u'9123456'
     1674>>> f.clean(u'20123456')
     1675u'20123456'
     1676>>> f.clean(u'20.123.456')
     1677u'20123456'
     1678>>> f.clean('20.123456')
     1679u'20123456'
     1680>>> f.clean('101234566')
     1681Traceback (most recent call last):
     1682...
     1683ValidationError: [u'This field requires 7 or 8 digits.']
     1684>>> f.clean('W0123456')
     1685Traceback (most recent call last):
     1686...
     1687ValidationError: [u'This field requires only numbers.']
     1688>>> f.clean('10,123,456')
     1689Traceback (most recent call last):
     1690...
     1691ValidationError: [u'This field requires only numbers.']
     1692>>> f.clean(None)
     1693u''
     1694>>> f.clean('')
     1695u''
     1696>>> f.clean(u'')
     1697u''
     1698
     1699# ARCUITField #################################################################
     1700
     1701>>> from django.contrib.localflavor.ar.forms import ARCUITField
     1702>>> f = ARCUITField()
     1703>>> f.clean('20-10123456-9')
     1704u'20-10123456-9'
     1705>>> f.clean(u'20-10123456-9')
     1706u'20-10123456-9'
     1707>>> f.clean('27-10345678-4')
     1708u'27-10345678-4'
     1709>>> f.clean('20101234569')
     1710u'20-10123456-9'
     1711>>> f.clean('27103456784')
     1712u'27-10345678-4'
     1713>>> f.clean('2-10123456-9')
     1714Traceback (most recent call last):
     1715...
     1716ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1717>>> f.clean('210123456-9')
     1718Traceback (most recent call last):
     1719...
     1720ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1721>>> f.clean('20-10123456')
     1722Traceback (most recent call last):
     1723...
     1724ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1725>>> f.clean('20-10123456-')
     1726Traceback (most recent call last):
     1727...
     1728ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1729>>> f.clean('20-10123456-5')
     1730Traceback (most recent call last):
     1731...
     1732ValidationError: [u'Invalid CUIT.']
     1733>>> f.clean(u'2-10123456-9')
     1734Traceback (most recent call last):
     1735...
     1736ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1737>>> f.clean('27-10345678-1')
     1738Traceback (most recent call last):
     1739...
     1740ValidationError: [u'Invalid CUIT.']
     1741>>> f.clean(u'27-10345678-1')
     1742Traceback (most recent call last):
     1743...
     1744ValidationError: [u'Invalid CUIT.']
     1745>>> f.clean(None)
     1746Traceback (most recent call last):
     1747...
     1748ValidationError: [u'This field is required.']
     1749>>> f.clean('')
     1750Traceback (most recent call last):
     1751...
     1752ValidationError: [u'This field is required.']
     1753>>> f.clean(u'')
     1754Traceback (most recent call last):
     1755...
     1756ValidationError: [u'This field is required.']
     1757
     1758>>> f = ARCUITField(required=False)
     1759>>> f.clean('20-10123456-9')
     1760u'20-10123456-9'
     1761>>> f.clean(u'20-10123456-9')
     1762u'20-10123456-9'
     1763>>> f.clean('27-10345678-4')
     1764u'27-10345678-4'
     1765>>> f.clean('20101234569')
     1766u'20-10123456-9'
     1767>>> f.clean('27103456784')
     1768u'27-10345678-4'
     1769>>> f.clean('2-10123456-9')
     1770Traceback (most recent call last):
     1771...
     1772ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1773>>> f.clean('210123456-9')
     1774Traceback (most recent call last):
     1775...
     1776ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1777>>> f.clean('20-10123456')
     1778Traceback (most recent call last):
     1779...
     1780ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1781>>> f.clean('20-10123456-')
     1782Traceback (most recent call last):
     1783...
     1784ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1785>>> f.clean('20-10123456-5')
     1786Traceback (most recent call last):
     1787...
     1788ValidationError: [u'Invalid CUIT.']
     1789>>> f.clean(u'2-10123456-9')
     1790Traceback (most recent call last):
     1791...
     1792ValidationError: [u'Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
     1793>>> f.clean('27-10345678-1')
     1794Traceback (most recent call last):
     1795...
     1796ValidationError: [u'Invalid CUIT.']
     1797>>> f.clean(u'27-10345678-1')
     1798Traceback (most recent call last):
     1799...
     1800ValidationError: [u'Invalid CUIT.']
     1801>>> f.clean(None)
     1802u''
     1803>>> f.clean('')
     1804u''
     1805>>> f.clean(u'')
     1806u''
    15171807"""
Back to Top