Code

Ticket #3890: us_ssnfield.diff

File us_ssnfield.diff, 2.4 KB (added by ubernostrum, 7 years ago)

Patch adding USSocialSecurityNumberField

Line 
1Index: django/contrib/localflavor/usa/forms.py
2===================================================================
3--- django/contrib/localflavor/usa/forms.py     (revision 4881)
4+++ django/contrib/localflavor/usa/forms.py     (working copy)
5@@ -9,6 +9,7 @@
6 import re
7 
8 phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$')
9+ssn_re = re.compile(r"^(?P<area>\d{3})-(?P<group>\d{2})-(?P<serial>\d{4})$")
10 
11 class USZipCodeField(RegexField):
12     def __init__(self, *args, **kwargs):
13@@ -28,6 +29,47 @@
14             return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
15         raise ValidationError(u'Phone numbers must be in XXX-XXX-XXXX format.')
16 
17+class USSocialSecurityNumberField(Field):
18+    """
19+    A United States Social Security number.
20+   
21+    Checks the following rules to determine whether the number is valid:
22+   
23+        * Conforms to the XXX-XX-XXXX format.
24+        * No group consists entirely of zeroes.
25+        * The leading group is not "666" (block "666" will never be allocated).
26+        * The number is not in the promotional block 987-65-4320 through 987-65-4329,
27+          which are permanently invalid.
28+        * The number is not one known to be invalid due to otherwise widespread
29+          promotional use or distribution (e.g., the Woolworth's number or the 1962
30+          promotional number).
31+   
32+    """
33+    def clean(self, value):
34+        super(USSocialSecurityNumberField, self).clean(value)
35+        if value in EMPTY_VALUES:
36+            return u''
37+        msg = gettext(u'Enter a valid US Social Security number in XXX-XX-XXXX format')
38+        match = re.match(ssn_re, value)
39+        if not match:
40+            raise ValidationError(msg)
41+        area, group, serial = match.groupdict()['area'], match.groupdict()['group'], match.groupdict()['serial']
42+       
43+        # First pass: no blocks of all zeroes.
44+        if area == '000' or \
45+           group == '00' or \
46+           serial == '0000':
47+            raise ValidationError(msg)
48+       
49+        # Second pass: promotional and otherwise permanently invalid numbers.
50+        if area == '666' or \
51+           (area == '987' and group == '65' and \
52+            4320 <= int(serial) <= 4329) or \
53+           value == '078-05-1120' or \
54+           value == '219-09-9999':
55+            raise ValidationError(msg)
56+        return value
57+
58 class USStateField(Field):
59     """
60     A form field that validates its input is a U.S. state name or abbreviation.