Automatiza la factura global dentro del plazo de 24 horas del SAT: el job diario que los blogs de los PAC no te enseñan — Cesar Ayala
← Todos los artículos

Automatiza la factura global dentro del plazo de 24 horas del SAT: el job diario que los blogs de los PAC no te enseñan

Cuando vendes a público en general (retail, e-commerce, efectivo) y nadie pide factura individual, no emites un CFDI por venta: las agregas en un CFDI global bajo la regla 2.7.1.21 RMF 2026, timbrado dentro de 24 horas del cierre del periodo. Arma un job diario: jala las ventas de público, excluye las ya facturadas, ensambla el CFDI 4.0 (RFC XAXX010101000), tímbralo en tu PAC, guarda el UUID y alerta si falla. Hazlo idempotente. RESICO solo emite mensual. Soy ingeniero, no contador.

La realidad operativa: si se te va la ventana de 24 horas, estás en incumplimiento

Si vendes a público en general —retail, e-commerce, OXXO, efectivo— tienes ventas apilándose todos los días de clientes que nunca te pidieron factura. Para el SAT no emites un CFDI por cada una de esas ventas: las agregas en una sola factura global. Y aquí viene el detalle que casi nadie te dice como ingeniero: ese comprobante global tiene que llegar al SAT, vía tu PAC, dentro de las 24 horas siguientes al cierre de las operaciones del periodo.

Eso cambia por completo cómo lo modelas. No es una tarea manual que haces cuando te acuerdas el lunes. Es un job programado que corre solo, que no puede fallar en silencio y que no puede emitir dos veces lo mismo. La regla 2.7.1.21 de la RMF 2026 es la que gobierna esto: un solo comprobante global para las operaciones de público en general del periodo, separando el IVA y el IEPS.

Lo veo como problema de confiabilidad, no de teoría fiscal. Tienes volumen diario, una ventana dura de 24 horas y necesitas idempotencia. Es exactamente el tipo de cosa que un proceso manual deja caer justo el día que estás más ocupado. Los blogs de marketing de los PAC te explican qué campos lleva el XML; lo que no te enseñan es a construir el job que lo timbra a tiempo, todos los días, sin duplicar.

Aclaro algo desde el arranque: soy ingeniero, no contador. Los umbrales exactos, las reglas de tu régimen y la decisión de cadencia (diario vs mensual) son territorio del SAT y de tu contador. Confirma las reglas vigentes antes de meter cualquier número al código. Lo que yo te puedo dar es el job confiable. Esto vive dentro del hub de CFDI y facturación junto con el resto del pipeline.

Para quiénPúblico en general (no pidió factura)
ReceptorXAXX010101000 / PUBLICO EN GENERAL
Régimen / Uso616 (Sin obligaciones) / S01 (Sin efectos)
CadenciaDiaria / semanal / mensual / bimestral
PlazoTimbrar dentro de 24h del cierre
DesgloseIVA + IEPS separados
RESICOSolo mensual

¿El plazo de 24 horas es nuevo para 2026? No, y aquí va la historia honesta

Vas a ver muchos artículos que venden el plazo de 24 horas como una urgencia de 2026, como si fuera una noticia. No lo es. El plazo de 24 horas es real y vigente bajo la regla 2.7.1.21 de la RMF 2026, pero no es un cambio de 2026.

El recorte de 72 horas a 24 horas pasó allá por 2022. La RMF 2026 simplemente carga la misma regla hacia adelante. No hay nada que correr a implementar de último momento por “novedad fiscal”.

Lo cual te debería dar más tranquilidad, no menos: trátalo como una obligación operativa permanente. Si vendes a público en general, esto ya debería estar automatizado en tu sistema. No es un evento, es una rutina.

Dicho esto, trata todas las reglas del SAT como sensibles al tiempo. Como en 2026, confirma contra las fuentes primarias —la Guía de llenado del CFDI global 4.0 y el propio SAT— antes de hardcodear un plazo o una clave de catálogo. Lo que era cierto el año pasado pudo cambiar.

CFDI por venta vs factura global: cuándo aplica cada uno

Toda la lógica del job depende de entender bien esta frontera, así que vamos despacio.

El CFDI individual lo emites cuando un cliente te pide factura: te da su RFC y sus datos fiscales, y tú emites un CFDI por esa venta específica. Ese caso lo cubre el job de facturación CFDI automática por venta.

La factura global es un solo comprobante agregado que cubre todas las operaciones de público en general del periodo donde nadie pidió factura individual.

Lo clave: las dos son mutuamente excluyentes por venta. Una venta que ya recibió su CFDI individual no debe volver a caer en el global, porque estarías duplicando el ingreso. Esa exclusión es justo lo que tu lógica de deduplicación va a aplicar más adelante.

¿Por qué el global específicamente necesita un job confiable y programado? Porque es recurrente, está acotado en el tiempo (24h) y agrega un conjunto de ventas que se mueve todos los días. La emisión manual no escala y se rompe justo los días pesados. El global puede emitirse diario, semanal, mensual o bimestral, pero la ventana de 24h después del cierre aplica al periodo que elijas.

CFDI individual

  • Lo pide el cliente con su RFC
  • Un comprobante por esa venta
  • Datos fiscales reales del receptor
  • Se emite en el momento de la venta

Factura global

  • Público en general, nadie pidió factura
  • UN comprobante agregado del periodo
  • Receptor XAXX010101000
  • Requiere un job programado e idempotente

Los campos que hacen válido un CFDI global (RFC XAXX, Régimen 616, Uso S01)

Aquí están los datos que cargan el peso. Estos son los que tu código va a ensamblar en el bloque del receptor.

  • Formato: CFDI 4.0.
  • RFC del receptor: XAXX010101000.
  • Nombre del receptor: PUBLICO EN GENERAL (deja el valor legal en mayúsculas y sin acentos).
  • Régimen Fiscal del receptor: 616 (Sin obligaciones fiscales).
  • UsoCFDI: S01 (Sin efectos fiscales).
  • DomicilioFiscalReceptor: el código postal del EMISOR (tu CP, no el del cliente). Este es el que más confunde.
  • Debes desglosar (separar) los montos de IVA y de IEPS en el comprobante.

Un ejemplo ilustrativo del bloque del receptor, para que veas la forma. Confirma los valores de catálogo contra la Guía de llenado antes de construirlo:

<!-- Ilustrativo. CFDI 4.0 global. Confirmar contra la Guía de llenado del CFDI global 4.0. -->
<!-- RegimenFiscalReceptor = régimen del RECEPTOR (616), distinto del RegimenFiscal del emisor. -->
<cfdi:Receptor
  Rfc="XAXX010101000"
  Nombre="PUBLICO EN GENERAL"
  DomicilioFiscalReceptor="72000"
  RegimenFiscalReceptor="616"
  UsoCFDI="S01" />

Repito porque importa: confirma los valores exactos de catálogo y la ubicación de cada campo contra la Guía de llenado del CFDI global 4.0. Las claves y reglas cambian, y un valor viejo te rebota el timbrado.

El job diario, de punta a punta: cierre → excluir → ensamblar → timbrar → guardar → alertar

Aquí está la parte que los tutoriales de los PAC se saltan: la arquitectura. Modela el job como un pipeline de etapas, cada una con su modo de falla.

Etapa 1 — Jalar. Al cierre del periodo, jala todas las ventas de público en general del periodo desde tu sistema (tu tabla de órdenes o de pagos).

Etapa 2 — Excluir. Quita las ventas que ya se facturaron individualmente (para no duplicar el ingreso) y cualquier ticket que, por estar bajo umbral, no se haya solicitado. Confirma el umbral y las reglas vigentes con tu contador.

Etapa 3 — Ensamblar. Construye el CFDI 4.0 global: el bloque del receptor XAXX010101000 (PUBLICO EN GENERAL / 616 / S01 / CP del emisor) más los montos agregados como conceptos, con IVA e IEPS desglosados.

Etapa 4 — Timbrar. Tímbralo en tu PAC, dentro de la ventana de 24h.

Etapa 5 — Guardar y conciliar. Persiste el UUID y un enlace de regreso a las ventas que lo componen, para poder auditar y probar qué ventas cubre el global.

Etapa 6 — Alertar. Si cualquier etapa falla, alerta fuerte. El punto entero es no quemar la ventana de 24h en silencio.

# Ilustrativo. El llamado de timbrado al PAC es específico de cada proveedor.
def emitir_global_del_periodo(periodo):
    # Idempotencia: si ya hay un global timbrado para este periodo, no-op.
    if existe_global_timbrado(periodo):
        return

    ventas = pull_ventas_publico_general(periodo)
    ventas = excluir_ya_facturadas(ventas)        # no duplicar ingreso
    ventas = excluir_no_solicitadas_bajo_umbral(ventas)  # confirmar con contador

    cfdi = ensamblar_cfdi_global_40(
        receptor_rfc="XAXX010101000",
        receptor_nombre="PUBLICO EN GENERAL",
        regimen_receptor="616",
        uso_cfdi="S01",
        cp_emisor=CP_EMISOR,
        conceptos=agregar_conceptos(ventas),   # IVA / IEPS desglosado
    )

    # Checkpoint: persiste el comprobante ensamblado en estado "pendiente de timbre"
    # ANTES de llamar al PAC. Si el timbrado falla, el retry retoma este CFDI
    # ya armado en lugar de reensamblar desde cero (falla parcial segura).
    guardar_pendiente_de_timbre(periodo, cfdi)

    uuid = pac.timbrar(cfdi)                    # dentro de las 24h del cierre
    guardar_uuid_y_enlace(periodo, uuid, ventas)

El código que muestro es ilustrativo. La llamada de timbrado al PAC es específica de cada proveedor, y los conceptos exactos los marca tu contador.

CierreCierra las ventas de público en general del periodo
ExcluirQuita las ya facturadas y las no solicitadas
EnsamblarCFDI 4.0 global, receptor XAXX, IVA/IEPS desglosado
TimbrarEn el PAC, dentro de 24h del cierre
Guardar + alertarPersiste el UUID y grita si falla

Idempotencia: por qué un re-run nunca debe emitir un segundo global

Esta es la propiedad de corrección más importante de todo el job, y la que ningún tutorial de PAC cubre.

Un re-run —un retry, un disparo manual, dos crons que se traslapan— no debe emitir un segundo global para el mismo periodo. Eso crea ingreso duplicado y un desorden fiscal que después alguien tiene que limpiar a mano.

La regla es simple: usa el periodo como llave de idempotencia. Antes de ensamblar, revisa si ya existe un global timbrado para esa llave de periodo exacta. Si ya existe, no-op. Guarda el UUID contra el periodo como tu registro de idempotencia: la presencia de un UUID almacenado es tu guardia de “esto ya se hizo”.

Dos detalles más que separan el job que funciona del que da problemas:

  • Haz que el pull y la exclusión sean deterministas. Un retry sobre el mismo periodo debe producir el mismo conjunto de ventas, no uno distinto porque algo cambió en el medio.
  • Maneja la falla parcial. El caso feo es: ensamblaste el comprobante pero el timbrado en el PAC falló. Quieres un retry seguro que retome donde se quedó, no uno que vuelva a emitir desde cero. Por eso persistes el estado entre el ensamblado y el timbrado —ese checkpoint “pendiente de timbre” del código— para que el retry retome el comprobante ya armado.

Este patrón de idempotencia por periodo es el mismo que aplica al REP, el otro job de CFDI con fecha límite: trabajos recurrentes, acotados en el tiempo, que no toleran duplicados.

  1. Programa el jobCron diario al cierre del periodo (cadencia configurable)
  2. Jala las ventasPúblico en general del periodo desde tu sistema
  3. DeduplicaExcluye las ya facturadas y las no solicitadas
  4. Ensambla el globalCFDI 4.0, receptor XAXX, IVA/IEPS desglosado
  5. Timbra en 24hEn el PAC, dentro de la ventana del cierre
  6. Guarda + concilia + alertaUUID enlazado a las ventas, idempotente por periodo

RESICO y los casos límite que le regreso a un contador

Hay una excepción que tienes que respetar en código: los contribuyentes en RESICO solo pueden emitir el CFDI global de forma MENSUAL (el total del periodo), no diario ni semanal.

Por eso la cadencia del job debe ser configurable. No hardcodees “diario”. Deja que la decisión del régimen y del contador maneje la frecuencia. Un flag de cadencia que sea diario, semanal o mensual te ahorra reescribir el job cuando cambia el régimen del cliente.

Soy ingeniero, no contador, y aquí dibujo la línea con claridad. Los umbrales exactos, la elección diario-vs-mensual, las reglas de los tickets bajo umbral o no solicitados, y las obligaciones de tu régimen son territorio del SAT y del contador.

Lo que yo tengo como ingeniero: el job confiable, a tiempo e idempotente, y el rastro de auditoría (el UUID enlazado a las ventas). Lo que tiene el contador: qué ventas cuentan, qué cadencia, qué umbrales. Trata cada valor de catálogo y cada umbral como “confirmar vigente” contra el SAT antes de lanzar.

Y ojo: esto convive con otras obligaciones del mismo builder. El lado del Egreso lo cubren los CFDI de egreso para reembolsos y notas de crédito, y si operas un marketplace, también te tocan las retenciones de plataformas digitales. Mismo perfil de ingeniero, mismas fechas límite del SAT.

Preguntas frecuentes: factura global, la ventana de 24h y el doble conteo

¿Qué RFC y datos van en el receptor? RFC XAXX010101000, nombre PUBLICO EN GENERAL, Régimen 616, Uso S01, y DomicilioFiscalReceptor igual al código postal del emisor.

¿Cuánto tiempo tengo para timbrarla? Dentro de las 24 horas siguientes al cierre de las operaciones del periodo (regla 2.7.1.21 RMF 2026).

¿El plazo de 24h es nuevo para 2026? No. Bajó de 72h a 24h en 2022; la RMF 2026 solo lo carga hacia adelante.

¿Cómo evito el doble conteo del ingreso? Excluye cualquier venta que ya recibió un CFDI individual antes de agregar, y guarda el enlace UUID a ventas para poder probarlo.

Estoy en RESICO, ¿puedo correrlo diario? No. En RESICO el global se emite solo mensual.

¿Puedo emitir semanal en lugar de diario? Sí, la regla permite diario, semanal, mensual o bimestral (RESICO es la excepción), pero confirma la cadencia con tu contador. Para los detalles de llenado del XML hay guías como la de Alegra sobre cómo emitir la factura global CFDI 4.0 —úsala solo como referencia de armado, no para el plazo. El plazo vigente es de 24h por la regla 2.7.1.21 de la RMF; confírmalo contra la Guía de llenado del SAT, no contra blogs de PAC, que a veces traen el viejo dato de 72h.

Lanza el job, no el heroísmo

El valor no está en saberte los campos de memoria. Está en el job que corre cada periodo, a tiempo, de forma idempotente, y que grita cuando falla.

Constrúyelo una vez: programado, deduplicado, timbrado, guardado, alertando. A partir de ahí deja de ser un plazo que se te puede ir y se vuelve una rutina que el sistema sostiene solo.

Y antes de lanzar, confirma los detalles fiscales —umbrales, cadencia, régimen— con tu contador y contra la Guía de llenado vigente del SAT. Tú pones el job confiable; el contador pone las reglas. Esa división de trabajo es la que hace que no vuelvas a perder la ventana de 24 horas.