Re: [Python-es] validación cif

Cesar Ortiz cesar en ortiz.name
Mie Abr 29 15:50:23 CEST 2009


Bueno... para quien le pueda interesar... creo que ya lo tengo.

Voy a echarle un ojo a la implementación de django, a ver si es correcta.
Chema tu implementación creo que no es correcta, creo que al menos tiene un
error en  la comprobación de _testNIFJuridica() cuando compruebas si las
posiciones son pares o impares. Yo cometí el mismo error. La cuestión es que
si tomamos como primera posición el 2, estas cambiando el algormitmo. La
primera posición tendría que ser el 1 => tienes los calculos de impar/par
cambiados.

Adjunto el código,

Saludos!

PD: Cuando digo que un nif o cif está normalizado, me refiero a que están
todas las letras/digitos seguidos sin ningún tipo de separador (ej:
P1234567A))

#-------------------------------------------------------------------------------
# Validador
#-------------------------------------------------------------------------------

class Validador(object):
  TABLA_NIF='TRWAGMYFPDXBNJZSQVHLCKE'       # Valores para validar el NIF

  CLAVES_CIF='PQS' + 'ABEH' + 'CDFGJRUVNW'
  CLAVES_NIF1 = 'LKM'                       # Son especiales, se validan
                                            # como CIFs
  CLAVES_NIF2 = 'XYZ'
  CLAVES_NIF = CLAVES_NIF1 + CLAVES_NIF2


  CONTROL_CIF_LETRA = 'KPQS'
  CONTROL_CIF_NUMERO = 'ABEH'

  EQUIVALENCIAS_CIF = {1:'A', 2:'B', 3:'C', 4:'D', 5:'E', 6:'F', 7:'G',
8:'H', 9:'I', 10:'J', 0:'J'}

#-------------------------------------------------------------------------------


  def validarNIF(self,valor):
    """
    Nos indica si un NIF es valido.
    El valor debe estar normalizado
    @note:
      - ante cualquier problema se valida como False
    """
    bRet = False

    if len(valor) == 9:
      try:
        if valor[0] in self.__class__.CLAVES_NIF1:
          bRet = self.validarCIF(valor)
        else:
          num=None
          if valor[0] in self.__class__.CLAVES_NIF2:
            pos = self.__class__.CLAVES_NIF2.find(valor[0])
            sNum = str(pos) + valor[1:-1]
            num=int(sNum)
          elif valor[0].isdigit():
            num=int(valor[:-1])
          if num!=None and self.__class__.TABLA_NIF[num%23] == valor[-1]:
              bRet=True
      except:
        pass

    return bRet

#-------------------------------------------------------------------------------


  def validarCIF(self,valor):
    """
    Nos indica si un CIF es valido.
    El valor debe estar normalizado
    @note:
      - ante cualquier problema se valida como False
    """
    bRet = False

    if len(valor) == 9:
      v0 = valor[0]
      if v0 in self.__class__.CLAVES_NIF1 or v0 in
self.__class__.CLAVES_CIF:
        try:
          sumPar = 0
          sumImpar = 0
          for i in xrange(1,8):
            if i % 2:
              v = int(valor[i]) * 2
              if v > 9: v = 1 + (v - 10)
              sumImpar += v
            else:
              v = int(valor[i])
              sumPar += v
          suma = sumPar + sumImpar
          e = suma % 10
          d = 10 - e
          letraCif = self.__class__.EQUIVALENCIAS_CIF[d]
          if valor[0] in self.__class__.CONTROL_CIF_LETRA:
            if valor[-1] == letraCif: bRet = True
          elif valor[0] in self.__class__.CONTROL_CIF_NUMERO:
            if d == 10: d = 0
            if valor[-1] == str(d): bRet = True
          else:
            if d == 10: d = 0
            if valor[-1] == str(d) or valor[-1] == letraCif: bRet = True
        except:
          pass

    return bRet


#-------------------------------------------------------------------------------


  def validar(self,valor):
    """
    Nos valida un CIF o un NIF
    """
    bRet = False

    if len(valor) == 9:
      if valor[0] in self.__class__.CLAVES_NIF or valor[0].isdigit():
        bRet = self.validarNIF(valor)
      else:
        bRet = self.validarCIF(valor)

    return bRet

#-------------------------------------------------------------------------------




2009/4/28 Cesar Ortiz <cesar en ortiz.name>

> Gracias!
>
> Anotada la nueva url para poder acceder a los archivos.
> Echaré un ojo a ese codigo para contrastarlo con una implementación que he
> hecho.
> Sólo vi online la de la url de antes y de fijo que está mal.
>
> Un saludos.
>
> 2009/4/28 Chema Cortes <pych3m4 en gmail.com>
>
> El día 28 de abril de 2009 18:10, Luis Peralta <peralta en aditel.org>
>> escribió:
>> > Hola César,
>> >
>> > El día 28 de abril de 2009 15:45, Cesar Ortiz <cesar en ortiz.name>
>> escribió:
>>
>> No me ha llegado este mensaje :-(
>>
>> Lo veo en gmane.org, que es una alternativa para cuando falle la web
>> de la lista:
>>
>> http://news.gmane.org/gmane.comp.python.general.castellano
>>
>> >>
>> >> Que creo erronea. ¿Sabeis de alguna implementación que esté online?
>> >
>> > La de django, ESIdentityCardNumberField:
>> >
>> >
>> http://code.djangoproject.com/browser/django/trunk/django/contrib/localflavor/es/forms.py
>> >
>> > No la he usado, pero sé que está ahí ;)
>>
>> Aún mantengo una vieja implementación:
>>
>> http://ch3m4.org/pystore/Calcnif.py
>>
>>
>> Tengo pendiente darle un buen repaso para adaptarla al nuevo estilo
>> python.
>>
>> Fallos de esta implementación (y la de django):
>>
>> - No admite los NIEs que empiezan por 'Y'
>> - Muy pronto aparecerán NIFs de 9 dígitos+letra (pasaremos de los 100
>> millones)
>> _______________________________________________
>> Lista de correo Python-es
>> http://listas.aditel.org/listinfo/python-es
>> FAQ: http://listas.aditel.org/faqpyes
>>
>
>
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es