Code

Ticket #6427: localflavor.at-2.diff

File localflavor.at-2.diff, 6.2 KB (added by Horst Gutmann <zerok@…>, 6 years ago)

Some final changes to the documentation to clarify the origin of the whole SSN checker

Line 
1diff --git a/django/contrib/localflavor/at/__init__.py b/django/contrib/localflavor/at/__init__.py
2new file mode 100644
3index 0000000..e69de29
4diff --git a/django/contrib/localflavor/at/at_provinces.py b/django/contrib/localflavor/at/at_provinces.py
5new file mode 100644
6index 0000000..da51b0a
7--- /dev/null
8+++ b/django/contrib/localflavor/at/at_provinces.py
9@@ -0,0 +1,21 @@
10+# -*- coding: utf-8 -*-
11+"""
12+A list of all nine provinces in Austria, see also:
13+http://en.wikipedia.org/wiki/ISO_3166-2:AT . Vienna is moved to the top,
14+because it's the capital of Austria
15+"""
16+
17+from django.utils.translation import ugettext_lazy as _
18+
19+# ISO_3166-2
20+PROVINCE_CHOICES = (
21+       ('9', _(u'Vienna')),
22+       ('1', _(u'Burgenland')),
23+       ('2', _(u'Carinthia')),
24+       ('3', _(u'Lower Austria')),
25+       ('4', _(u'Upper Austria')),
26+       ('5', _(u'Salzburg')),
27+       ('6', _(u'Styria')),
28+       ('7', _(u'Tyrol')),
29+       ('8', _(u'Vorarlberg')),
30+)
31\ No newline at end of file
32diff --git a/django/contrib/localflavor/at/forms.py b/django/contrib/localflavor/at/forms.py
33new file mode 100644
34index 0000000..9a2f5f5
35--- /dev/null
36+++ b/django/contrib/localflavor/at/forms.py
37@@ -0,0 +1,65 @@
38+"""
39+AT-specific Form helpers
40+"""
41+
42+from django.newforms.fields import RegexField, Select, Field
43+from django.newforms import ValidationError
44+from django.utils.translation import ugettext
45+import re
46+
47+re_ssn = re.compile(r'^\d{4} \d{6}')
48+
49+class ATZipCodeField(RegexField):
50+    """
51+    A simple input field that validates 4-digit zip codes as used in Austria.
52+    """
53+   
54+    default_error_messages = {
55+        'invalid': ugettext('Enter a zip code in the format XXXX.'),
56+    }
57+
58+    def __init__(self, *args, **kwargs):
59+        super(ATZipCodeField, self).__init__(r'^[1-9]\d{3}$',
60+            max_length=None, min_length=None, *args, **kwargs)
61+
62+class ATProvinceSelect(Select):
63+    """
64+    A simple select box for all nine provinces of Austria.
65+    """
66+   
67+    def __init__(self, attrs=None):
68+        from django.contrib.localflavor.at.at_provinces import PROVINCE_CHOICES
69+        super(ATProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
70+
71+class ATSocialSecurityNumberField(Field):
72+    """
73+    Austrian Social Security numbers are composed of a 4 digits and 6 digits
74+    field. The latter represents in most cases the person's birthdate while
75+    the first 4 digits represent a 3-digits-counter and a one-digit checksum.
76+   
77+    The 6-digits-field can also differ from the person's birthdate if the
78+    3-digits counter suffered an overflow.
79+   
80+    This code is based on information available on
81+    http://de.wikipedia.org/wiki/Sozialversicherungsnummer#.C3.96sterreich
82+    """
83+   
84+    default_error_messages = {
85+        'invalid': ugettext(u'Enter a valid Austrian Social Security Number in XXXX XXXXXX format.'),
86+    }
87+   
88+    def clean(self, value):
89+        if not re_ssn.search(value):
90+            raise ValidationError(self.error_messages['invalid'])
91+        sqnr, date = value.split(" ")
92+        sqnr, check = (sqnr[:3], (sqnr[3]))
93+        if int(sqnr) < 100:
94+           raise ValidationError(self.error_messages['invalid'])
95+        res = int(sqnr[0])*3 + int(sqnr[1])*7 + int(sqnr[2])*9 \
96+           + int(date[0])*5 + int(date[1])*8 + int(date[2])*4 \
97+           + int(date[3])*2 + int(date[4])*1 + int(date[5])*6
98+        res = res % 11
99+        if res != int(check):
100+           raise ValidationError(self.error_messages['invalid'])
101+        return u'%s%s %s'%(sqnr, check, date,)
102+       
103diff --git a/tests/regressiontests/forms/localflavor/at.py b/tests/regressiontests/forms/localflavor/at.py
104new file mode 100644
105index 0000000..b230329
106--- /dev/null
107+++ b/tests/regressiontests/forms/localflavor/at.py
108@@ -0,0 +1,37 @@
109+# -*- coding: utf-8 -*-
110+# Tests for contrib/localflavor/at form fields
111+
112+tests = r"""
113+# ATZipCodeField ############################################################
114+
115+>>> from django.contrib.localflavor.at.forms import ATZipCodeField
116+>>> f = ATZipCodeField()
117+>>> f.clean('9073')
118+u'9073'
119+>>> f.clean('90730')
120+Traceback (most recent call last):
121+...
122+ValidationError: [u'Enter a zip code in the format XXXX.']
123+>>> f.clean('0073')
124+Traceback (most recent call last):
125+...
126+ValidationError: [u'Enter a zip code in the format XXXX.']
127+
128+# ATProvinceSelect ##########################################################
129+
130+>>> from django.contrib.localflavor.at.forms import ATProvinceSelect
131+>>> w = ATProvinceSelect()
132+>>> w.render('provinces', '2')
133+u'<select name="provinces">\n<option value="9">Vienna</option>\n<option value="1">Burgenland</option>\n<option value="2" selected="selected">Carinthia</option>\n<option value="3">Lower Austria</option>\n<option value="4">Upper Austria</option>\n<option value="5">Salzburg</option>\n<option value="6">Styria</option>\n<option value="7">Tyrol</option>\n<option value="8">Vorarlberg</option>\n</select>'
134+
135+# ATSocialSecurityNumberField ###############################################
136+
137+>>> from django.contrib.localflavor.at.forms import ATSocialSecurityNumberField
138+>>> f = ATSocialSecurityNumberField()
139+>>> f.clean('1237 010180')
140+u'1237 010180'
141+>>> f.clean('1237 010181')
142+Traceback (most recent call last):
143+...
144+ValidationError: [u'Enter a valid Austrian Social Security Number in XXXX XXXXXX format.']
145+"""
146diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py
147index bb0e30b..0891c1b 100644
148--- a/tests/regressiontests/forms/tests.py
149+++ b/tests/regressiontests/forms/tests.py
150@@ -4,6 +4,7 @@ from fields import tests as fields_tests
151 from forms import tests as form_tests
152 from error_messages import tests as custom_error_message_tests
153 from localflavor.ar import tests as localflavor_ar_tests
154+from localflavor.at import tests as localflavor_at_tests
155 from localflavor.au import tests as localflavor_au_tests
156 from localflavor.br import tests as localflavor_br_tests
157 from localflavor.ca import tests as localflavor_ca_tests
158@@ -33,6 +34,7 @@ __test__ = {
159     'form_tests': form_tests,
160     'custom_error_message_tests': custom_error_message_tests,
161     'localflavor_ar_tests': localflavor_ar_tests,
162+    'localflavor_at_tests': localflavor_at_tests,
163     'localflavor_au_tests': localflavor_au_tests,
164     'localflavor_br_tests': localflavor_br_tests,
165     'localflavor_ca_tests': localflavor_ca_tests,