Skip to content

Instantly share code, notes, and snippets.

@AldoMX
Last active September 13, 2024 14:48
Show Gist options
  • Save AldoMX/d819189f68626db9088c to your computer and use it in GitHub Desktop.
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)
/**
* 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;
}
})();
/**
* 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