Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 11-08-2011
Gallosuarez Gallosuarez is offline
Miembro
 
Registrado: feb 2007
Posts: 92
Poder: 20
Gallosuarez Va por buen camino
Talking Ofrecimiento ...

Amerika111:

Ofrezco mi humilde ayuda para codificar dicho procedimiento almacenado, siempre y cuando me hagas llegar el proceso por escrito (lo mas explicito que se pueda, así como también algunos casos típicos para ver que todo funciona correctamente), no quiero estar viendo el código en otros lenguajes y hacer suposiciones que no siempre resultan ciertas, ¿me explico?. Espero tu respuesta.

Saludos,
Gerardo Suárez Trejo
Responder Con Cita
  #2  
Antiguo 11-08-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Gallosuarez Ver Mensaje
siempre y cuando me hagas llegar el proceso por escrito (lo mas explicito que se pueda, así como también algunos casos típicos para ver que todo funciona correctamente)
¡Uf! El proceso es algo líoso. No sé si Amerika111 ya te lo hizo llegar, pero mientras tanto voy a intentar describirlo aquí.

El RFC es un identificador alfanumérico que se asigna en México a cada persona y se basa en los apellidos, nombre y fecha de nacimiento. Para fijar ideas, vamos a tomar esta persona ficticia:

Apellido paterno: Del Real
Apellido Materno: Anzures
Nombre: José Antonio
Fecha de nacimiento: 14 de abril de 1972

Su RFC será:

Código:
REAA 720414 N9 4
Las primeras cuatro letras se forman a partir de apellidos y nombre, sigue la fecha de nacimiento en formato aammdd, luego dos caracteres de homonimia y termina con un dígito verificador.

Veamos por partes, como se calcula cada una:

Letras

Esta parte se forma con:
  • Primera letra del apellido paterno
  • Primera vocal interna del apellido paterno
  • Primera letra del apellido materno
  • Primera letra del nombre

Ahora bien, deben tomarse en cuenta estas excepciones:
  1. En nombres compuestos se toma la primera palabra siempre y cuando no sea JOSE o MARIA (en el ejemplo se omitió JOSE y se toma ANTONIO)
  2. Se omiten artículos, preposiciones, conjunciones y contracciones de apellidos y nombres. La lista oficial es:

    Código:
    DE, LA, LAS, MC, VON, DEL, LOS, Y, MAC, VAN, MI
    (en el ejemplo se omitió DEL)
  3. Si el apellido paterno consta de una o dos letras (por ejemplo: DE LA O, una vez que se omiten los artículos), se toman la primera letra del apellido paterno, la primera del apellido materno y las dos primeras del nombre.
  4. Si sólo hay un apellido se toman las dos primeras letras del apellido y las dos primeras del nombre)
  5. Si las cuatro letras resultantes coinciden con una palabra "fea", debe sustituirse la última letra por una X. La lista oficial de palabras "feas" es:

    Código:
    BUEI, BUEY, CACA, CACO, CAGA, CAGO, CAKA, CAKO, COGE, COJA, COJE, COJI, COJO, 
    CULO, FETO, GUEY, JOTO, KACA, KACO, KAGA, KAGO, KAKA, KOGE, KOJO, KULO, MAME, 
    MAMO, MEAR, MEAS, MEON, MION, MOCO, MULA, PEDA, PEDO, PENE, PUTA, PUTO, QULO, 
    RUIN, RATA,

Aquí hay que notar, que estas reglas no son absolutas ni completas (pero son las oficiales). Por ejemplo, no indican qué hacer en caso de que el apellido paterno no contenga vocales internas, como ALBY, BYRD, ORMSBY.

En alguna ocasión tuve la oportunidad de analizar los RFC de una base de datos relativamente amplia y observé que la excepción 4 en realidad es así:

Primera letra y primera vocal interna del apellido y primera y segunda letra del nombre.

En resumen, parece que en los casos de excepción, muchas veces depende del criterio del funcionario en turno que asigne el RFC oficial.

Fecha

En formato de seis diígitos: aammdd

Homonimia
  1. Se toma el nombre completo de la persona, comenzando por los apellidos:

    Código:
    DEL REAL ANZURES JOSE ANTONIO
    En este caso se toma todo el nombre incluyendo lo que se omite en el cálculo de las letras.

  2. A cada letra se le asocia un valor numérico de acuerdo a la siguiente tabla:

    Código:
    esp	00	|	I	19
    0	00	|	J	21
    1	01	|	K	22
    2	02	|	L	23
    3	03	|	M	24
    4	04	|	N	25
    5	05	|	O	26
    6	06	|	P	27
    7	07	|	Q	28
    8	08	|	R	29
    9	09	|	S	32
    &	10	|	T	33
    A	11	|	U	34
    B	12	|	V	35
    C	13	|	W	36
    D	14	|	X	37
    E	15	|	Y	38
    F	16	|	Z	39
    G	17	|	Ñ	40
    H	18	|
    Hay que observar que los valores no son consecutivos (hay un salto después de la I y despúés de la R). Cada valor debe incluir el cero inicial y al principio de toda la cadena de números se añade un cero solitario. En el ejemplo quedaría así:

    Código:
    	D	E	L		R	E	A	L		A	N	Z	U	R	E	S		J	O	S	E		A	N	T	O	N	I	O
    0	14	15	23	00	29	15	11	23	00	11	25	39	34	29	15	32	00	21	26	32	15	00	11	25	33	26	25	19	26
    quedando la siguiente cadena de dígitos:

    Código:
    01415230029151123001125393429153200212632150011253326251926
  3. Esta cadena se recorre de izquierda a derecha desde el primero hasta el penúltimo caracter. En la iteración i-ésima se multiplican los dígitos i e i+1.

    Se suman todos los productos. En el ejemplo queda: 4756

  4. De este número se toman los tres últimos (el residuo al dividir por 1000), en este caso: 756

  5. Se toman el cociente y el residuo de este número al dividirse por 34:

    Cociente: 22
    Residuo: 8

  6. Se buscan los caracteres correspondientes en la siguiente tabla:

    Código:
    0	1	|	17	I
    1	2	|	18	J
    2	3	|	19	K
    3	4	|	20	L
    4	5	|	21	M
    5	6	|	22	N
    6	7	|	23	P
    7	8	|	24	Q
    8	9	|	25	R
    9	A	|	26	S
    10	B	|	27	T
    11	C	|	28	U
    12	D	|	29	V
    13	E	|	30	W
    14	F	|	31	X
    15	G	|	32	Y
    16	H	|	33	Z
    Obsérvese que no hay letra O. Al cociente (22) le corresponde N y al residuo (8) le corresponde 9.

  7. Estos dos caracteres forman la homonimia: N9

Dígito verificador
  • A cada caracter del RFC ya formado (cuatro letras, fecha y homonimia; 12 en total) se le asigna un valor numérico según la tabla:

    Código:
    0	0	|	K	20
    1	1	|	L	21
    2	2	|	M	22
    3	3	|	N	23
    4	4	|	&	24
    5	5	|	O	25
    6	6	|	P	26
    7	7	|	Q	27
    8	8	|	R	28
    9	9	|	S	29
    A	10	|	T	30
    B	11	|	U	31
    C	12	|	V	32
    D	13	|	W	33
    E	14	|	X	34
    F	15	|	Y	35
    G	16	|	Z	36
    H	17	|	ESP	37
    I	18	|	Ñ	38
    J	19	|
    Nótese que hay un espacio y un ampersand intercalados y que la Ñ está fuera de orden.

  • Cada valor se multiplica por la posición del caracter correspondiente en el RFC contada de derecha a izquierda empezando por 2:

    Código:
      R	E	A	A	7	2	0	4	1	4	N	9
      28	14	10	10	7	2	0	4	1	4	23	9
    x 13	12	11	10	9	8	7	6	5	4	3	2
    ------------------------------------------------------------------------------------------
     364	168	110	100	63	16	0	24	5	16	69	18
  • Se toma la suma de estos productos: Suma=953

  • De esta suma, se toma el residuo al dividirse por 11 y luego su complemento:

    DV = 11 - (Suma mod 11) (este número siempre está en el rango 1..11)

    Este es el dígito verificador, a menos que sea 11, en cuyo caso se toma 0 (cero).

    En el ejemplo, DV = 11 - (953 mod 11) = 11 - 7 = 4.

Algunas observaciones

Como dije antes, el algoritmo en la parte de las letras es confuso. Al implementar hay que decidir qué hacer en los casos especiales (por ejemplo, poner una X en caso de no haber vocal interna del apellido paterno).

Por otra parte, todas las letras de los nombres deben considerarse sin acentos de ningún tipo.

Este algoritmo es únicamente para personas físicas (seres humanos) y no para personas morales (empresas).

Desconozco si hay un documento oficial de Hacienda que describa el algoritmo, pero existe un documento oficial (en el cual yo me basé) en el IFAI (Instituto Federal de Acceso a la Información).

Este documento pueden localizarlo entrando al sitio de INFOMEX buscando el folio: 0610100135506, que corresponde a la solicitud que alguien hizo para obtener esta información. Ahí pueden ver el documento de respuesta. Este documento también describe el algoritmo del RFC para personas morales.

// Saludos

Última edición por roman fecha: 12-08-2011 a las 06:25:23.
Responder Con Cita
  #3  
Antiguo 11-08-2011
Gallosuarez Gallosuarez is offline
Miembro
 
Registrado: feb 2007
Posts: 92
Poder: 20
Gallosuarez Va por buen camino
Talking Rfc ...

Román:

Excelente, es justamente lo que necesitaba... de hecho ya empece .... creo que ya llevo la primera parte ... tuve que parar un rato (hay que ganarse el pan de cada día, je, je, je).

Saludos,
Gerardo Suárez Trejo

P.D. Estoy indeciso en liberar la primera parte (de esta forma es más fácil hacer la depuración). ¿Hay alguien que se apunte para hacer las pruebas?
Responder Con Cita
  #4  
Antiguo 11-08-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Todavía no tengo mucho tiempo para lo del dígito verificador pero aprovecho para comentar que en esta página http://www.aplicarh.com/ pueden descargar una aplicación que calcula el RFC. Con esto pueden probar qué tal funciona su algoritmo.

// Saludos
Responder Con Cita
  #5  
Antiguo 12-08-2011
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
¡Listo! Ya completé la parte del dígito verificador y puse algunas observaciones finales.

// Saludos
Responder Con Cita
  #6  
Antiguo 12-08-2011
Gallosuarez Gallosuarez is offline
Miembro
 
Registrado: feb 2007
Posts: 92
Poder: 20
Gallosuarez Va por buen camino
Thumbs up Pendientes ...

Román:

Gracias ... bueno pues lo que sigue solo es cuestión mía ... espero que hoy por la tarde tener un versión lista ... saludos al foro ...

Atte:
Gerardo Suárez Trejo
Responder Con Cita
  #7  
Antiguo 13-08-2011
Gallosuarez Gallosuarez is offline
Miembro
 
Registrado: feb 2007
Posts: 92
Poder: 20
Gallosuarez Va por buen camino
Red face Primer intento ...

America111:

Bueno pues aquí tenemos el primer esbozo . Se debe de considerar como eso, es decir, una versión de prueba que no está lista para entrar a producción. Falta muchas protecciones, además de agregarle el código para la homoclave y el dígito verificador.

Lo programé en la versión 2.5, sin embargo creo que funcionaría desde la 2.1 (falta confirmar). Utilicé dominios en la declaración de variables (enorme ventaja de conservar consistencia en el tipo de datos entre tablas y procedimientos almacenados). No utilicé ningún UDF (ventaja que se traduce al utilizar diferentes plataformas: Linux, Mac, UNIX, Windows, etc). Planeo, para después, agregar una tabla de Personal donde utilizaré los dominios antes mencionados, además de un campo calculado para el nombre completo que estaría indexado para hacer búsquedas rapidísimas que no sean sensibles a mayúscula o a los acentos (tal y como sucede en el cálculo del RFC).
Se usa de la siguiente manera:
Código SQL [-]
SELECT RFC
FROM CALC_RFC('Del Real', 'Anzures', 'José Antonio', '04/14/1972')

ó

SELECT RFC
FROM CALC_RFC('DEL REAL', 'ANZURES', 'JOSÉ ANTONIO', '04/14/1972')

etc, etc

Código:
Código SQL [-]
/******************** DOMINIOS *********************/
CREATE DOMAIN DOM_AMATERNO
 AS Varchar(27)
 COLLATE ES_ES_CI_AI;
CREATE DOMAIN DOM_APATERNO
 AS Varchar(27)
 COLLATE ES_ES_CI_AI;
CREATE DOMAIN DOM_NOMBRECMPLTO
 AS Varchar(93)
 COLLATE ES_ES_CI_AI;
CREATE DOMAIN DOM_NOMBRES
 AS Varchar(37)
 COLLATE ES_ES_CI_AI;
CREATE DOMAIN DOM_RFC
 AS Varchar(13)
 COLLATE ES_ES_CI_AI;

/********** PROCEDIMIENTO VOCAL_MAYUSCULA ***********/
SET TERM ^ ;
CREATE PROCEDURE VOCAL_MAYUSCULA (
    C Char(1) COLLATE ES_ES_CI_AI)
RETURNS (
    VOCAL Char(1) )
AS
BEGIN
  VOCAL = C;
  IF (C IN ('Á')) THEN VOCAL = 'A';
  IF (C IN ('É')) THEN VOCAL = 'E';
  IF (C IN ('Í')) THEN VOCAL = 'I';
  IF (C IN ('Ó')) THEN VOCAL = 'O';
  IF (C IN ('Ú')) THEN VOCAL = 'U';
END^
SET TERM ; ^

/********** PROCEDIMIENTO CALC_RFC ***********/
SET TERM ^ ;
CREATE PROCEDURE CALC_RFC (
    APATERNO_PARAM DOM_APATERNO,
    AMATERNO_PARAM DOM_AMATERNO,
    NOMBRES_PARAM DOM_NOMBRES,
    F_NACIMIENTO Date )
RETURNS (
    RFC DOM_RFC )
AS
DECLARE dd CHAR(2); /* día de nacimiento */
DECLARE mm CHAR(2); /* mes de nacimiento */
DECLARE aa CHAR(2); /* año de nacimiento */
DECLARE APaterno DOM_APATERNO = '';
DECLARE AMaterno DOM_APATERNO = '';
DECLARE Nombres DOM_NOMBRES = '';
DECLARE Nombre1 DOM_NOMBRES = '';
DECLARE APaterno1 DOM_APATERNO = '';
DECLARE NombreCmplto DOM_NOMBRECMPLTO = '';
DECLARE PosEspacio INTEGER = 0; 
DECLARE PrimeraVocal CHAR(1) = ''; /* primera vocal interna */
DECLARE Cadena VARCHAR(24) = '';
DECLARE i INTEGER = 1;
DECLARE LongCadena INTEGER = 0; /* longitud de cadena */
BEGIN
  dd = LPAD(CAST(EXTRACT(DAY FROM F_NACIMIENTO) AS VARCHAR(2)), 2, '0');
  mm = LPAD(CAST(EXTRACT(MONTH FROM F_NACIMIENTO) AS VARCHAR(2)), 2, '0');
  aa = RIGHT(CAST(EXTRACT(YEAR FROM F_NACIMIENTO) AS VARCHAR(4)), 2);
  
  APaterno = TRIM(APATERNO_PARAM);
  AMaterno = TRIM(AMATERNO_PARAM);
  Nombres = TRIM(NOMBRES_PARAM);
  
  /* Bucle para procesar nombre(s) */
  WHILE (1 = 1) DO
  BEGIN
    PosEspacio = IIF(POSITION(' ', Nombres) = 0, 1, POSITION(' ', Nombres));
    Nombre1 = SUBSTRING(Nombres FROM 1 FOR PosEspacio - 1);
    IF (Nombre1 NOT IN ('JOSE','MARIA','MA.','MA','DE','LA','LAS','MC','VON','DEL','LOS','Y','MAC','VAN')
      OR (PosEspacio - 1) = 0) THEN LEAVE;
    Nombres = SUBSTRING(Nombres FROM PosEspacio + 1);
  END
  
  /* Bucle para procesar apellido(s) paterno */
  WHILE (1 = 1) DO
  BEGIN
    PosEspacio = IIF(POSITION(' ', APaterno) = 0, 1, POSITION(' ', APaterno));
    APaterno1 = SUBSTRING(APaterno FROM 1 FOR PosEspacio - 1);
    IF (APaterno1 NOT IN ('DE','LA','LAS','MC','VON','DEL','LOS','Y','MAC','VAN')
      OR (PosEspacio - 1) = 0) THEN LEAVE;
    APaterno = SUBSTRING(APaterno FROM PosEspacio + 1);
  END
    
  /* Bucle para buscar primera vocal interna en el apellido paterno */
  Cadena = SUBSTRING(APaterno FROM 2);
  LongCadena = CHAR_LENGTH(Cadena);
  i = 1;
  WHILE (i < LongCadena) DO
  BEGIN
    EXECUTE PROCEDURE VOCAL_MAYUSCULA(SUBSTRING(Cadena FROM 1 FOR 1))
    RETURNING_VALUES PrimeraVocal;
    IF (PrimeraVocal IN ('A', 'E', 'I', 'O', 'U')) THEN LEAVE;
    Cadena = SUBSTRING(Cadena FROM 2);
    i = i + 1;
  END
  
  /* Concatena todo los resultados */
  RFC = UPPER(LEFT(APaterno, 1) || PrimeraVocal || COALESCE(LEFT(AMaterno, 1), 'X') ||
    LEFT(Nombres, 1));
  
  /* Elimina palabras "feas" */
  IF (RFC IN ('BUEI','BUEY','CACA','CACO','CAGA','CAGO','CAKA','CAKO','COGE','COJA',
    'COJE','COJI','COJO','CULO','FETO','GUEY','JOTO','KACA','KACO','KAGA',
    'KAGO','KAKA','KOGE','KOJO','KULO','MAME','MAMO','MEAR','MEAS','MEON',
    'MION','MOCO','MULA','PEDA','PEDO','PENE','PUTA','PUTO','QULO','RUIN','RATA')) THEN
    RFC = SUBSTRING(RFC FROM 1 FOR 3) || 'X';
      
  /* Concatena fecha de nacimiento */  
  RFC = RFC || aa || mm || dd;
  SUSPEND;
END^
SET TERM ; ^

Saludos,
Gerardo Suárez Trejo
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
condicionar un procedimiento dentro de otro procedimiento yossi Varios 7 17-05-2010 10:47:14
Ayuda, como llamar a un procedimiento desde otro procedimiento? Ariatna Varios 1 01-02-2005 04:05:35
error calculo en udf marrullas Firebird e Interbase 0 02-11-2004 21:01:58
Calculo con un String AMC Varios 7 14-09-2004 20:46:53
Calculo De Totales PETERKANTROPUS Tablas planas 2 25-05-2004 03:06:14


La franja horaria es GMT +2. Ahora son las 18:13:34.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi