| 32 | class USSocialSecurityNumberField(Field): |
| 33 | """ |
| 34 | A United States Social Security number. |
| 35 | |
| 36 | Checks the following rules to determine whether the number is valid: |
| 37 | |
| 38 | * Conforms to the XXX-XX-XXXX format. |
| 39 | * No group consists entirely of zeroes. |
| 40 | * The leading group is not "666" (block "666" will never be allocated). |
| 41 | * The number is not in the promotional block 987-65-4320 through 987-65-4329, |
| 42 | which are permanently invalid. |
| 43 | * The number is not one known to be invalid due to otherwise widespread |
| 44 | promotional use or distribution (e.g., the Woolworth's number or the 1962 |
| 45 | promotional number). |
| 46 | |
| 47 | """ |
| 48 | def clean(self, value): |
| 49 | super(USSocialSecurityNumberField, self).clean(value) |
| 50 | if value in EMPTY_VALUES: |
| 51 | return u'' |
| 52 | msg = gettext(u'Enter a valid US Social Security number in XXX-XX-XXXX format') |
| 53 | match = re.match(ssn_re, value) |
| 54 | if not match: |
| 55 | raise ValidationError(msg) |
| 56 | area, group, serial = match.groupdict()['area'], match.groupdict()['group'], match.groupdict()['serial'] |
| 57 | |
| 58 | # First pass: no blocks of all zeroes. |
| 59 | if area == '000' or \ |
| 60 | group == '00' or \ |
| 61 | serial == '0000': |
| 62 | raise ValidationError(msg) |
| 63 | |
| 64 | # Second pass: promotional and otherwise permanently invalid numbers. |
| 65 | if area == '666' or \ |
| 66 | (area == '987' and group == '65' and \ |
| 67 | 4320 <= int(serial) <= 4329) or \ |
| 68 | value == '078-05-1120' or \ |
| 69 | value == '219-09-9999': |
| 70 | raise ValidationError(msg) |
| 71 | return u'%s-%s-%s' % (area, group, serial) |
| 72 | |