| | 1 | """ |
| | 2 | Chile specific form helpers. |
| | 3 | """ |
| | 4 | from django.newforms import ValidationError |
| | 5 | from django.newforms.fields import RegexField, EMPTY_VALUES |
| | 6 | from django.utils.translation import gettext |
| | 7 | |
| | 8 | class CLRutField(RegexField): |
| | 9 | """ |
| | 10 | Chilean "Rol Unico Tributario" (RUT) field. This is the chilean national identification number. |
| | 11 | """ |
| | 12 | def __init__(self, *args, **kwargs): |
| | 13 | if kwargs.get('strict') == True: |
| | 14 | del kwargs['strict'] |
| | 15 | super(CLRutField, self).__init__(r'^(\d{1,2}\.)?\d{3}\.\d{3}-[\dkK]$', |
| | 16 | error_message=gettext(u'Enter valid a Chilean Rut. The format is XX.XXX.XXX-X.'), |
| | 17 | *args, **kwargs) |
| | 18 | else: # We take it relaxed and format it for the user, |
| | 19 | # accepting RUTs that are validate, but do not exist in the real world. |
| | 20 | super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', |
| | 21 | error_message=gettext(u'Enter valid a Chilean RUT'), |
| | 22 | *args, **kwargs) |
| | 23 | |
| | 24 | def clean(self, value): |
| | 25 | """ |
| | 26 | Check and clean the chilean rut. |
| | 27 | """ |
| | 28 | super(CLRutField, self).clean(value) |
| | 29 | if value in EMPTY_VALUES: |
| | 30 | return u'' |
| | 31 | (rut, verificador) = self._canonify(value) |
| | 32 | if self._algorithm(rut) == verificador: |
| | 33 | return self._format(rut, verificador) |
| | 34 | else: |
| | 35 | raise ValidationError(u'The Chilean RUT is not valid.') |
| | 36 | |
| | 37 | |
| | 38 | def _algorithm(self, rut): |
| | 39 | """ |
| | 40 | Takes RUT in pure canonical form, calculates the verifier digit. |
| | 41 | """ |
| | 42 | suma = 0 |
| | 43 | multi = 2 |
| | 44 | for r in rut[::-1]: |
| | 45 | suma += int (r) * multi |
| | 46 | multi += 1 |
| | 47 | if multi == 8: |
| | 48 | multi = 2 |
| | 49 | rest = suma % 11 |
| | 50 | rest = 11 - rest |
| | 51 | if rest == 11: return '0' |
| | 52 | elif rest == 10: return 'K' |
| | 53 | else: return str(rest) |
| | 54 | |
| | 55 | def _canonify(self, rut): |
| | 56 | """ |
| | 57 | Turns the rut into one normalized format. Returns a (rut, verifier) tuple. |
| | 58 | """ |
| | 59 | rut = str(rut) |
| | 60 | rut = rut.replace(' ', '') |
| | 61 | rut = rut.replace('.', '') |
| | 62 | rut = rut.replace('-', '') |
| | 63 | return (rut[:-1], rut[-1]) |
| | 64 | |
| | 65 | def _format(self, code, verifier=None): |
| | 66 | """ |
| | 67 | Formats the rut from canonical form to the common string representation. |
| | 68 | If verifier=None, then the last digit in 'code' is the verifier. |
| | 69 | """ |
| | 70 | if(verifier == None): |
| | 71 | verifier = code[-1] |
| | 72 | code = code[:-1] |
| | 73 | while len(code) > 3 and (code.find('.') > 3 or code.find('.') == -1): |
| | 74 | if code.find('.') == -1: |
| | 75 | new_dot = -3 |
| | 76 | else: |
| | 77 | new_dot = code.find('.')-3 |
| | 78 | code = code[:new_dot] +'.'+code[new_dot:] |
| | 79 | return '%s-%s' % (code, verifier) |
| | 80 | |