Saltar al contenido
Hugo Méndez
  • CFDI
  • SAT
  • Python
  • Automatización

Cómo automatizar la conciliación de CFDI contra tu ERP y validar la lista 69-B del SAT

Guía para automatizar la conciliación de facturas CFDI emitidas y recibidas contra tu sistema contable o ERP, y validar proveedores en las listas 69 y 69-B del SAT con Python.

Hugo Méndez21 de julio de 20263 min de lectura

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

  1. 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.
  2. Obtener lo que dice el SAT. Los XML de CFDI emitidos y recibidos del periodo (o sus metadatos).
  3. Cruzar por UUID y comparar importes, fechas y estatus.
  4. 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:

  1. Descargar los listados vigentes de forma programada.
  2. Normalizar los RFC y guardarlos en una tabla.
  3. Cruzar tu catálogo de proveedores (y los emisores de tus CFDI recibidos) contra esa tabla.
  4. 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.

Volver al blog

Servicios relacionados

¿Tienes un proceso que ya no aguanta más Excel?

Cuéntame qué necesitas. En menos de 24 horas hábiles te respondo con una idea clara de cómo resolverlo y cuánto cuesta.