Last active
September 13, 2024 14:48
-
-
Save AldoMX/d819189f68626db9088c to your computer and use it in GitHub Desktop.
Implementación en JavaScript del algoritmo para generar el RFC para personas físicas (IFAI 0610100135506)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* PersonaFisica.js | |
* | |
* Implementación en JavaScript del algoritmo para generar el RFC para personas | |
* físicas (IFAI 0610100135506) | |
* | |
* Copyright 2015 Aldo Fregoso. | |
* | |
* El uso de este archivo está permitido bajo los términos de la licencia de | |
* código abierto "GNU Affero General Public License" (AGPL) disponible en: | |
* http://www.gnu.org/licenses/agpl.txt | |
* | |
* En caso de requerir su uso bajo términos diferentes, favor de contactar al | |
* autor en la siguiente dirección de correo electrónico: | |
* aldomx [arroba] gmail [punto] com | |
*/ | |
var PersonaFisica = (function () { | |
var MAPA_NOMBRES_REMOVER = [ | |
'DE', 'DEL', 'LA', 'LAS', 'LOS', 'MAC', 'MC', 'MI', 'VAN', 'VON', 'Y' | |
]; | |
var MAPA_REEMPLAZOS = { | |
'Á': 'A', 'É': 'E', 'Í': 'I', 'Ó': 'O', 'Ú': 'U', 'Ü': 'U', 'á': 'A', | |
'é': 'E', 'í': 'I', 'ó': 'O', 'ú': 'U', 'ü': 'U', 'ñ': 'Ñ', | |
'´': 'APOSTROFE', '\'': 'APOSTROFE', '.': 'PUNTO' | |
}; | |
function limpiarNombre(nombre) { | |
var nombres = []; | |
nombre = nombre.replace(/\s+/g, ' '); | |
nombre = nombre.trim(); | |
nombre = nombre.replace(/[^A-Za-zÑ& ]/g, function (caracter) { | |
return MAPA_REEMPLAZOS[caracter] || ''; | |
}); | |
nombre = nombre.toUpperCase(); | |
if (nombre === '') { | |
return nombre; | |
} | |
nombre.split(' ').forEach(function (nombre) { | |
var nombreSinPuntos = nombre.replace('/PUNTO$/', ''); | |
if (MAPA_NOMBRES_REMOVER.indexOf(nombreSinPuntos) === -1) { | |
nombres.push(nombre); | |
} | |
}); | |
return nombres.join(' '); | |
} | |
return function (datos) { | |
this.paterno = limpiarNombre(datos.paterno || ''); | |
this.materno = limpiarNombre(datos.materno || ''); | |
if (this.paterno === '' && this.materno === '') { | |
throw 'Se require por lo menos un apellido, solo se permiten letras de la A a la Z (incluyendo Ñ).'; | |
} | |
this.nombre = limpiarNombre(datos.nombre || ''); | |
if (this.nombre === '') { | |
throw 'Se require por lo menos un nombre, solo se permiten letras de la A a la Z (incluyendo Ñ).'; | |
} | |
this.fechaNacimiento = datos.fechaNacimiento; | |
if (Object.prototype.toString.call(this.fechaNacimiento) !== '[object Date]') { | |
throw 'fechaNacimiento no es un objeto de tipo "Date"'; | |
} | |
} | |
}()); | |
PersonaFisica.prototype.calcularRFC = (function () { | |
var MAPA_NOMBRES_COMUNES_REMOVER = [ | |
'JOSE', 'MARIA' | |
]; | |
function limpiarNombresComunes(nombre) { | |
var nombres = []; | |
nombre.split(' ').forEach(function (nombre) { | |
if (MAPA_NOMBRES_COMUNES_REMOVER.indexOf(nombre) === -1) { | |
nombres.push(nombre); | |
} | |
}); | |
if (nombres.length > 0) { | |
return nombres.join(' '); | |
} | |
return nombre; | |
} | |
var MAPA_REEMPLAZOS_EXPRESION_ALFABETICA = { | |
'BUEI': 'BUEX', 'KOGE': 'KOGX', 'BUEY': 'BUEX', 'KOJO': 'KOJX', | |
'CACA': 'CACX', 'KAKA': 'KAKX', 'CACO': 'CACX', 'KULO': 'KULX', | |
'CAGA': 'CAGX', 'MAME': 'MAMX', 'CAGO': 'CAGX', 'MAMO': 'MAMX', | |
'CAKA': 'CAKX', 'MEAR': 'MEAX', 'COGE': 'COGX', 'MEON': 'MEOX', | |
'COJA': 'COJX', 'MION': 'MIOX', 'COJE': 'COJX', 'MOCO': 'MOCX', | |
'COJI': 'COJX', 'MULA': 'MULX', 'COJO': 'COJX', 'PEDA': 'PEDX', | |
'CULO': 'CULX', 'PEDO': 'PEDX', 'FETO': 'FETX', 'PENE': 'PENX', | |
'GUEY': 'GUEX', 'PUTA': 'PUTX', 'JOTO': 'JOTX', 'PUTO': 'PUTX', | |
'KACA': 'KACX', 'QULO': 'QULX', 'KACO': 'KACX', 'RATA': 'RATX', | |
'KAGA': 'KAGX', 'RUIN': 'RUIX', 'KAGO': 'KAGX' | |
}; | |
function calcularExpresionAlfabetica(paterno, materno, nombre) { | |
var expresion = (function (paterno, materno, nombre) { | |
var i, indiceVocal; | |
// Caso especial 1: Un solo apellido | |
if (paterno === '' || materno === '') { | |
if (paterno === '') { | |
paterno = materno; | |
materno = ''; | |
} | |
return [ | |
paterno[0], | |
paterno[1] || 'X', | |
nombre[0], | |
nombre[1] || 'X' | |
].join(''); | |
} | |
// Caso especial 2: Apellido paterno con 2 o menos letras | |
if (paterno.length <= 2) { | |
return [ | |
paterno[0], | |
materno[0], | |
nombre[0], | |
nombre[1] || 'X' | |
].join(''); | |
} | |
// Caso normal | |
indiceVocal = 1; | |
for (i = 1; i < paterno.length; i++) { | |
if (['A', 'E', 'I', 'O', 'U'].indexOf(paterno[i]) !== -1) { | |
indiceVocal = i; | |
break; | |
} | |
} | |
return [ | |
paterno[0], | |
paterno[indiceVocal] || 'X', | |
materno[0], | |
nombre[0] | |
].join(''); | |
})(paterno, materno, limpiarNombresComunes(nombre)); | |
return MAPA_REEMPLAZOS_EXPRESION_ALFABETICA[expresion] || expresion; | |
} | |
function calcularExpresionNumerica(fechaNacimiento) { | |
return fechaNacimiento.toISOString().substr(2, 8).replace(/-/g, ''); | |
} | |
var MAPA_VALORES_PARA_CALCULO_CLAVE_DIFERENCIADORA = { | |
' ': '00', '0': '00', '1': '01', '2': '02', '3': '03', '4': '04', | |
'5': '05', '6': '06', '7': '07', '8': '08', '9': '09', '&': '10', | |
'A': '11', 'B': '12', 'C': '13', 'D': '14', 'E': '15', 'F': '16', | |
'G': '17', 'H': '18', 'I': '19', 'J': '21', 'K': '22', 'L': '23', | |
'M': '24', 'N': '25', 'O': '26', 'P': '27', 'Q': '28', 'R': '29', | |
'S': '32', 'T': '33', 'U': '34', 'V': '35', 'W': '36', 'X': '37', | |
'Y': '38', 'Z': '39', 'Ñ': '40' | |
}; | |
var MAPA_VALORES_CLAVE_DIFERENCIADORA = [ | |
'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', | |
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', | |
'U', 'V', 'W', 'X', 'Y', 'Z' | |
]; | |
function calcularClaveDiferenciadora(paterno, materno, nombre) { | |
var nombreCompleto = [paterno, materno, nombre].join(' '), | |
valores = ['0']; | |
Array.prototype.forEach.call(nombreCompleto, function (letra) { | |
valores.push(MAPA_VALORES_PARA_CALCULO_CLAVE_DIFERENCIADORA[letra] || ''); | |
}); | |
valores = valores.join(''); | |
var sumaValores = 0; | |
for (var i = 1; i < valores.length; i++) { | |
sumaValores += parseInt(valores.substr(i - 1, 2), 10) * parseInt(valores[i], 10); | |
} | |
sumaValores %= 1000; | |
var cociente = Math.floor(sumaValores / 34), | |
residuo = sumaValores % 34; | |
return [ | |
MAPA_VALORES_CLAVE_DIFERENCIADORA[cociente] || 'X', | |
MAPA_VALORES_CLAVE_DIFERENCIADORA[residuo] || 'X' | |
].join(''); | |
} | |
var MAPA_VALORES_DIGITO_VERIFICADOR = [ | |
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', | |
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', '&', 'O', 'P', 'Q', | |
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'Ñ' | |
]; | |
function calcularDigitoVerificador(rfc) { | |
var multiplicador = rfc.length + 1, | |
sumaValores = 0; | |
Array.prototype.forEach.call(rfc, function (letra) { | |
var indiceLetra = MAPA_VALORES_DIGITO_VERIFICADOR.indexOf(letra); | |
if (indiceLetra == -1) { | |
indiceLetra = 0; | |
} | |
sumaValores += indiceLetra * multiplicador--; | |
}); | |
var digitoVerificador = 11 - (sumaValores % 11); | |
switch (digitoVerificador) { | |
case 11: | |
return 0; | |
case 10: | |
return 'A'; | |
default: | |
return digitoVerificador; | |
} | |
} | |
return function () { | |
var rfc = [ | |
calcularExpresionAlfabetica(this.paterno, this.materno, this.nombre), | |
calcularExpresionNumerica(this.fechaNacimiento), | |
calcularClaveDiferenciadora(this.paterno, this.materno, this.nombre) | |
].join(''); | |
rfc += calcularDigitoVerificador(rfc); | |
return rfc; | |
} | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Ejemplo de uso | |
*/ | |
var aldo = new PersonaFisica({ | |
paterno: 'Fregoso', | |
materno: '', | |
nombre: 'Aldo', | |
fechaNacimiento: new Date('1987-04-12') | |
}); | |
console.log( aldo.calcularRFC() ); // Imprime: "FRAL870412147" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment