Cada cierre de mes, muchas áreas de contabilidad hacen lo mismo: descargan los XML del SAT, exportan lo registrado en el ERP y cruzan todo en Excel buscando diferencias. Con varios RFC y miles de comprobantes, eso son días de trabajo repetitivo y un riesgo alto de que algo se escape.
La buena noticia es que ese proceso se puede automatizar casi por completo. Aquí te explico cómo lo abordo.
El proceso, en 4 pasos
- Obtener lo que dice el ERP. Facturas emitidas, notas de crédito y facturas de proveedores registradas en el periodo, con su UUID, RFC, fecha y montos.
- Obtener lo que dice el SAT. Los XML de CFDI emitidos y recibidos del periodo (o sus metadatos).
- Cruzar por UUID y comparar importes, fechas y estatus.
- Reportar las diferencias en un formato que contabilidad pueda revisar o importar a su plataforma fiscal.
Paso 1: sacar los datos del ERP
Según tu sistema, el camino puede ser una API (SAP Business One, Odoo, Dynamics), una consulta a la base de datos, un reporte programado o una exportación. Lo que necesitas por cada comprobante: UUID, RFC, fecha, tipo y montos. Lo importante es que el UUID del CFDI esté registrado en el ERP; si no lo está, ese es el primer problema a resolver.
Paso 2: leer los XML de CFDI 4.0
Un CFDI es un XML con un nodo Comprobante y un complemento TimbreFiscalDigital que contiene el UUID. Con Python y la librería estándar se lee así:
import xml.etree.ElementTree as ET
from pathlib import Path
NS = {
'cfdi': 'http://www.sat.gob.mx/cfd/4',
'tfd': 'http://www.sat.gob.mx/TimbreFiscalDigital',
}
def leer_cfdi(ruta: Path) -> dict:
root = ET.parse(ruta).getroot()
emisor = root.find('cfdi:Emisor', NS)
receptor = root.find('cfdi:Receptor', NS)
timbre = root.find('cfdi:Complemento/tfd:TimbreFiscalDigital', NS)
return {
'uuid': timbre.get('UUID').upper(),
'fecha': root.get('Fecha'),
'tipo': root.get('TipoDeComprobante'), # I, E, P, N, T
'rfc_emisor': emisor.get('Rfc'),
'rfc_receptor': receptor.get('Rfc'),
'subtotal': float(root.get('SubTotal')),
'total': float(root.get('Total')),
'moneda': root.get('Moneda'),
}
cfdis = [leer_cfdi(p) for p in Path('xml/2026-09').glob('*.xml')]
El campo TipoDeComprobante te permite separar ingresos (I), egresos o notas de crédito (E), pagos (P) y nómina (N).
Paso 3: conciliar
Con ambos lados en tablas, la conciliación es un cruce por UUID:
import pandas as pd
sat = pd.DataFrame(cfdis)
erp = pd.read_csv('erp_facturas_2026-09.csv') # columnas: uuid, total, fecha, rfc
erp['uuid'] = erp['uuid'].str.upper().str.strip()
cruce = sat.merge(erp, on='uuid', how='outer', suffixes=('_sat', '_erp'), indicator=True)
solo_sat = cruce[cruce['_merge'] == 'left_only'] # timbrado pero no registrado
solo_erp = cruce[cruce['_merge'] == 'right_only'] # registrado sin CFDI válido
dif_monto = cruce[(cruce['_merge'] == 'both') &
((cruce['total_sat'] - cruce['total_erp']).abs() > 0.01)]
Con eso ya tienes las tres listas que contabilidad necesita revisar: lo que falta registrar, lo que falta timbrar (o está cancelado) y lo que no cuadra.
Paso 4: validar proveedores contra las listas del SAT
El SAT publica listados de contribuyentes con situaciones especiales:
- Artículo 69 del CFF: contribuyentes con créditos fiscales firmes, no localizados, sentencias condenatorias, entre otros supuestos.
- Artículo 69-B del CFF: contribuyentes que presuntamente emitieron comprobantes sin sustento en operaciones reales (las llamadas “EFOS”), con estatus como presunto, desvirtuado, definitivo o sentencia favorable.
Los listados se publican como archivos descargables en el portal del SAT y se actualizan periódicamente. La automatización consiste en:
- Descargar los listados vigentes de forma programada.
- Normalizar los RFC y guardarlos en una tabla.
- Cruzar tu catálogo de proveedores (y los emisores de tus CFDI recibidos) contra esa tabla.
- Alertar cuando un proveedor aparece o cambia de estatus, antes de pagarle o deducir sus facturas.
Si un proveedor aparece como definitivo en el 69-B, los comprobantes que emitió no producen efectos fiscales. Detectarlo a tiempo evita problemas serios; la decisión de qué hacer siempre debe tomarla tu contador o asesor fiscal.
Lo que ganas al automatizarlo
- El cruce corre solo cada periodo y por cada RFC.
- Contabilidad deja de armar archivos y se dedica a analizar diferencias.
- Tienes un historial de cada conciliación para auditorías.
- Las alertas de proveedores llegan cuando todavía puedes actuar.
Si tu equipo pierde días en esto cada mes, platiquemos.