ÍNDICE

01. Visión General

Debido a la actualización de la Facturación Electrónica con la Reforma Fiscal 2022; se modificó en el apartado Recibo de Nómina (dentro de la documentación técnica Factura Electrónica) del CFDI 4.0, se establece que la vigencia de esta nueva versión inicia a partir del 01 de enero del 2022, el complemento de nómina versión 1.2 se integra con la versión 4.0 del CFDI en su revisión C, siendo obligatorio a partir del 1 de julio de 2022.

Por tanto, será a partir del 1 de julio de 2022 que se deje de utilizar la versión 3.3 y se generalice la obligación de emitir la versión 4.0.


Para cumplir con dicha reforma fiscal, se modifica el esquema del CFDI con los siguientes cambios:

Para mayor información ver la documentación del Portal del SAT.


02. Rutinas Utilizadas

Para contar con la nueva funcionalidad de Recibo de Nómina para versión CFDI 4.0, es necesario tener actualizadas las siguientes rutinas:


GPER884.PRWRecibos de Nomina CFDI v 1.2
GPER884.INIGeneración de XML para recibos de Nómina 3.3
GPER88440.INIGeneración de XML para recibos de Nómina 4.0
GPTABMEX.PRXDefinición tablas alfanuméricas. 
GPCRGMEX.PRXMantenimiento tablas alfanuméricas. 
TIMBRERN.PRWTimbrado de CFDI con Complemento de Recibo de Nómina.
CANCTFD.PRWCancelación de CFDI con Complemento de Nómina.

Al contar con las versiones de las rutinas descritas anteriormente; en la rutina Recibos de Nómina CFDI Versión 1.2 (GPER884), si no se cuenta con la actualización del Diccionario de Datos mencionadas en el presente Documento Técnico, no se podrá utilizar la rutina. Se enviará un mensaje indicando que se debe actualizar el grupo de preguntas GPER884.

Lo anterior se agregó para evitar errores en el proceso de Timbrado y Cancelación.

03. Ejemplo de Utilización

Implementación

  1. Realizar las configuraciones al Diccionario de Datos mencionadas en la sección 06. Diccionario de Datos.
  2. Realizar las modificaciones al Script de Generación del Comprobante Fiscal (XML) del Recibo de Nómina (GPER884.INI), mencionadas en la sección 07. Archivo de Configuración (GPER884.INI).
  3. Colocar el Script de Generación del Comprobante Fiscal (XML) del Recibo de Nómina (GPER884.INI), en la carpeta "System".
  4. Colocar el ejecutable homologado del Proveedor Autorizado de Certificación (PAC), en el directorio configurado en el parámetro MV_CFDSMAR.
  5. Colocar los Certificados emitidos por el SAT (archivos .cer, .key, .pfx y .pem), como se indica a continuación:
  6. Crear la carpeta "cancelar", dentro del directorio configurado en el parámetro MV_CFDRECN, por ejemplo:

Escenarios

01 - Comprobante emitido con errores con relación

Cuando se emite un CFDI con errores, como por ejemplo un error en el cálculo de conceptos; es necesario cancelarlo y se realiza de la siguiente forma:

  1. Emitir el CFDI que corrija el error, el cual deberá tener relacionado el "UUID" del comprobante a corregir en el nodo "CfdiRelacionados" y con la clave "04" que indica la "Sustitución de los CFDI previos".
  2. Realizar la Cancelación del CFDI con errores, para la cual se tendrá que enviar el motivo "01" y el Folio Fiscal del CFDI que corrige.
Ejemplo del proceso

¿Cómo cancelo un Recibo de Nómina con el Motivo "01" en Protheus?

Cancelación automática:

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Recibo de Nómina CFDI V1.2, ubicada en "Informes | Empleados | Recibo de Nómina CFDI V1.2 (GPER884)".
  3. Informar las preguntas solicitadas y considerar las siguientes indicaciones:
  4. Dar clic en "Ok".
  5. Visualizar el mensaje que confirma el timbrado del nuevo CFDI y la anulación del CFDI anterior.
  6. Validar que la información en la tabla Folios Fiscales de Nómina (RIW), sea actualizada de forma correcta.


Debido a que el proceso de generación de Comprobantes Fiscales (XML), para la nómina de Finiquitos genera dos XML's y estos tienen conceptos de indemnización, es posible que los errores de cálculo en los conceptos no apliquen para ambos XML; por lo tanto, tendría que cancelarse por separado.

Por lo anterior, se recomienda configurar la pregunta ¿Enviar a Canc. Rec. Ant.? en "NO" y después desde la rutina Cancelación de Recibos de Nómina (CANCTFD) seleccionar y cancelar solo el recibo con error.


Cancelación manual:

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Recibo de Nómina CFDI V1.2, ubicada en "Informes | Empleados | Recibo de Nómina CFDI V1.2 (GPER884)".
  3. Informar las preguntas solicitadas y considerar las siguientes indicaciones para las preguntas nuevas:
  4. Dar clic en "Ok".
  5. Visualizar el mensaje que confirma el timbrado del nuevo CFDI.
  6. Ingresar a la rutina Cancelación de Recibos de Nómina, ubicada en "Informes | Empleados | Cancelación Recibo Nómina (CANCTFD)".
  7. Informar las preguntas solicitadas:
  8. Seleccionar el CFDI con error, para su cancelación.
  9. Dar clic en "Ok".
  10. Visualizar el mensaje que confirma la correcta anulación del CFDI.
  11. Validar que en la tabla Folios Fiscales de Nómina (RIW), sean actualizados los campos Fch Canc Tim (RIW_FECANT)Motivo Canc. (RIW_MOTIVO) y UUID Sustit. (RIW_IDSUST).


02 - Comprobante emitido con errores sin relación

Cuando se emite un CFDI con errores, como por ejemplo un error en la información del receptor; es necesario cancelarlo y se realiza de la siguiente forma:

  1. Realizar solicitud de Cancelación del CFDI con errores, para la cual se tendrá que enviar el motivo "02".
  2. Emitir el CFDI que corrija el error.
Ejemplo del proceso

¿Cómo cancelo un Recibo de Nómina con el Motivo "02" en Protheus?

Cancelación automática:

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Recibo de Nómina CFDI V1.2, ubicada en "Informes | Empleados | Recibo de Nómina CFDI V1.2 (GPER884)".
  3. Informar las preguntas solicitadas y considerar las siguientes indicaciones:
  4. Dar clic en "Ok".
  5. Visualizar el mensaje que confirma el timbrado del nuevo CFDI y la anulación del CFDI anterior.
  6. Validar que la información en la tabla Folios Fiscales de Nómina (RIW), sea actualizada de forma correcta.

Cancelación manual:

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Recibo de Nómina CFDI V1.2, ubicada en "Informes | Empleados | Recibo de Nómina CFDI V1.2 (GPER884)".
  3. Informar las preguntas solicitadas y considerar las siguientes indicaciones:
  4. Dar clic en "Ok".
  5. Visualizar el mensaje que confirma el timbrado del nuevo CFDI.
  6. Ingresar a la rutina Cancelación de Recibos de Nómina, ubicada en "Informes | Empleados | Cancelación Recibo Nómina (CANCTFD)".
  7. Informar las preguntas solicitadas:
  8. Seleccionar el CFDI con error, para su cancelación.
  9. Dar clic en "Ok".
  10. Visualizar el mensaje que confirma la correcta anulación del CFDI.
  11. Validar que en la tabla Folios Fiscales de Nómina (RIW), sean actualizados los campos Fch Canc Tim (RIW_FECANT) y Motivo Canc. (RIW_MOTIVO).

03 - Comprobante del cual no se llevó a cabo la operación

Cuando se emite un CFDI por error, como por ejemplo un CFDI de Finiquitos para un empleado incorrecto; es necesario cancelarlo y se realiza de la siguiente forma:

  1. Realizar la solicitud de Cancelación del CFDI emitido por error, para la cual se tendrá que enviar el motivo "03".
Ejemplo del proceso

¿Cómo cancelo un Recibo de Nómina con el Motivo "03" en Protheus?

Cancelación manual:

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Cancelación de Recibos de Nómina, ubicada en "Informes | Empleados | Cancelación Recibo Nómina (CANCTFD)".
  3. Informar las preguntas solicitadas:
  4. Seleccionar el CFDI con error, para su cancelación.
  5. Dar clic en "Ok".
  6. Visualizar el mensaje que confirma la correcta anulación del CFDI.
  7. Validar que en la tabla Folios Fiscales de Nómina (RIW), sean actualizados los campos Fch Canc Tim (RIW_FECANT) y Motivo Canc. (RIW_MOTIVO).

04. Timbrado de Recibos de Nómina

Descripción general del proceso de Generación, Timbrado, Impresión y Envío de Recibos de Nómina:

Ubicación

Menú

Gestión de Personal

Submenú

Informes | Empleados

Nombre de la Rutina

Recibo de Nómina CFDI V1.2

Programa

GPER884

Módulo

Gestión de Personal

Tipo

Función Protheus

Procedimiento

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Recibo de Nómina CFDI V1.2, ubicada en "Informes | Empleados | Recibo de Nómina CFDI V1.2 (GPER884)".
  3. Informar los parámetros solicitados:
  4. Dar clic en "Ok", para confirmar los parámetros e iniciar el proceso.
  5. Visualizar el mensaje de confirmación.
  6. Visualizar el "PDF" del Recibo de Nómina en pantalla:

05. Cancelación de Recibos de Nómina

Descripción general del proceso de Generación, Timbrado, Impresión y Envío de Recibos de Nómina:

Ubicación

Menú

Gestión de Personal

Submenú

Informes | Empleados

Nombre de la Rutina

Cancelación Recibo Nómina

Programa

CANCTFD

Módulo

Gestión de Personal

Tipo

Función Protheus

Procedimiento

  1. Ingresar al módulo SIGAGPE - Gestión de Personal.
  2. Ingresar a la rutina Cancelación de Recibos de Nómina, ubicada en "Informes | Empleados | Cancelación Recibo Nómina (CANCTFD)".
  3. Informar los parámetros solicitados:
  4. Dar clic en "Ok".

  5. Visualizar el mensaje de confirmación:

06. Diccionario de Datos

Ingresar al módulo Configurador (SIGACFG) y realizar las siguientes modificaciones:

Grupos de Preguntas (SX1)

Agregar las preguntas resaltadas en azul:

Grupo GPER884

Orden

Pregunta

Tipo

Tamaño

DecimalPre-selección

Modo

Validación

Variable

Def. 01

Def. 02

Consulta

Help

01¿Proceso?C50
Get
MV_PAR01                              RCJ   
02¿Procedimiento?C30
Get
MV_PAR02                              SRY   
03¿Periodo?C60
Get
MV_PAR03                              RCH   
04¿Número de Pago?C20
Get
MV_PAR04                              RCH01 
05¿Pre-Imp/Mail?C10
Combo
MV_PAR05Impreso        E-Mail               
06¿De Sucursal?C80
Get
MV_PAR06                              XM0   
07¿A Sucursal?C80
Get
MV_PAR07                              XM0   
08¿De Matricula?C60
Get
MV_PAR08                              SRA02 
09¿A Matricula?C60
Get
MV_PAR09                              SRA02 
10¿De Nombre?C300
Get
MV_PAR10                                    
11¿A Nombre?C300
Get
MV_PAR11                                    
12¿De Nº de Tarj. sin Rel.?C50
Get
MV_PAR12                                    
13¿A Nº de Tarj. sin Rel.?C50
Get
MV_PAR13                                    
14¿De Centro de costo?C90
Get
MV_PAR14                              CTT   
15¿A centro de costo?C90
Get
MV_PAR15                              CTT   
16¿De departamento?C90
Get
MV_PAR16                              SQB   
17¿A departamento?C90
Get
MV_PAR17                              SQB   
18¿Situaciones por Impr.?C50
GetfSituacao()MV_PAR18                                    
19¿Categorías por Impr.?C150
GetfCategoria()MV_PAR19                                    
20¿Mensaje 1?C30
Get
MV_PAR20                              X06   
21¿Mensaje 2?C30
Get
MV_PAR21                              X06   
22¿Mensaje 3?C30
Get
MV_PAR22                              X06   
23¿Mensaje Pie de Pag.?C40
Get
MV_PAR23                              S018  
24¿De Local Pago?C40
Get
MV_PAR24                              RGC   
25¿A Local Pago?C40
Get
MV_PAR25                              RGC   
26¿Sumariza Concepto?C102Combo
MV_PAR26SI             NO                   
27¿Envía Timbrar?             C101Combo
MV_PAR27SI             NO                   
28¿Sustituye Recibo Anterior?C102Combo
MV_PAR28SI             NO                   

Seleccione la opción "SI", para generar un nuevo recibo que corrige al anterior; lo cual solo aplica cuando ocurrió un error en la emisión del recibo anterior para el Empleado, Proceso, Procedimiento, Periodo y Número de Pago seleccionados.

Seleccione la opción “NO”, si no se realizará la corrección de un recibo anterior para el Empleado, Proceso, Procedimiento, Periodo y Número de Pago seleccionados.

29¿Enviar a Canc. Rec. Ant.?C102Combo
MV_PAR30SI             NO             

Seleccione la opción "SI", para que al finalizar el timbrado del CFDI que corrige, automáticamente se envíe a cancelar el recibo anterior para el Empleado, Proceso, Procedimiento, Periodo y Número de Pago seleccionados.

Seleccione la opción "NO", para solo generar el recibo que corrige al anterior y Cancelar posteriormente desde la rutina Cancelación de Recibo de Nómina (CANCTFD).

30¿Motivo de Cancelación?C102Combo
MV_PAR2901 - Con Relac.02 - Sin Relac.      

Seleccione el motivo por el cual se cancelará el recibo anterior.

01 - Comprobante emitido con errores con relación; por ejemplo, un recibo con error en el cálculo de conceptos.

02 - Comprobante emitido con errores sin relación; por ejemplo, un recibo con error en la información del empleado.

Grupo CANCTFD

Agregar las preguntas resaltadas en azul:

Orden

Pregunta

Tipo

Tamaño

DecimalPre-selecciónGrupo de campos

Modo

Validación

Variable

Def. 01

Def. 02

Def. 03Consulta

Help

01¿Proceso?C50

GetGpr040Valid(MV_PAR01)MV_PAR01                              
RCJ   
02¿Procedimiento?C30

GetExistcpo('SRY') .and. fSetVarPer(,,,,,,'cRot',MV_PAR02 )MV_PAR02                               
SRY   
03¿Periodo?C60

GetGpr040Valid(MV_PAR01 + MV_PAR02 + MV_PAR03)MV_PAR03                              
RCH   
04¿Numero de Pago?C20

GetGpr040Valid(MV_PAR01 + MV_PAR02 + MV_PAR03 + MV_PAR04)MV_PAR04                              
RCH01 
05¿De Sucursal?C100

Get
MV_PAR05Impreso        E-Mail         
XM0   
06¿A Sucursal?C100

GetNaoVazio()MV_PAR06                              
XM0   
07¿De matrícula?C60
121Get
MV_PAR07                              
SRA02 
08¿A matrícula?C60
121GetNaoVazio()MV_PAR08                              
SRA02 
09¿Ruta Archivos XML?C990

GetNaoVazio()MV_PAR09                              
HSSDIR
10¿Motivo de Cancelación?C102
Combo
MV_PAR1001 - Con Relac.02 - Sin Relac.03 - Sin Opera.      

Seleccione el motivo con el cual se cancelarán los recibos del Empleado, Proceso, Procedimiento, Periodo y Número de Pago seleccionados

01 - Comprobante emitido con errores con relación; por ejemplo un recibo con error en el cálculo de conceptos.

02 - Comprobante emitido con errores sin relación; por ejemplo, un recibo con error en la información del empleado.

03 - No se llevó a cabo la operación; por ejemplo, un recibo de Finiquitos emitido para el empleado incorrecto.

Campos (SX3)

Crear los siguientes campos:

Campo RIW_MOTIVO
NombreRIW_MOTIVO
Orden10
TipoCaracter
Tamaño2
Decimal0
Formato@!
TítuloMotivo Canc.
DescripciónMotivo de Cancelación
ContextoReal
PropiedadModificar
ObligatorioNo
Usado
BrowseNo
Help

Campo utilizado para almacenar el Motivo de Cancelación del CFDI.

01 - Comprobantes emitidos con errores con relación.

02 - Comprobantes emitidos con errores sin relación.

03 - No se llevó a cabo la operación.

Campo RIW_IDSUST
NombreRIW_IDSUST
Orden11
TipoCaracter
Tamaño36
Decimal0
Formato@!
TítuloUUID Sustit.
DescripciónUUID que sustituye
ContextoReal
PropiedadModificar
ObligatorioNo
Usado
BrowseNo
Help

Campo utilizado para almacenar el UUID (Folio Fiscal) que sustituye.

   

Los ajustes al Diccionario de Datos estándar, se realizaron en el siguiente paquete de uso interno:

Código: 010274
Descripción: DNOMI-47 - CANCELACIÓN CFDI NÓMINA - MEX

07. Archivo de Configuración (GPER884.INI)

Realizar las modificaciones resaltadas en azul, para el Script de Generación del Comprobante Fiscal del Recibo de Nómina, como se muestra a continuación:

/*GPER884.INI V1.2 - Modelo 2017 - 20/03/2017*/
[XXX POSICIONAMENTOS]

[XXX INICIALIZACION]   
(PRE) SRVPD->(DbSetOrder(1)) 
(PRE) _aTotal[072] := SRA->RA_FILIAL
(PRE) _aTotal[073] := SRA->RA_MAT
(PRE) _aTotal[074] := ""
(PRE) _aTotal[075] := CFDCarEsp(Alltrim(SM0->M0_NOMECOM))
(PRE) _aTotal[076] := StrZero(Year(Date()),4) + "-" + StrZero(Month(Date()),2) + "-" + StrZero(Day(Date()),2) + "T" + Time() 
(PRE) _aTotal[077] := Alltrim(MV_PAR01)+Alltrim(MV_PAR02)+Alltrim(MV_PAR03)+Alltrim(MV_PAR04)
(PRE) _aTotal[078] := Alltrim(SRA->RA_MAT)+Alltrim(SRA->RA_FILIAL)
(PRE) _aTotal[098] := "|"
(PRE) _aTotal[099] := "||"
(PRE) _aTotal[100] := ""

//CADENA  ORIGINAL
[SRA CADENAORIGINAL_SELLO]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

//Cadena Original
(PRE) cCadOrig := _aTotal[099]
//Version
(PRE) cCadOrig += "3.3" + _aTotal[098]
//Serie
(PRE) cCadOrig += _aTotal[078] + _aTotal[098]
//Folio
(PRE) cCadOrig += _aTotal[077] + _aTotal[098]
//Fecha
(PRE) cCadOrig += Alltrim(_aTotal[076]) + _aTotal[098]
//Forma Pago
(PRE) cCadOrig += CFDCarEsp("99") + _aTotal[098]
//Num Certificado
(PRE) cCadOrig += SuperGetMv("MV_CFDI_CS",,"") + _aTotal[098]
//Subtotal
(PRE) cCadOrig += Alltrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP), 2), "99999999.99")) + _aTotal[098]
//Descuento
(PRE) cCadOrig += Alltrim(Transform(Round(nOtroDedu+nImpReten,2), "99999999.99")) + _aTotal[098]
//Moneda
(PRE) cCadOrig += Alltrim("MXN") + _aTotal[098]
//Total
(PRE) cCadOrig += Alltrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP) - (nOtroDedu + nImpReten), 2), "99999999.99")) + _aTotal[098]
//Tipo Comprobante
(PRE) cCadOrig += Alltrim("N") + _aTotal[098]
//Metodo Pago
(PRE) cCadOrig += Alltrim("PUE") + _aTotal[098]
//Lugar de expedición
(PRE) cCadOrig += CFDCarEsp(AllTrim(RGC->RGC_CODPOS)) + _aTotal[098] 
//Tipo Relacionados
(PRE) cCadOrig += NodoRelacc(3) 
//UUIDS Relacionados
(PRE) cCadOrig += NodoRelacc(1)

//COMPROBANTE:EMISOR
//:RFC
(PRE) cCadOrig += CFDCarEsp(Alltrim(SM0->M0_CGC)) + _aTotal[098]
//:Nombre
(PRE) cCadOrig += Alltrim(SM0->M0_NOMECOM) + _aTotal[098]
//:Regimen
(PRE) cCadOrig += cTipoReg + _aTotal[098]

//COMPROBANTE:RECEPTOR
//:RFC
(PRE) cCadOrig += CFDCarEsp(AllTrim(SRA->RA_CIC)) + _aTotal[098]
//:Nombre
(PRE) cCadOrig += CFDCarEsp(Alltrim(SRA->RA_NOME)) + _aTotal[098]
//:UsoCFDI
(PRE) cCadOrig += Alltrim("P01") + _aTotal[098]

//COMPROBANTE:CONCEPTOS
//Clave Servicio
(PRE) cCadOrig += AllTrim("84111505")+ _aTotal[098]
//:Cantidad
(PRE) cCadOrig += Alltrim("1")+ _aTotal[098]
//:Unidad de medida
(PRE) cCadOrig += Alltrim("ACT")+ _aTotal[098]
//:Descripcion
(PRE) cCadOrig += DECODEUTF8(AllTrim("Pago de nómina")) + _aTotal[098]
//:valorUnitario
(PRE) cCadOrig += AllTrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP),2), "99999999.99")) + _aTotal[098]
//Importe
(PRE) cCadOrig += AllTrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP),2), "99999999.99")) + _aTotal[098]
//TotalDeducciones
(PRE) cCadOrig += Alltrim(Transform(Round(nTotDGrav+nTotDExen,2), "99999999.99")) + _aTotal[098]

//NOMINA
//version
(PRE) cCadOrig += "1.2" + _aTotal[098]
//TipoNomina
(PRE) cCadOrig += IIf(SRY->RY_TIPO == "1" .And. !lImprIndem, "O", "E") + _aTotal[098]
//FechaPago
(PRE) cCadOrig += Alltrim(STR(YEAR(dFchPag)))+"-"+ STRZERO(MONTH(dFchPag),2) +"-"+STRZERO(DAY(dFchPag),2) + _aTotal[098]
//FechaInicialPago
(PRE) cCadOrig += Alltrim(STR(YEAR(dFchInPag)))+"-"+ STRZERO(MONTH(dFchInPag),2) +"-"+STRZERO(DAY(dFchInPag),2) + _aTotal[098]
//FechaFinalPago
(PRE) cCadOrig += Alltrim(STR(YEAR(dFchFiPag)))+"-"+ STRZERO(MONTH(dFchFiPag),2) +"-"+STRZERO(DAY(dFchFiPag),2) + _aTotal[098]
//NumDiasPagados
(PRE) cCadOrig += Alltrim(Str(IIf(nDiasPag == 0, 1, nDiasPag))) + _aTotal[098]
//TotalPercepciones
(PRE) cCadOrig += IIf(nTotPGrav+nTotPExen <> 0, Alltrim(Transform(Round(nTotPGrav+nTotPExen,2), "99999999.99")) + _aTotal[098], "")
//TotalDeducciones
(PRE) cCadOrig += IIf(nTotDGrav+nTotDExen <> 0, Alltrim(Transform(Round(nTotDGrav+nTotDExen,2), "99999999.99")) + _aTotal[098], "")
//TotalOtrosPagos
(PRE) cCadOrig += IIf(nTotOtroP <> 0 .And. !lRegAsimil, AllTrim(Transform(Round(nTotOtroP,2), "99999999.99")) + _aTotal[098], "")

//EMISOR
//RegistroPatronal
(PRE) cCadOrig += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, AllTrim(cRegPatr) + _aTotal[098], "")
//RfcPatronOrigen
(PRE) cCadOrig += CFDCarEsp(Alltrim(SM0->M0_CGC)) + _aTotal[098]

//EntidadSNCF
(PRE) IIf(!Empty(cOrigRecur), cCadOrig += Alltrim(cOrigRecur) + _aTotal[098], "")
(PRE) IIf(!Empty(cOrigRecur), cCadOrig += Alltrim(Transform(Round(nTotPGrav+nTotPExen,2), "99999999.99")) + _aTotal[098], "")

//RECEPTOR
//Curp
(PRE) cCadOrig += Alltrim(SRA->RA_CURP) + _aTotal[098]
//NumSeguridadSocial
(PRE) IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, cCadOrig += AllTrim(SRA->RA_RG) + _aTotal[098], "")
//FechaInicioRelLaboral
(PRE) IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, cCadOrig += AllTrim(Str(Year(dFchInLab))) + "-" + StrZero(Month(dFchInLab),2) + "-" + StrZero(Day(dFchInLab),2) + _aTotal[098], "")
//Antigüedad
(PRE) IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, cCadOrig += 'P' + AllTrim(Str(nAntigue)) + 'W' + _aTotal[098], "")
//TipoContrato
(PRE) cCadOrig += IIf(lImprIndem,"99", Alltrim(SRA->RA_TIPCON)) + _aTotal[098]
//Sindicalizado
(PRE) IIf(SRA->RA_CATFUNC <> 'A', cCadOrig += IIf(!Empty(SRA->RA_SINDICA) .And. !lRegAsimil, "Sí", "No") + _aTotal[098], "")
//TipoJornada
(PRE) IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil, cCadOrig += AllTrim(cTipJorn) + _aTotal[098], "")
//TipoRegimen
(PRE) cCadOrig += IIf(lImprIndem,"13",AllTrim(SRA->RA_TIPREG)) + _aTotal[098]
//NumEmpleado
(PRE) cCadOrig += AllTrim(SRA->RA_MAT) + _aTotal[098]
//Departamento
//MOD (PRE) cCadOrig += IIf(!Empty(cDeptoIm), AllTrim(cDeptoIm), "") + _aTotal[098]
(PRE) cCadOrig += IIf(!Empty(cDeptoIm), AllTrim(cDeptoIm) + _aTotal[098], "")
//Puesto
(PRE) cCadOrig += IIf(!Empty(cPuesCfdi), AllTrim(cPuesCfdi) + _aTotal[098], "")
//RiesgoPuesto
(PRE) cCadOrig += IIf(!lRegAsimil .AND. !lImprIndem, IIf(SRA->RA_CATFUNC <> 'A', AllTrim(cRiegCFDi), AllTrim("99"))  + _aTotal[098], "")
//PeriodicidadPago
(PRE) cCadOrig += CFDCarEsp(Alltrim(IIf(SRY->RY_TIPO == "1",cPerCFDi, "99"))) + _aTotal[098]
//Banco
(PRE) IIf(!Empty(SRA->RA_CLABE),,cCadOrig += IIf(!Empty(cBcoCfdi), Alltrim(cBcoCfdi) + _aTotal[098], ""))
//CLABE
(PRE) cCadOrig += IIf(!Empty(SRA->RA_CLABE), Alltrim(SRA->RA_CLABE), Alltrim(SRA->RA_CTDEPSA)) + _aTotal[098]
//SalarioBaseCotApor
(PRE) IIf(SRA->RA_CATFUNC <> 'A', cCadOrig += Alltrim(Transform(Round(nSalBasAp,2), "99999999.99")) + _aTotal[098], "")
//SalarioDiarioIntegrado
(PRE) IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, cCadOrig += AllTrim(Transform(Round(SRA->RA_SALINT,2), "99999999.99")) + _aTotal[098], "")
//ClaveEntFed
(PRE) cCadOrig += Alltrim(cEntFed) + _aTotal[098]

//SUBCONTRATACION
//RfcLabora
(PRE) cCadOrig += IIf(SRA->RA_PORSUB <> 0, Alltrim(SRA->RA_RFCLAB) + _aTotal[098], "")
//PorcentajeTiempo
(PRE) cCadOrig += IIf(SRA->RA_PORSUB <> 0, Alltrim(Str(SRA->RA_PORSUB)) + _aTotal[098], "")

//PERCEPCIONES
//TotalSueldos
(PRE) IIf(nTotSueld <> 0, cCadOrig += Alltrim(Transform(Round(nTotSueld,2), "99999999.99")) + _aTotal[098], "")
//TotalSeparacionIndemnizacion
(PRE) IIf(nTotIndem <> 0, cCadOrig += Alltrim(Transform(Round(nTotIndem,2), "99999999.99")) + _aTotal[098], "")
//TotalJubilacionPensionRetiro
(PRE) IIf(nTotJubil <> 0, cCadOrig += Alltrim(Transform(Round(nTotJubil,2), "99999999.99")) + _aTotal[098], "")
//TotalGravado
(PRE) cCadOrig += Alltrim(Transform(Round(nTotPGrav,2), "99999999.99")) + _aTotal[098]
//TotalExento
(PRE) cCadOrig += Alltrim(Transform(Round(nTotPExen,2), "99999999.99")) + _aTotal[098]
//PERCEPCION (AccionesOTitulos y/o Horas Extras)
(PRE) VldCad884("1")

//JubilacionPensionRetiro
//TotalUnaExhibicion
(PRE) IIf(nTotUnaEx <> 0, cCadOrig += Alltrim(Transform(Round(nTotUnaEx,2), "99999999.99")) + _aTotal[098], "")
//TotalParcialidad
(PRE) IIf(nTotParci <> 0, cCadOrig += Alltrim(Transform(Round(nTotParci,2), "99999999.99")) + _aTotal[098], "")
//MontoDiario
(PRE) IIf(nTotParci <> 0, cCadOrig += Alltrim(Transform(Round(nTotDiari,2), "99999999.99")) + _aTotal[098], "")
//IngresoAcumulable
(PRE) IIf(nTotUnaEx+nTotParci <> 0, cCadOrig += Alltrim(Transform(Round(nTotIAcum,2), "99999999.99")) + _aTotal[098], "")
//IngresoNoAcumulable
(PRE) IIf(nTotUnaEx+nTotParci <> 0, cCadOrig += Alltrim(Transform(Round(NTotNAcum,2), "99999999.99")) + _aTotal[098], "")

//SeparacionIndemnizacion 
//TotalPagado
(PRE) IIf(nTotPagad <> 0, cCadOrig += Alltrim(Transform(Round(nTotPagad,2), "99999999.99")) + _aTotal[098], "")
//NumAñosServicio
(PRE) IIf(nTotPagad <> 0, cCadOrig += Alltrim(Str(IIf(nNumAnios==0, 1, nNumAnios))) + _aTotal[098], "")
//UltimoSueldoMensOrd
(PRE) IIf(nTotPagad <> 0, cCadOrig += Alltrim(Transform(Round(nUltSuelM,2), "99999999.99")) + _aTotal[098], "")
//IngresoAcumulable
(PRE) IIf(nTotPagad <> 0, cCadOrig += Alltrim(Transform(Round(nIngrAcum,2), "99999999.99")) + _aTotal[098], "")
//IngresoNoAcumulable
(PRE) IIf(nTotPagad <> 0, cCadOrig += Alltrim(Transform(Round(nIngrNAcu,2), "99999999.99")) + _aTotal[098], "")

//DEDUCCIONES
//TotalOtrasDeducciones
(PRE) IIf(nOtroDedu <> 0, cCadOrig += Alltrim(Transform(Round(nOtroDedu,2), "99999999.99")) + _aTotal[098], "")
//TotalImpuestosRetenidos
(PRE) IIf(nImpReten <> 0, cCadOrig += Alltrim(Transform(Round(nImpReten,2), "99999999.99")) + _aTotal[098], "")
//DEDUCCION
(PRE) VldCad884("2")

//OtroPago
//TipoOtroPago (SubsidioAlEmpleo - CompensacionSaldosAFavor)
(PRE) IIf(!lRegAsimil, VldCad884("3"), .T.)

//Incapacidad
(PRE) VldCad884("4")  

(PRE) cCadOrig += _aTotal[098]
(POS) _aTotal[074] := ENCODEUTF8(cCadOrig)
(POS) cCadOrig := ENCODEUTF8(cCadOrig)
//Sello
(POS) _aTotal[100] := LjHex2Asc(SHA256(cCadOrig,2))
(POS) _aTotal[100] := PrivSignRSA(&(SuperGetMv("MV_CFDDIRS",,""))+SuperGetMv("MV_CFDI_KP",,""),_aTotal[100],6,"assinatura")
(POS) _aTotal[100] := ENCODE64(_aTotal[100])

//                                          C O N F I G U R A C I O N    D E L    A R C H I V O :    R E C N O M . INI
[XXX CABECERA]
Linha1     C 041 0 Chr(239) + Chr(187) + Chr(191) + '<?xml version="1.0" encoding="UTF-8"?>'

//CFDI:  CFDI:COMPROBANTE
[XXX CFDI]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

//Certificado
//CSD_XIA190128J61c.pem XIA190128J61 - pruebas SAT
(PRE) cCert01 := "MIIFyDCCA7CgAwIBAgIUMzAwMDEwMDAwMDA0MDAwMDI0NDMwDQYJKoZIhvcNAQEL"
(PRE) cCert01 += "BQAwggErMQ8wDQYDVQQDDAZBQyBVQVQxLjAsBgNVBAoMJVNFUlZJQ0lPIERFIEFE"
(PRE) cCert01 += "TUlOSVNUUkFDSU9OIFRSSUJVVEFSSUExGjAYBgNVBAsMEVNBVC1JRVMgQXV0aG9y"
(PRE) cCert01 += "aXR5MSgwJgYJKoZIhvcNAQkBFhlvc2Nhci5tYXJ0aW5lekBzYXQuZ29iLm14MR0w"
(PRE) cCert01 += "GwYDVQQJDBQzcmEgY2VycmFkYSBkZSBjYWRpejEOMAwGA1UEEQwFMDYzNzAxCzAJ"
(PRE) cCert01 += "BgNVBAYTAk1YMRkwFwYDVQQIDBBDSVVEQUQgREUgTUVYSUNPMREwDwYDVQQHDAhD"
(PRE) cCert01 += "T1lPQUNBTjERMA8GA1UELRMIMi41LjQuNDUxJTAjBgkqhkiG9w0BCQITFnJlc3Bv"
(PRE) cCert01 += "bnNhYmxlOiBBQ0RNQS1TQVQwHhcNMTkwNjE3MjA0MDUxWhcNMjMwNjE3MjA0MDUx"
(PRE) cCert01 += "WjCB7zEqMCgGA1UEAxMhWEVOT04gSU5EVVNUUklBTCBBUlRJQ0xFUyBTIERFIENW"
(PRE) cCert01 += "MSowKAYDVQQpEyFYRU5PTiBJTkRVU1RSSUFMIEFSVElDTEVTIFMgREUgQ1YxKjAo"
(PRE) cCert01 += "BgNVBAoTIVhFTk9OIElORFVTVFJJQUwgQVJUSUNMRVMgUyBERSBDVjElMCMGA1UE"
(PRE) cCert01 += "LRMcWElBMTkwMTI4SjYxIC8gS0FITzY0MTEwMUIzOTEeMBwGA1UEBRMVIC8gS0FI"
(PRE) cCert01 += "TzY0MTEwMUhOVExLUzA2MSIwIAYDVQQLExlYZW5vbiBJbmR1c3RyaWFsIEFydGlj"
(PRE) cCert01 += "bGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiJQ5YcSgjwsGf29+"
(PRE) cCert01 += "3go7VGdtMZCcH9wUpn46ZMAlFwUojnCPTvwJ3+cSwjqJnw8ahr3DuRwekvGR4BJA"
(PRE) cCert01 += "b5b9Xi8kyoiWtwcGOSWxO38Bp9J1e/BO9HMbQBPAtLDuG47oqnH8zWLOeaoYRJDp"
(PRE) cCert01 += "ARw4RX1ko2+9tbj0ntBtM7Vk1E8EWiA/h2Meq0LIv1+ySGTUrEW46FM01J5pzELv"
(PRE) cCert01 += "5XupBghuJxR5DG9fiOW7u3dR5s3tZoVLwA1KdjJtY0mmnfCwxg6i5AqhvY+FAI5D"
(PRE) cCert01 += "6CF6/lHA8PWg63WasvrhuIv70xCLjgPT/j00ZcPrLvBf1DefGVic980Ch/SDvC+M"
(PRE) cCert01 += "dJ1F5wIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG"
(PRE) cCert01 += "9w0BAQsFAAOCAgEACjfTPoKY2N5MxjmAMltd5XZCV1vgAwEtrIRYTodhE8R0Tp1Q"
(PRE) cCert01 += "anAXb0luPyBv5hIXWK4VqAI4fcTtP+n7kkrwfha6ErkPWFNJWJm8ZsMmby/3WgVo"
(PRE) cCert01 += "JkOFyRYQqr5Il3N6wMa5kiDBtDRbqB3iEXmvtrvjWSHyxAER+zo3jWGFlhBZ0nQN"
(PRE) cCert01 += "Rtjx8sPFihVc5TUH682HJiU4oWvT63Dnra8ncqiW/uCuY86crnUq0fW7Lw/3+PY5"
(PRE) cCert01 += "xXjNxR/Hh3sUPITfJrGaLWurD1J9npr9yGAJ6t9zrhhZnepIC0DUMc5+j4pg1DrO"
(PRE) cCert01 += "32jzwUOLQqErDizh84NoJCWwbg+US8wi3zD0ZKiDv7XsTNWAW2Ap2JkzykKHjFTZ"
(PRE) cCert01 += "iEm3uZOkJNfcu3o+kefr5HfXFT+iN9K5FUEhaQwgUeZBRJ8V5F6gmhz3d6ixVbiZ"
(PRE) cCert01 += "oFNhYR8e2k8gF9gGrVMrEbJGQrl+6+ZYQLFiauXeG7fu1svk19PuyredRJGnseJq"
(PRE) cCert01 += "yV4RzcRGhJA+cLnmpdDOTEhignnvnhEuY6HVRYYXhOTyeeluET7KRCxbJGqO7TdW"
(PRE) cCert01 += "gjrHL3HRbNE4NY5GAdOZuLaWxElG5ZVCHqtG0Nh7UQAhcz+EKyZBAewv5XuH0Oom"
(PRE) cCert01 += "ZXw6mM2mY2soL6z1224NusM8/BbJcYTQUlAEKblEChhGK1XlxiVOU2nc9KE="

(PRE) if (SM0->M0_CODIGO == '01', cCert := cCert01,cCert := cCert01)

(PRE) _aTotal[001] := '<cfdi:Comprobante'
(PRE) _aTotal[001] += ' xmlns:cfdi="http://www.sat.gob.mx/cfd/3"'
(PRE) _aTotal[001] += ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
(PRE) _aTotal[001] += ' xmlns:nomina12="http://www.sat.gob.mx/nomina12"'
(PRE) _aTotal[001] += ' xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd http://www.sat.gob.mx/nomina12 http://www.sat.gob.mx/sitio_internet/cfd/nomina/nomina12.xsd"'
(PRE) _aTotal[001] += ' Version="3.3"'
(PRE) _aTotal[001] += ' Serie="' + _aTotal[078] + '"'
(PRE) _aTotal[001] += ' Folio="' + _aTotal[077] + '"'
(PRE) _aTotal[001] += ' Fecha="' + _aTotal[076]+ '"'  
(PRE) _aTotal[001] += ' Sello="' + Alltrim(_aTotal[100]) + '"'
(PRE) _aTotal[001] += ' FormaPago="' + CFDCarEsp("99")+ '"'
(PRE) _aTotal[001] += ' NoCertificado="' + SuperGetMv("MV_CFDI_CS",,"") + '"'   
(PRE) _aTotal[001] += ' Certificado="' + cCert + '"'
(PRE) _aTotal[001] += ' SubTotal="' + AllTrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP), 2), "99999999.99")) + '"'
(PRE) _aTotal[001] += ' Descuento="' + Alltrim(Transform(Round(nOtroDedu+nImpReten,2), "99999999.99")) + '"'
(PRE) _aTotal[001] += ' Moneda="' + Alltrim("MXN") + '"'
(PRE) _aTotal[001] += ' Total="' + AllTrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP) - (nOtroDedu + nImpReten), 2), "99999999.99")) + '"'
(PRE) _aTotal[001] += ' TipoDeComprobante="' + AllTrim("N") + '"'
(PRE) _aTotal[001] += ' MetodoPago="' + Alltrim("PUE") + '"'
(PRE) _aTotal[001] += ' LugarExpedicion="' + CFDCarEsp(AllTrim(RGC->RGC_CODPOS)) + '"'
(PRE) _aTotal[001] += '>'
(PRE) _aTotal[001] := ENCODEUTF8(_aTotal[001])
(PREREG) _aTotal[001]

//COMPROBANTE: CFDI:CfdiRelacionado
[XXX CfdiRelacionados]
(PRE) _aTotal[001] := NodoRelacc(2)
(PRE) _aTotal[001] := ENCODEUTF8(_aTotal[001])
(PREREG) _aTotal[001]

//COMPROBANTE:  CFDI:EMISOR
[XXX EMISOR]
(PRE) _aTotal[001] := '    <cfdi:Emisor'
(PRE) _aTotal[001] += ' Rfc="' + CFDCarEsp(Alltrim(SM0->M0_CGC)) + '"'
(PRE) _aTotal[001] += ' Nombre="' + _aTotal[075] + '"'
(PRE) _aTotal[001] += ' RegimenFiscal="' + cTipoReg + '"'
(PRE) _aTotal[001] += '/>'
(PRE) _aTotal[001] := ENCODEUTF8(_aTotal[001])
(PREREG) _aTotal[001]

//COMPROBANTE:  CFDI:RECEPTOR
[XXX RECEPTOR]
(PREREG) (_aTotal[001] := '    <cfdi:Receptor' , .T.)
(PREREG) (_aTotal[001] += ' Rfc="' + CFDCarEsp(AllTrim(SRA->RA_CIC)) + '"' , .T.)
(PREREG) (_aTotal[001] += ' Nombre="' + CFDCarEsp(Alltrim(SRA->RA_NOME)) + '"' , .T.)
(PREREG) (_aTotal[001] += ' UsoCFDI="' + CFDCarEsp( "P01") + '"' , .T.)
(PREREG) (_aTotal[001] += '/>' ,.T.)
(PREREG) (_aTotal[001] := ENCODEUTF8(_aTotal[001]) , .T.)
(PREREG) _aTotal[001]

//COMPROBANTE:  CFDI:COCEPTOS
[XXX CONCEPTOS]
CONCEPTOS  C 021 0 ENCODEUTF8(XMLConv("",,,"cfdi:Conceptos",.T.,.F.,4))

[XXX CONCEPTO]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

(PREREG) (_aTotal[002] := '        <cfdi:Concepto',.T.)
(PREREG) (_aTotal[002] += ' ClaveProdServ="'+AllTrim("84111505")+'"',.T.)
(PREREG) (_aTotal[002] += ' Cantidad="' + Alltrim("1") + '"',.T.)
(PREREG) (_aTotal[002] += ' ClaveUnidad="' + Alltrim("ACT") + '"',.T.)
(PREREG) (_aTotal[002] += ' Descripcion="' + DECODEUTF8(AllTrim("Pago de nómina")) + '"',.T.)
(PREREG) (_aTotal[002] += ' ValorUnitario="' + Alltrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP),2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += ' Importe="' + Alltrim(Transform(Round(nTotPGrav + nTotPExen + IIf(lRegAsimil, 0, nTotOtroP),2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += ' Descuento="' + Alltrim(Transform(Round(nTotDGrav+nTotDExen,2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += '/>',.T.)
(PREREG) (_aTotal[078] ++,.T.)
(PREREG) ENCODEUTF8(_aTotal[002])

[XXX CONCEPTOS]
CONCEPTOS  C 021 0 ENCODEUTF8(XMLConv("",,,"cfdi:Conceptos",.F.,.T.,4))

//COMPLEMENTO:  CFDI:COMPLEMENTO
[XXX COMPLEM]
COMPLEM    C 023 0 ENCODEUTF8(XMLConv("",,,"cfdi:Complemento",.T.,.F.,4))

//COMPLEMENTO:  NOMINA:NOMINA
[XXX NOMINA]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

(PRE) _aTotal[001] := '    <nomina12:Nomina'
(PRE) _aTotal[001] += ' Version="1.2"'
(PRE) _aTotal[001] += ' TipoNomina="' + IIf(SRY->RY_TIPO == "1" .And. !lImprIndem, "O", "E") + '"'
(PRE) _aTotal[001] += ' FechaPago="' + Alltrim(STR(YEAR(dFchPag)))+"-"+ STRZERO(MONTH(dFchPag),2) +"-"+STRZERO(DAY(dFchPag),2)+ '"'        
(PRE) _aTotal[001] += ' FechaInicialPago="' + Alltrim(STR(YEAR(dFchInPag)))+"-"+ STRZERO(MONTH(dFchInPag),2) +"-"+STRZERO(DAY(dFchInPag),2)+ '"'
(PRE) _aTotal[001] += ' FechaFinalPago="' + Alltrim(STR(YEAR(dFchFiPag)))+"-"+ STRZERO(MONTH(dFchFiPag),2) +"-"+STRZERO(DAY(dFchFiPag),2)+ '"'
(PRE) _aTotal[001] += ' NumDiasPagados="' + Alltrim(Str(IIf(nDiasPag == 0, 1, nDiasPag))) + '"'
(PRE) _aTotal[001] += IIf(nTotPGrav+nTotPExen <> 0, ' TotalPercepciones="' + Alltrim(Transform(Round(nTotPGrav+nTotPExen,2), "99999999.99")) + '"', "")
(PRE) _aTotal[001] += IIf(nTotDGrav+nTotDExen <> 0, ' TotalDeducciones="' + Alltrim(Transform(Round(nTotDGrav+nTotDExen,2), "99999999.99")) + '"', "")
(PRE) _aTotal[001] += IIf(nTotOtroP <> 0 .And. !lRegAsimil, ' TotalOtrosPagos="' + Alltrim(Transform(Round(nTotOtroP,2), "99999999.99")) + '" ', "")
(PRE) _aTotal[001] += '>'
(PRE) _aTotal[001] := ENCODEUTF8(_aTotal[001])
(PREREG) _aTotal[001]

[XXX EMISOR]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

(PREREG) (NodOpcion(6),.T.)
(PRE) _aTotal[001] := '        <nomina12:Emisor'
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, ' RegistroPatronal="' + Alltrim(cRegPatr) +'"', "")
(PRE) _aTotal[001] += ' RfcPatronOrigen="' + CFDCarEsp(Alltrim(SM0->M0_CGC)) +  '"'
(PREREG) (_aTotal[001] += IIf(Alltrim(cOrigRecur) == "", '/>', '>'),.T.)
(PREREG) (_aTotal[001] += IIf(Alltrim(cOrigRecur) == "", "", cCRLF + cNodoSNCF),.T.)
(PREREG) ENCODEUTF8(_aTotal[001])
(PREREG) ( Iif ((cOrigRecur <> ""),.T.,.F.))
EMISOR     C 026 0 ENCODEUTF8(XMLConv("",,,"nomina12:Emisor",.F.,.T.,8))

//COMPROBANTE:  CFDI:RECEPTOR
[XXX RECEPTOR]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

(PREREG) (NodOpcion(5),.T.)
(PRE) _aTotal[001] := '        <nomina12:Receptor'
(PRE) _aTotal[001] += ' Curp="' + Alltrim(SRA->RA_CURP) + '"'
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, ' NumSeguridadSocial="' + AllTrim(SRA->RA_RG) +'"', "")
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, ' FechaInicioRelLaboral="' + AllTrim(Str(Year(dFchInLab))) + "-" + StrZero(Month(dFchInLab),2) + "-" + StrZero(Day(dFchInLab),2) + '"', "")
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, DecodeUTF8(' Antigüedad="') + 'P' + AllTrim(Str(nAntigue)) + 'W' + '" ', "")
(PRE) _aTotal[001] += ' TipoContrato="' + Iif(lImprIndem,"99",Alltrim(SRA->RA_TIPCON)) + '"'
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A', ' Sindicalizado="' + IIf(!Empty(SRA->RA_SINDICA) .And. !lRegAsimil, "S�", "No") + '"', "")
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil, ' TipoJornada="' + AllTrim(cTipJorn) + '"', "")
(PRE) _aTotal[001] += ' TipoRegimen="' + Iif(lImprIndem,"13",Alltrim(SRA->RA_TIPREG)) + '"'
(PRE) _aTotal[001] += ' NumEmpleado="' + Alltrim(SRA->RA_MAT) +'"'
(PRE) _aTotal[001] += ' Departamento="' + Alltrim(cDeptoIm) + '"'
(PRE) _aTotal[001] += ' Puesto="' + Alltrim(cPuesCfdi) + '"'
(PRE) IIf(!lRegAsimil .AND. !lImprIndem, _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A', ' RiesgoPuesto="' + AllTrim(cRiegCFDi) + '"', ' RiesgoPuesto="' + AllTrim("99") + '"'), .T.)
(PRE) _aTotal[001] += ' PeriodicidadPago="' + CFDCarEsp(Alltrim(IIf(SRY->RY_TIPO == "1",cPerCFDi, "99"))) + '"'
(PRE) IIf(!Empty(SRA->RA_CLABE), ,_aTotal[001] += ' Banco="' + Alltrim(cBcoCfdi) + '"')
(PRE) _aTotal[001] += ' CuentaBancaria="' + IIf(!Empty(SRA->RA_CLABE), Alltrim(SRA->RA_CLABE), Alltrim(SRA->RA_CTDEPSA)) + '"'
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A', ' SalarioBaseCotApor="' + Alltrim(Transform(Round(nSalBasAp,2), "99999999.99")) + '"', "")
(PRE) _aTotal[001] += IIf(SRA->RA_CATFUNC <> 'A' .And. !lRegAsimil .And. !lImprIndem, ' SalarioDiarioIntegrado="' + Alltrim(Transform(Round(SRA->RA_SALINT,2), "99999999.99")) + '"', "")
(PRE) _aTotal[001] += ' ClaveEntFed="' + Alltrim(cEntFed) + '"'
(PREREG) (_aTotal[001] += IIf(cNodoSubC <> "", '>', '/>'),.T.)
(PREREG) (_aTotal[001] += IIf(cNodoSubC == "", "", cCRLF + cNodoSubC),.T.)
(PREREG) ENCODEUTF8(_aTotal[001])
(PREREG) ( Iif ((cNodoSubC <> ""),.T.,.F.))
RECEPTOR   C 028 0 ENCODEUTF8(XMLConv("",,,"nomina12:Receptor",.F.,.T.,8))

//COMPLEMENTO:  NOMINA:PERCEPCIONES
[XXX PERCEPCION]    
(PRE) DBSELECTAREA("SRVPD")
(PRE) SRVPD->(DbGotop())
(PREREG) ( Iif ((Alltrim(SRVPD->RV_TIPO) =="1"),.T.,.F.))
(PRE) _aTotal[002] := '        <nomina12:Percepciones'
(PRE) _aTotal[002] += IIf(nTotSueld<>0, ' TotalSueldos="' + Alltrim(Transform(Round(nTotSueld,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nTotIndem<>0, ' TotalSeparacionIndemnizacion="' + Alltrim(Transform(Round(nTotIndem,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nTotJubil<>0, ' TotalJubilacionPensionRetiro="' + Alltrim(Transform(Round(nTotJubil,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += ' TotalGravado="' + Alltrim(Transform(Round(nTotPGrav,2), "99999999.99")) + '"'
(PRE) _aTotal[002] += ' TotalExento="' + Alltrim(Transform(Round(nTotPExen,2), "99999999.99")) + '"'
(PRE) _aTotal[002] += '>'
(PRE) _aTotal[002] := ENCODEUTF8(_aTotal[002])
(PREREG) _aTotal[002]

[SRVPD PERCEPCION]
(PRE) SRVPD->(DbGotop())
(PREREG) ( Iif ((Alltrim(SRVPD->RV_TIPO) =="1"),.T.,.F.))
(PREREG) NodOpcion(1)
(PREREG) NodOpcion(2)
(PREREG) (_aTotal[002] := '            <nomina12:Percepcion',.T.)
(PREREG) (_aTotal[002] += ' TipoPercepcion="' + Alltrim(Substr(SRVPD->RV_TIPSAT,1,3)) + '"',.T.)
(PREREG) (_aTotal[002] += ' Clave="' + Alltrim(SRVPD->RV_COD) + '"',.T.)
(PREREG) (_aTotal[002] += ' Concepto="' + Alltrim(SRVPD->RV_DESCDET) + '"',.T.)
(PREREG) (_aTotal[002] += ' ImporteGravado="' + Alltrim(Transform(Round(SRVPD->RC_VALORGV,2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += ' ImporteExento="' + Alltrim(Transform(Round(SRVPD->RC_VALOREX,2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += IIf(cNodoAccT <> "" .Or. cNodoHExt <> "", '>', '/>'),.T.)
(PREREG) (_aTotal[002] += IIf(cNodoAccT == "", "", cCRLF + cNodoAccT),.T.)
(PREREG) (_aTotal[002] += IIf(cNodoHExt == "", "", cCRLF + cNodoHExt),.T.)
(PREREG) ENCODEUTF8(_aTotal[002])
(PREREG) ( Iif ((cNodoAccT <> "" .Or. cNodoHExt <> ""),.T.,.F.))
PERCEPCION C 036 0 ENCODEUTF8(XMLConv("",,,"nomina12:Percepcion",.F.,.T.,12))

[SRVPD JUBILACION]
(PREREG) Iif((nTotUnaEx+nTotParci+nTotDiari+nTotIAcum+NTotNAcum<>0),.T.,.F. )
(PRE) _aTotal[002] := '                <nomina12:JubilacionPensionRetiro'
(PRE) _aTotal[002] += IIf(nTotUnaEx <> 0, ' TotalUnaExhibicion="' + Alltrim(Transform(Round(nTotUnaEx,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nTotParci <> 0, ' TotalParcialidad="' + Alltrim(Transform(Round(nTotParci,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nTotParci <> 0, ' MontoDiario="' + Alltrim(Transform(Round(nTotDiari,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nTotUnaEx+nTotParci <> 0, ' IngresoAcumulable="' + Alltrim(Transform(Round(nTotIAcum,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nTotUnaEx+nTotParci <> 0, ' IngresoNoAcumulable="' + Alltrim(Transform(Round(NTotNAcum,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += '/>'
(PREREG) ENCODEUTF8(_aTotal[002])
(PREREG) VldNodJub()

[SRVPD INDEMNIZACION]
(PREREG) Iif((nTotPagad+nNumAnios+nUltSuelM+nIngrAcum+nIngrNAcu<>0),.T.,.F. )
(PRE) _aTotal[002] := '                <nomina12:SeparacionIndemnizacion'
(PRE) _aTotal[002] += ' TotalPagado="' + Alltrim(Transform(Round(nTotPagad,2), "99999999.99")) + '"'
(PRE) _aTotal[002] += ' NumAñosServicio="' + Alltrim(Str(IIf(nNumAnios==0, 1, nNumAnios))) + '"'
(PRE) _aTotal[002] += ' UltimoSueldoMensOrd="' + Alltrim(Transform(Round(nUltSuelM,2), "99999999.99")) + '"'
(PRE) _aTotal[002] += ' IngresoAcumulable="' + Alltrim(Transform(Round(nIngrAcum,2), "99999999.99")) + '"'
(PRE) _aTotal[002] += ' IngresoNoAcumulable="' + Alltrim(Transform(Round(nIngrNAcu,2), "99999999.99")) + '"'
(PRE) _aTotal[002] += '/>'
(PREREG) ENCODEUTF8(_aTotal[002])
(PREREG) VldNodInde()

[XXX PERCEPCION] 
(PRE) SRVPD->(DbGotop())
(PREREG) ( Iif ((Alltrim(SRVPD->RV_TIPO) =="1"),.T.,.F.))
PERCEPCION C 032 0 ENCODEUTF8(XMLConv("",,,"nomina12:Percepciones",.F.,.T.,8))

//COMPLEMENTO:  NOMINA:DEDUCCIONES
[XXX DEDUCCIONS]
(PRE) DBSELECTAREA("SRVPD")
(PRE) SRVPD->(DbGotop()) 
(PRE) DbSeek(_aTotal[072]+_aTotal[073]+"2") 
(PREREG) ( Iif ((Alltrim(SRVPD->RV_TIPO) =="2"),.T.,.F.))
(PRE) _aTotal[002] := '        <nomina12:Deducciones'
(PRE) _aTotal[002] += IIf(nOtroDedu <> 0, ' TotalOtrasDeducciones="' + Alltrim(Transform(Round(nOtroDedu,2), "99999999.99")) + '"', "")
(PRE) _aTotal[002] += IIf(nImpReten <> 0, ' TotalImpuestosRetenidos="' + Alltrim(Transform(Round(nImpReten,2), "99999999.99")) + '" ', "")
(PRE) _aTotal[002] += '>'
(PREREG) ENCODEUTF8(_aTotal[002])

[SRVPD DEDUCCION]  
(PREREG) ( Iif ((Alltrim(SRVPD->RV_TIPO) =="2"),.T.,.F.))
(PREREG) (_aTotal[002] := '            <nomina12:Deduccion',.T.)
(PREREG) (_aTotal[002] += ' TipoDeduccion="' + Alltrim(Substr(SRVPD->RV_TIPSAT,1,3)) + '"',.T.)
(PREREG) (_aTotal[002] += ' Clave="' + Alltrim(SRVPD->RV_COD) + '"',.T.)
(PREREG) (_aTotal[002] += ' Concepto="' + Alltrim(SRVPD->RV_DESCDET) + '"',.T.)
(PREREG) (_aTotal[002] += ' Importe="' + Alltrim(Transform(Round(SRVPD->RC_VALORGV + SRVPD->RC_VALOREX,2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += '/>',.T.)
(PREREG) ENCODEUTF8(_aTotal[002]) 

[XXX DEDUCCIONS] 
(PRE) DBSELECTAREA("SRVPD")
(PRE) SRVPD->(DbGotop()) 
(PRE) DbSeek(_aTotal[072]+_aTotal[073]+"2")  
(PREREG) ( Iif ((Alltrim(SRVPD->RV_TIPO) =="2"),.T.,.F.))
DEDUCCIONS C 032 0 ENCODEUTF8(XMLConv("",,,"nomina12:Deducciones",.F.,.T.,8))

//COMPLEMENTO:  NOMINA:OTROSPAGOS
[XXX OTROSPAGOS]

//Variable utilizada para validar si es Regimen Asimilado
(PRE) lRegAsimil := SRA->RA_TIPREG $ "05|06|07|08|09|10|11"

(PREREG) !lRegAsimil
(PREREG) _aTotal[002] := ''
(PREREG) _aTotal[002] := fOtrosPag()
(PREREG) ENCODEUTF8(_aTotal[002])

[XXX INCAPACIDS] 
(PRE) SRCIN->(DbGotop()) 
(PREREG) Iif(!SRCIN->(Eof()),.T.,.F. )
(PRE) _aTotal[001] := '        <nomina12:Incapacidades>'
(PREREG) ENCODEUTF8(_aTotal[001])

//COMPLEMENTO:  NOMINA:INCAPACIDAD
[SRCIN INCAPACIDAD]
(PRE) SRCIN->(DbGotop())
(PREREG) (_aTotal[002] := '            <nomina12:Incapacidad',.T.)
(PREREG) (_aTotal[002] += ' DiasIncapacidad="' + Alltrim(Str(SRCIN->RC_HORAS)) + '"',.T.)
(PREREG) (_aTotal[002] += ' TipoIncapacidad="' + Alltrim(SRCIN->RCM_TIPSAT) + '"',.T.)
(PREREG) (_aTotal[002] += ' ImporteMonetario="' + Alltrim(Transform(Round(SRCIN->RC_VALOR,2), "99999999.99")) + '"',.T.)
(PREREG) (_aTotal[002] += '/>',.T.)
(PREREG) ENCODEUTF8(_aTotal[002])

[XXX INCAPACIDAD]  
(PRE) SRCIN->(DbGotop()) 
(PREREG) Iif(!SRCIN->(Eof()),.T.,.F. )
INCAPACIDAD C 030 0 ENCODEUTF8(XMLConv("",,,"nomina12:Incapacidad",.F.,.T.,8))

[XXX INCAPACIDS] 
(PRE) SRCIN->(DbGotop()) 
(PREREG) Iif(!SRCIN->(Eof()),.T.,.F. )
INCAPACIDS C 033 0 ENCODEUTF8(XMLConv("",,,"nomina12:Incapacidades",.F.,.T.,8))

[XXX NOMINA]  
NOMINA     C 023 0 ENCODEUTF8(XMLConv("",,,"nomina12:Nomina",.F.,.T.,4))

//COMPLEMENTO:  CFDI:COMPLEMENTO
[XXX COMPLEM]  
COMPLEM    C 023 0 ENCODEUTF8(XMLConv("",,,"cfdi:Complemento",.F.,.T.,4))  

[XXX ADDENDA]
ADDENDA    C 019 0 ENCODEUTF8(XMLConv("",,,"cfdi:Addenda",.T.,.F.,4))

[XXX ADDENDA1]
(PREREG) (_aTotal[003] := '        <cfdi:t_obs',.T.)
(PREREG) (_aTotal[003] += ' CadenaOrig="' + Alltrim(_aTotal[074]) + '"',.T.)
(PREREG) (_aTotal[003] += ' Sucursal="' + SRA->RA_FILIAL + '"',.T.)
(PREREG) (_aTotal[003] += '/>',.T.)
(PREREG) _aTotal[003]
(POS) DelATbr884()

[XXX ADDENDA]
ADDENDA    C 019 0 ENCODEUTF8(XMLConv("",,,"cfdi:Addenda",.F.,.T.,4))

[XXX CFDI]
CFDI       C 019 0 ENCODEUTF8(XMLConv("",,,"cfdi:Comprobante",.F.,.T.,0))

08. Tablas Utilizadas

09. Preguntas Frecuentes

¿Es posible cancelar recibos generados en versión 3.3 del CFDI?

Si, aunque el nuevo Esquema de Cancelación entró en vigor a partir del 01 de enero del 2022; el SAT extendió el periodo de ambas versiones hasta el 30 de junio de 2022, dando como resultado un periodo de convivencia para ambas versiones. A partir del 1 de julio de 2022, solo estará vigente la versión 4.0 del CFDI.

¿Cuáles son los nuevos códigos de respuesta del CFDI?

CódigoDescripción de la Respuesta
201UUID Solicitud Recibida.
202

UUID Previamente Cancelado.

203UUID No encontrado o no corresponde con el emisor.
204UUID No aplicable para cancelación.
205UUID No existe.
206UUID No corresponde a un CFDI del sector primario.

¿Qué debo tomar en cuenta para cancelar un CFDI?

Los contribuyentes solo podrán cancelar un CFDI en el mismo periodo de ejercicio en que se haya emitido.

10. Errores comunes

A continuación, se enlistan los errores comunes al realizar la cancelación o timbrado de recibos de nómina:

Código de errorValidaciónDescripción del error

CFDI90000

El folio sustitución del uuid (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) es requerido.Error originado al intentar cancelar un recibo con el motivo "01" y dicho recibo, no tiene un recibo que lo sustituya.

11. Información Adicional

Documento de Referencia para CFDI 3.3:

DT Recibo de Nómina CFDI 3.3 - México

Documento Técnico de Cancelación de CFDI por Reforma Fiscal 2022:

13481039 DNOMI-47 DT Cancelación CFDI de Nómina con Motivos de Cancelación MEX