Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Adding MXSocialSecurityNumberField to local flavor #42

Closed
wants to merge 8 commits into from

4 participants

Gerard Orozco Francisco Albarran Cristobal Adrian Holovaty Ramiro Morales
Gerard Orozco

Adding MXSocialSecurityNumberField to local flavor

AUTHORS
@@ -563,6 +563,7 @@ answer newbie questions, and generally made Django that much better:
563 563
     Gasper Zejn <zejn@kiberpipa.org>
564 564
     Jarek Zgoda <jarek.zgoda@gmail.com>
565 565
     Cheng Zhang
  566
+    Francisco Albarran Cristobal <pahko.xd@gmail.com>
1
Ramiro Morales Owner
ramiro added a note May 03, 2012

Contributor names in the AUTHORS file need to be sorted by last name.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
django/contrib/localflavor/mx/forms.py
((11 lines not shown))
  233
+    following the next pattern:
  234
+
  235
+    =====  =======================================
  236
+    Index  Required numbers
  237
+    =====  =======================================
  238
+    1-2    The number of the branch office where the Social Security Number
  239
+           was designated.
  240
+    3-4    The year of inscription to the Social Security.
  241
+    5-6    The year of birth of the Social Security Number owner.
  242
+    7-10   The progressive number of procedure for the IMSS.
  243
+           (This digit is provided exclusively by the Institute as it regards
  244
+            the Folio number of such procedure).
  245
+    11     The verification digit.
  246
+
  247
+    More info about this:
  248
+        <reference here>
1
Ramiro Morales Owner
ramiro added a note May 03, 2012

Please add the reference or simply remove the section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Francisco Albarran Cristobal
pahko commented May 03, 2012

Now Fixed @ramiro thanks.

Adrian Holovaty

Hey there -- django.contrib.localflavor is now deprecated, and we're not making any more changes to it (see https://docs.djangoproject.com/en/dev/ref/contrib/localflavor/). Could you reopen this pull request for the shiny new package django-localflavor-mx? Here's the link: https://github.com/django/django-localflavor-mx

Sorry we didn't get to this pull request before the deprecation. I hope it's not too much of a pain to migrate this to the new package.

Adrian Holovaty adrianholovaty closed this October 15, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
1  AUTHORS
@@ -43,6 +43,7 @@ answer newbie questions, and generally made Django that much better:
43 43
     ajs <adi@sieker.info>
44 44
     alang@bright-green.com
45 45
     A S Alam <aalam@users.sf.net>
  46
+    Francisco Albarran Cristobal <pahko.xd@gmail.com>
46 47
     Andi Albrecht <albrecht.andi@gmail.com>
47 48
     Marty Alchin <gulopine@gamemusic.org>
48 49
     Ahmad Alhashemi <trans@ahmadh.com>
58  django/contrib/localflavor/mx/forms.py
@@ -17,7 +17,6 @@
17 17
 document described in the next link:
18 18
     http://www.sisi.org.mx/jspsi/documentos/2005/seguimiento/06101/0610100162005_065.doc
19 19
 """
20  
-
21 20
 RFC_INCONVENIENT_WORDS = [
22 21
     u'BUEI', u'BUEY', u'CACA', u'CACO', u'CAGA', u'CAGO', u'CAKA', u'CAKO',
23 22
     u'COGE', u'COJA', u'COJE', u'COJI', u'COJO', u'CULO', u'FETO', u'GUEY',
@@ -46,6 +45,7 @@
46 45
    u'WUEY',
47 46
 ]
48 47
 
  48
+
49 49
 class MXStateSelect(Select):
50 50
     """
51 51
     A Select widget that uses a list of Mexican states as its choices.
@@ -105,8 +105,8 @@ class MXRFCField(RegexField):
105 105
         http://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(M%C3%A9xico)
106 106
     """
107 107
     default_error_messages = {
108  
-        'invalid': _('Enter a valid RFC.'),
109  
-        'invalid_checksum': _('Invalid checksum for RFC.'),
  108
+        'invalid': _(u'Enter a valid RFC.'),
  109
+        'invalid_checksum': _(u'Invalid checksum for RFC.'),
110 110
     }
111 111
 
112 112
     def __init__(self, min_length=9, max_length=13, *args, **kwargs):
@@ -186,7 +186,7 @@ class MXCURPField(RegexField):
186 186
         http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp
187 187
     """
188 188
     default_error_messages = {
189  
-        'invalid': _('Enter a valid CURP.'),
  189
+        'invalid': _(u'Enter a valid CURP.'),
190 190
         'invalid_checksum': _(u'Invalid checksum for CURP.'),
191 191
     }
192 192
 
@@ -223,3 +223,53 @@ def _checksum(self, value):
223 223
     def _has_inconvenient_word(self, curp):
224 224
         first_four = curp[:4]
225 225
         return first_four in CURP_INCONVENIENT_WORDS
  226
+
  227
+
  228
+class MXSocialSecurityNumberField(RegexField):
  229
+    """
  230
+    A field that validates a Mexican Social Security Number.
  231
+
  232
+    The Social Security Number is integrated by a juxtaposition of digits
  233
+    following the next pattern:
  234
+
  235
+    =====  =======================================
  236
+    Index  Required numbers
  237
+    =====  =======================================
  238
+    1-2    The number of the branch office where the Social Security Number
  239
+           was designated.
  240
+    3-4    The year of inscription to the Social Security.
  241
+    5-6    The year of birth of the Social Security Number owner.
  242
+    7-10   The progressive number of procedure for the IMSS.
  243
+           (This digit is provided exclusively by the Institute as it regards
  244
+            the Folio number of such procedure).
  245
+    11     The verification digit.
  246
+    """
  247
+    default_error_messages = {
  248
+        'invalid': _(u'Enter a valid Social Security Number.'),
  249
+        'invalid_checksum': _(u'Invalid checksum for Social Security Number.'),
  250
+    }
  251
+
  252
+    def __init__(self, min_length=11, max_length=11, *args, **kwargs):
  253
+        ssn_re = ur'^\d{11}$'
  254
+        ssn_re = re.compile(ssn_re)
  255
+        super(MXSocialSecurityNumberField, self).__init__(ssn_re,
  256
+            min_length=min_length, max_length=max_length, *args, **kwargs)
  257
+
  258
+    def clean(self, value):
  259
+        value = super(MXSocialSecurityNumberField, self).clean(value)
  260
+        if value in EMPTY_VALUES:
  261
+            return u''
  262
+        if value[-1] != self.__checksum(value[:-1]):
  263
+            raise ValidationError(self.default_error_messages['invalid_checksum'])
  264
+        return value
  265
+
  266
+    def __checksum(self, value):
  267
+        multipliers = [1 if i % 2 == 0 else 2 for i in xrange(10)]
  268
+
  269
+        s = [int(v) * m for v, m in zip(value, multipliers)]
  270
+        s = sum(map(int, ''.join(map(str, s))))
  271
+        checksum = 10 - s % 10
  272
+
  273
+        if checksum == 10:
  274
+            return u'0'
  275
+        return unicode(checksum)
22  django/contrib/localflavor/mx/models.py
@@ -3,7 +3,8 @@
3 3
 
4 4
 from django.contrib.localflavor.mx.mx_states import STATE_CHOICES
5 5
 from django.contrib.localflavor.mx.forms import (MXRFCField as MXRFCFormField,
6  
-    MXZipCodeField as MXZipCodeFormField, MXCURPField as MXCURPFormField)
  6
+    MXZipCodeField as MXZipCodeFormField, MXCURPField as MXCURPFormField,
  7
+    MXSocialSecurityNumberField as MXSocialSecurityNumberFormField)
7 8
 
8 9
 
9 10
 class MXStateField(CharField):
@@ -67,4 +68,21 @@ def __init__(self, *args, **kwargs):
67 68
     def formfield(self, **kwargs):
68 69
         defaults = {'form_class': MXCURPFormField}
69 70
         defaults.update(kwargs)
70  
-        return super(MXCURPField, self).formfield(**defaults)
  71
+        return super(MXCURPField, self).formfield(**defaults)
  72
+
  73
+
  74
+class MXSocialSecurityNumberField(CharField):
  75
+    """
  76
+    A model field that forms represent as a forms.MXSocialSecurityNumberField
  77
+    field and stores the value of a valid Mexican Social Security Number.
  78
+    """
  79
+    description = _("Mexican Social Security Number")
  80
+
  81
+    def __init__(self, *args, **kwargs):
  82
+        kwargs['max_length'] = 11
  83
+        super(MXSocialSecurityNumberField, self).__init__(*args, **kwargs)
  84
+
  85
+    def formfield(self, **kwargs):
  86
+        defaults = {'form_class': MXSocialSecurityNumberFormField}
  87
+        defaults.update(kwargs)
  88
+        return super(MXSocialSecurityNumberField, self).formfield(**defaults)
10  docs/ref/contrib/localflavor.txt
@@ -842,6 +842,11 @@ Mexico (``mx``)
842 842
 
843 843
 .. _curp: http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp
844 844
 
  845
+.. class:: mx.forms.MXSocialSecurityNumberField
  846
+
  847
+   A field that validates a Mexican Social Security Number(NSS) for *Instituto Mexicano del Seguro Social*.
  848
+
  849
+
845 850
 .. class:: mx.forms.MXStateSelect
846 851
 
847 852
     A ``Select`` widget that uses a list of Mexican states as its choices.
@@ -874,6 +879,11 @@ Mexico (``mx``)
874 879
     A model field that forms represent as a ``forms.MXCURPField`` field and
875 880
     stores the value of a valid Mexican CURP.
876 881
 
  882
+.. class:: mx.models.MXSocialSecurityNumberField
  883
+
  884
+    A model field that forms represent as a ``forms.MXSocialSecurityNumberField`` field and
  885
+    stores the eleven-digit Mexican Social Security Number for *Instituto Mexicano del Seguro Social*.
  886
+
877 887
 Additionally, a choice tuple is provided in ``django.contrib.localflavor.mx.mx_states``,
878 888
 allowing customized model and form fields, and form presentations, for subsets of
879 889
 Mexican states abbreviations:
4  tests/regressiontests/localflavor/mx/models.py
... ...
@@ -1,5 +1,6 @@
1 1
 from django.contrib.localflavor.mx.models import (
2  
-    MXStateField, MXRFCField, MXCURPField, MXZipCodeField)
  2
+    MXStateField, MXRFCField, MXCURPField, MXZipCodeField,
  3
+    MXSocialSecurityNumberField)
3 4
 from django.db import models
4 5
 
5 6
 
@@ -8,6 +9,7 @@ class MXPersonProfile(models.Model):
8 9
     rfc = MXRFCField()
9 10
     curp = MXCURPField()
10 11
     zip_code = MXZipCodeField()
  12
+    ssn = MXSocialSecurityNumberField()
11 13
 
12 14
     class Meta:
13 15
         app_label = 'localflavor'
48  tests/regressiontests/localflavor/mx/tests.py
@@ -2,7 +2,7 @@
2 2
 from __future__ import absolute_import
3 3
 
4 4
 from django.contrib.localflavor.mx.forms import (MXZipCodeField, MXRFCField,
5  
-    MXStateSelect, MXCURPField)
  5
+    MXStateSelect, MXCURPField, MXSocialSecurityNumberField)
6 6
 from django.test import SimpleTestCase
7 7
 
8 8
 from .forms import MXPersonProfileForm
@@ -16,6 +16,7 @@ def setUp(self):
16 16
             'rfc': 'toma880125kv3',
17 17
             'curp': 'toma880125hmnrrn02',
18 18
             'zip_code': '58120',
  19
+            'ssn': '53987417457',
19 20
         })
20 21
 
21 22
     def test_get_display_methods(self):
@@ -30,12 +31,14 @@ def test_errors(self):
30 31
             'rfc': 'invalid rfc',
31 32
             'curp': 'invalid curp',
32 33
             'zip_code': 'xxx',
  34
+            'ssn': 'invalid ssn',
33 35
         })
34 36
         self.assertFalse(form.is_valid())
35 37
         self.assertEqual(form.errors['state'], [u'Select a valid choice. Invalid state is not one of the available choices.'])
36 38
         self.assertEqual(form.errors['rfc'], [u'Enter a valid RFC.'])
37 39
         self.assertEqual(form.errors['curp'], [u'Ensure this value has at least 18 characters (it has 12).', u'Enter a valid CURP.'])
38 40
         self.assertEqual(form.errors['zip_code'], [u'Enter a valid zip code in the format XXXXX.'])
  41
+        self.assertEqual(form.errors['ssn'], [u'Enter a valid Social Security Number.'])
39 42
 
40 43
     def test_field_blank_option(self):
41 44
         """Test that the empty option is there."""
@@ -196,3 +199,46 @@ def test_MXCURPField(self):
196 199
             'OOMG890727HMNRSR07': error_checksum,
197 200
         }
198 201
         self.assertFieldOutput(MXCURPField, valid, invalid)
  202
+
  203
+    def test_MXSocialSecurityNumberField(self):
  204
+        error_format = [u'Enter a valid Social Security Number.']
  205
+        error_checksum = [u'Invalid checksum for Social Security Number.']
  206
+        valid = {
  207
+            '53987417457': u'53987417457',
  208
+            '53916912966': u'53916912966',
  209
+            '53986504172': u'53986504172',
  210
+            '17300426925': u'17300426925',
  211
+            '53067407212': u'53067407212',
  212
+            '53018000538': u'53018000538',
  213
+            '10836311612': u'10836311612',
  214
+            '37007910666': u'37007910666',
  215
+            '53055700974': u'53055700974',
  216
+            '17303364941': u'17303364941',
  217
+            '53078528469': u'53078528469',
  218
+        }
  219
+        invalid = {
  220
+            # Invalid format
  221
+            '5398741A457': error_format,
  222
+            '53487G12031': error_format,
  223
+            '530P8028702': error_format,
  224
+            '173004K6925': error_format,
  225
+            '5306T407212': error_format,
  226
+            '53018N00538': error_format,
  227
+            'E0836311612': error_format,
  228
+            '3700U910666': error_format,
  229
+            '530557 0974': error_format,
  230
+            '173033?4941': error_format,
  231
+            '53#88417917': error_format,
  232
+            # Incorrect checksum
  233
+            '53987417451': error_checksum,
  234
+            '53018522942': error_checksum,
  235
+            '53897239693': error_checksum,
  236
+            '01704423244': error_checksum,
  237
+            '53855919735': error_checksum,
  238
+            '53926201296': error_checksum,
  239
+            '53017919037': error_checksum,
  240
+            '53884201248': error_checksum,
  241
+            '42805762629': error_checksum,
  242
+            '53563800130': error_checksum,
  243
+        }
  244
+        self.assertFieldOutput(MXSocialSecurityNumberField, valid, invalid)
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.