Validar un CIF, NIF


#1

Hola chicos,

Iba a ponerme a escribir un método para validar un CIF[1], pero el
compi del al lado[2] me ha dicho que sois über-majos y que seguro que
alguno lo ha escrito alguna vez… ¿es eso cierto?

Gracias 0:-)

[1]
http://es.wikipedia.org/wiki/Código_de_Identificación_Fiscal
[2] http://simplelogica.net/logicola

David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net


#2

Hola David!

Iba a ponerme a escribir un método para validar un CIF[1], pero el
compi del al lado[2] me ha dicho que sois über-majos y que seguro que
alguno lo ha escrito alguna vez… ¿es eso cierto?

Lo de que somos über-majos es ciertísimo, claro! :smiley:

En cuanto a la validación que pides, casualmente me ha tocado
implementarla hoy (tampoco la he encontrado en la red). Aquí va:

def add_digits_from_int(n)
digits = str_to_int_array(n.to_s)
digits.inject(0) { |acum, n| acum + n }
end

def str_to_int_array(str)
(0…(str.length-1)).inject([]) { |result, pos| result <<
str[pos,1].to_i }
end

def is_a_valid_cif?(candidate)
return false unless candidate.length == 9

 # We also accept NIFs, NIF validation algoritm taken from:
 # 

http://es.wikipedia.org/wiki/Algoritmo_para_obtener_la_letra_del_NIF
if candidate.match(/\D(\d{8})/)
nif_letter = candidate[0,1]
nif_digits = candidate[1,8]
elsif candidate.match(/(\d{8})\D/)
nif_letter = candidate[-1, 1]
nif_digits = candidate[0,8]
end
nif_addition = nif_digits.to_i % 23
return true if nif_letter && nif_digits &&
‘TRWAGMYFPDXBNJZSQVHLCKE’[nif_addition,1] == nif_letter

 # CIF validation algorithm taken from:
 # http://club.telepolis.com/jagar1/Ccif.htm
 return false unless "ABCDEFGHNPQS".include? candidate[0,1]
 central_digits = str_to_int_array(candidate[1,7])

 a = [1,3,5].inject(0) { |acum, pos| central_digits[pos] + acum }
 b = [0,2,4,6].inject(0) { |acum, pos| acum +

add_digits_from_int(central_digits[pos] * 2) }

 candidate_digit = 10 - ( (a+b) % 10)
 candidate_letter = "JABCDEFGHI"[candidate_digit,1]

 control_digit = candidate[8,1]
 control_digit == candidate_digit.to_s || control_digit ==

candidate_letter
end

Como no sé si se verá bien, también la dejo
aquí: http://pastie.caboo.se/32677

DISCLAIMER:

La he terminado hace un rato y tengo un hambre que no veo, así que
aún no la he sometido a demasiadas pruebas y seguramente el código apesta:
sugerencias, críticas, bugs y demás feedback será siempre bienvenido.
Eso sí, después de la cena :slight_smile:

Saludos,
Raul


#3

Wooops, con las prisas olvidé indicar que en la llamada a la función de
validación aplico un

candidate_cif.upcase!.gsub!(/\W/,’’)

sobre el CIF a validar, para formatearlo eliminando los caracteres no
alfanuméricos y pasar la/s letra/s a mayúsculas. De esta forma el dato
puede venir en un formato libre (hay gente que separa la letra y los
dígitos con guiones, con espacios…).

Saludos,
Raul


#4

On 1/12/07, Raul M. removed_email_address@domain.invalid wrote:

Wooops, con las prisas olvidé indicar que en la llamada a la función de
validación aplico un

    candidate_cif.upcase!.gsub!(/\W/,'')

Muchas gracias Raúl, me viene de perlas tanto el algoritmo como el
snippet este para limpiarlo :slight_smile:


David A., el único desarrollador con una orden de alejamiento de
Jeffrey Zeldman
Simplelogica.net, ahora con un 33,3% más de intromisión en listas de correo

Cuando no hago otra cosa escribo en mildiez.net


#5

Corrigiéndome en voz alta, este código es erróneo:

Wooops, con las prisas olvidé indicar que en la llamada a la función de
validación aplico un

candidate_cif.upcase!.gsub!(/\W/,’’)

En contra de lo que yo creía, resulta que upcase! devuelve nil si no ha
realizado ningún cambio, lo que en mi instrucción provoca un error de
ejecución cuando la cadena ya está en mayúsculas.

gsub! se comporta igual: si no hay cambios devuelve nil.


#6

Los metodos ! no son generalmente apropiados para encadenar. Como no
deben retornar un nuevo valor, algunos retornan informacion sobre la
operacion en si misma. Otros retornan self, por lo que si son
encadenables, pero debes leer con detalle la documentacion