Validación del módulo 11 (RUT y Patente en Chile)
Hace bastante tiempo que no escribo una entrada en el blog, llegó la hora de revivirlo 🙂
El módulo 11 es un código de control usado para la validación de un dato al añadir un dígito verificador, en chile es usado para validar el RUN (Rol Único Nacional), RUT (Rol Único Tributario) y la Patente de los vehículos (no sé si se utilizará para otras cosas).
Esta entrada está enfocada en la validación del módulo 11 y la aplicación en C# para validar un RUN/RUT y una Patente chilena.
El módulo 11: El método denominado módulo 11 detecta errores en un solo dígito e intercambios simples o dobles. Se basa en aplicar un factor de chequeo ponderado a cada dígito del número original.
El Registro Civil (chile) ofrece manuales para validar correctamente el RUT/RUN y la patente.
Para validar el módulo 11 tenemos el siguiente código (gentileza de Germán Aroca):
public class Mod11Validator { public int Numero { get; set; } public string DigitoVerificador { get; set; } public Mod11Validator(int numero, string digitoVerificador) { this.Numero = numero; this.DigitoVerificador = digitoVerificador.ToUpper(); } public bool ObtenerValidezMod11() { return this.DigitoVerificador == CalcularDigitoVerificador(this.Numero); } private string CalcularDigitoVerificador(int numero) { string cadenaNumero = numero.ToString(); int calculador = 0; int[] factores = {3, 2, 7, 6, 5, 4, 3, 2}; int indiceFactor = factores.Length - 1; for (int i = cadenaNumero.Length - 1; i >= 0; i--) { calculador = calculador + (factores[indiceFactor]*int.Parse(cadenaNumero.Substring(i, 1))); indiceFactor--; } string digitoVerificador; int resultado = 11 - (calculador%11); if (resultado == 11) { digitoVerificador = "0"; } else if (resultado == 10) { digitoVerificador = "K"; } else { digitoVerificador = resultado.ToString(); } return digitoVerificador; } }
Para validar el RUT/RUN por lo tanto solo debemos llamar a este método de la siguiente forma
Mod11Validator mod11 = new Mod11Validator(numero, dv); bool esValido = mod11.ObtenerValidezMod11();
Para la validación de patente es un tema distinto, dado que la validación de la patente lleva letras, estas deben ser convertidas en dígitos de acuerdo al manual del registro civil. Entiendo que traspasar todas estas letras a dígitos es realmente aburrido y tedioso, les dejo adjunto 2 archivos CSV con las conversiones de patentes nuevas y antiguas Cortesía de Carlos Muñoz.
- Patentes Antiguas: Descargar CSV
- Patentes Nuevas: Descargar CSV
Para utilizar estos archivos correctamente con la clase que embedo a continuación, solo deben añadir los archivos a un archivo de recursos y luego mapearlos (ver líneas destacadas en el código). Por cierto, para leer los archivos utilizo el siguiente código: Leer CSV (archivo separado por coma)
public class PatenteValidator { public class PatenteAntigua { public static Dictionary<string, string> ValorLetras { get { DataTable dt = Utils.Common.Files.FileTools.ByteBufferToTable(ValidatorResources.Resources.DiccionarioPatentesAntiguas, true); Dictionary<string, string> d = new Dictionary<string, string>(); foreach (DataRow dr in dt.Rows) d[dr[0].ToString()] = dr[1].ToString(); return d; } } } public class PatenteNueva { public static Dictionary<string, string> ValorLetras { get { DataTable dt = Utils.Common.Files.FileTools.ByteBufferToTable(ValidatorResources.Resources.DiccionarioPatentesNuevas, true); Dictionary<string, string> d = new Dictionary<string, string>(); foreach (DataRow dr in dt.Rows) d[dr[0].ToString()] = dr[1].ToString(); return d; } } } public static bool ValidarPatente(string patente) { if (patente.Trim().Length != 8) return false; if (!patente.Trim().Contains("-")) return false; int aux; bool esPatenteAntigua = int.TryParse(patente.Substring(2,2), out aux); int numero; string dv; if(esPatenteAntigua) { Dictionary<string, string> valorLetras = PatenteAntigua.ValorLetras; string letras = patente.Substring(0, 2); if (!valorLetras.ContainsKey(letras.ToUpper())) return false; string valor = valorLetras[letras.ToUpper()]; valor += patente.Substring(2, 4); dv = patente.Substring(7, 1); numero = int.Parse(valor); } else { Dictionary<string, string> valorLetras = PatenteNueva.ValorLetras; char[] letras = patente.Substring(0, 4).ToCharArray(); string valor = string.Empty; foreach (char c in letras) { if (!valorLetras.ContainsKey(c.ToString().ToUpper())) return false; valor += valorLetras[c.ToString().ToUpper()]; } valor += patente.Substring(4, 2); dv = patente.Substring(7, 1); numero = int.Parse(valor); } Mod11Validator mod11Validator = new Mod11Validator(numero, dv); return mod11Validator.ObtenerValidezMod11(); } }
El validado de patente no funciona
Podrías ser un poco más específico en el error? Yo lo tengo implementado y funciona.
El dígito verificador que devuelve no corresponde con el ultimo dígito de la patente en todas las patentes que e ingresado.
¿estás seguro? yo lo tengo implementado y funciona perfecto, considera que recibe patentes AA0000-1 y AAAA00-1. Lo que calcula es el digito verificador según lo establecido por el registro civil.
no entiendo la function de leer el cvs. la function recibe buffer As Byte() pero los cvs son string…..
Entiendo perfectamente lo que dices, ten en cuenta que toda representación de datos es un arreglo de bytes, en el caso de un CSV, ese arreglo de Bytes es texto simple, por lo cual no es necesario interpretar el arreglo como string, sino que lo es por defecto.
Si lo que deseas es una función «StringToDataTable» que interprete un string en formato CSV, yo utilizo la siguiente: https://gist.github.com/Gabriel-Espinoza/1c86fec6e757fad3834e
Avísame si te sirve 🙂
algo estoy haciendo mal entonces. yo agrego los archivos «csv» al resource pero luego al invocarlos me lanza un error: Dim dt As DataTable = ByteBufferToTable(My.Resources.DiccionarioPatentesAntiguas, True)
Un valor de tipo ‘String’ no se puede convertir en ‘1-matriz dimensional de Byte’.
No había reparado en que estás usando VB.NET, de ser así, te recomiendo utilizar la función que te dejé linqueada en la respuesta anterior, ahí interpretas el CSV y lo lees. Prueba y me cuentas como te fue.
Saludos
Gracias! ocupé las clases que tienes en GitHub… exelente!
Me alegro que funcionara 🙂
validar patente pero en vba. tu serias tan amable de colocarlo
hola luis, lamentablemente nunca he trabajado con VBA, pero debe haber un traductor de c# a vba por ahí. Algo así quizás http://converter.telerik.com/
gracias.
Podrias enviar tu codigo a este sitio que tiene muchas funciones.
El de rut y patente
http://users.dcc.uchile.cl/~mortega/microcodigos/validarrut/
Gracias por la sugerencia Erik, envié un mail a ver si lo agregan.
Saludos
estimado me podrías mandar el código de la validación de Rut a este correo marcelo.mora.jara@gmail.com gracias
Como ocupo Utils?, me dice que no existe y no se como implementarla en mi codigo. Agregue Utils a referencias pero no me lo reconoce
Hola Daniel!
Utils es el nombre de una librería personal, lo que necesitas realmente es el método ByteBufferToTable el cual lee un archivo CSV y lo interpreta como DataTable. Este método lo puedes encontrar en https://tipsdelgabo.wordpress.com/2013/08/20/leer-csv-archivo-separado-por-coma-como-datatable-y-viceversa/
Espero esto responda tu pregunta.
Saludos
Muy bien explicado, pero los enlaces a los csv, están rotos .
Gracias por avisarme! Ahora que Dropbox eliminó la carpeta pública he tenido que hacer público el archivo. Ya está solucionado! 😉
Muchas gracias 🤘