La factura parece bien leída. ¿Podemos importarla?
Una oficina pequeña recibe facturas de distintos proveedores. Copiar importes y partidas al sistema exige atención; un asistente de IA promete datos listos para usar. Pero una tabla ordenada no completa el trabajo: un total plausible puede pertenecer a otro documento, una partida puede desaparecer y el proveedor puede confundirse con el destinatario. Este artículo ayuda a quienes gestionan administración o automatización documental a decidir qué comprobaciones interponer entre lectura automática y registro. La pregunta es concreta: ¿qué demuestran los controles numéricos y qué no pueden demostrar?
La respuesta anticipada es que la coherencia aritmética detecta parte de los errores, pero no demuestra fidelidad al documento. Lo mostramos con doce registros sintéticos, un validador ejecutado y una simulación temporal. No ejecutamos OCR, consultamos un modelo, procesamos facturas reales ni medimos a operadores. Los resultados pertenecen al ejemplo declarado, no estiman la fiabilidad de ningún producto ni constituyen validación fiscal. La aportación es un método verificable para diseñar la transferencia al sistema de gestión.
Primera decisión: ¿hace falta leer una página?
Si llega un archivo estructurado utilizable, con campos identificados y formato compatible, conviene comparar un importador determinista con la vía de IA. Determinista significa que reglas explícitas transforman las mismas entradas del mismo modo, sin pedir a un modelo que adivine dónde está el total. No significa que el archivo sea verdadero o carezca de errores: siguen siendo necesarias identidad, autorización y conciliación. Significa evitar reconstrucción visual cuando la información ya está estructurada. Hay que evaluar esta alternativa antes de comprar reconocimiento de imágenes.
Para escaneos y PDF no estructurados hay tres trabajos. El OCR, reconocimiento óptico de caracteres, intenta leer signos y palabras. La extracción asigna esas palabras a campos como proveedor e importe. La validación comprueba restricciones y correspondencia con la fuente. Un número puede transcribirse correctamente y asignarse al campo equivocado. Separar las fases permite diagnosticar errores: cambiar de modelo no corrige automáticamente una regla que interpreta mal la coma decimal.
Un ejemplo reconstruible de principio a fin
El documento ideal tiene dos partidas netas de 120 y 80 euros, neto de 200 euros, impuesto declarado de 40 euros, total de 240 euros, proveedor SUP-A y moneda EUR. Son datos inventados para el experimento. No calculamos el impuesto desde una tasa ni recomendamos tratamiento tributario. Excluimos descuentos y cargos de documento, anticipos, redondeos especiales, otras monedas y notas de crédito. El alcance explica la lógica, no reduce un proceso real a cuatro números. Un documento fuera de alcance debe marcarse, no forzarse al esquema.
El código guarda importes como céntimos enteros: 120 euros pasa a ser 12000. Las sumas son exactas sin tolerancias arbitrarias para coma flotante binaria. Esto no permite redondear silenciosamente cada precio a dos decimales: precios unitarios, cantidades y redondeos pueden exigir otras reglas. Aquí las partidas ya son importes netos finales en céntimos. Un sistema completo conserva el valor original y aplica una política decimal explícita. La documentación de Decimal de Python distingue representación y redondeo.
Que los números cuadren: necesario pero insuficiente
¿Qué pregunta resuelve la fórmula? Si las partidas extraídas cubren el documento y están bien asignadas, su suma debe igualar el neto; neto e impuesto deben reconstruir el total. l_i es el importe de la partida i, N el neto, T el impuesto y G el total. Todos son céntimos; m es el número de partidas, sin unidad. No pedimos a la IA que se juzgue: aplicamos restricciones externas explícitas.
Inicialmente 12000 + 8000 = 20000 y 20000 + 4000 = 24000: los residuos son cero. Si la extracción cambia solo G a 25000, el segundo residuo vale 1000 céntimos, diez euros. Los campos no pueden ser todos correctos bajo los supuestos declarados, pero no sabemos cuál corregir. Cambiar automáticamente el total borra evidencia y podría alterar un total bien leído cuando el impuesto es erróneo. El residuo exige revisar la fuente, no corregir una columna concreta.
Peppol BR-CO-10 y BR-CO-15 documentan relaciones entre sumas de partidas y totales. El validador usa su lógica aritmética en un subconjunto simplificado: no implementa estándar, XML, todas las reglas ni redondeos. El total con impuestos no siempre coincide con el saldo pendiente. Un validador real necesita una familia documental y reglas aplicables: este ejemplo no demuestra conformidad con Peppol ni con la facturación italiana.
Todas las sumas son correctas, el registro es erróneo
Construyamos un error que ninguna ecuación detecta. El extractor devuelve partidas de 132 y 88 euros, neto 220, impuesto 44 y total 264: cada importe se multiplica por 1,1. Las sumas cuadran, pero no coinciden con la fuente de 240 euros. El contraejemplo refuta «si los totales cuadran, podemos importar». No hace falta estimar la frecuencia para mostrar que la implicación es falsa. La frecuencia real sí requiere datos representativos y etiquetas fiables.
Un segundo caso mantiene los importes y cambia SUP-A por SUP-B. El control sigue aprobando. Número documental, fecha y pedido tienen el mismo límite: las restricciones no protegen campos que no examinan. Comprobar el maestro detecta códigos inexistentes, pero no distingue dos proveedores existentes. Hace falta conciliar identidad y documento, conservando página y recorte de origen del campo. Cada control cubre un error concreto; un nombre tranquilizador no lo vuelve universal.
Doce casos para comprobar una política de importación
El conjunto contiene seis copias correctas del registro base, C1–C6, y seis erróneas, E1–E6. E1 cambia solo el total, E2 el neto y E3 el impuesto: incumplen al menos una suma. E4 es la transformación coherente descrita; E5 y E6 cambian solo el proveedor. Son casos diseñados para poner a prueba el control, no una muestra aleatoria de facturas empresariales. Que la mitad sean erróneos es didáctico, no una estimación real. No hay semilla: los datos son deterministas e íntegros en el código.
Asignamos puntuaciones sintéticas. C1–C6 reciben 0,99; 0,97; 0,94; 0,85; 0,98 y 0,92. E1–E6 reciben 0,99; 0,98; 0,96; 0,99; 0,97 y 0,90. No son salidas de un modelo ni probabilidades calibradas. Permiten probar la práctica de aceptar datos si pasan controles y el sistema parece suficientemente seguro. El umbral 0,95 es un parámetro didáctico, no una recomendación de producción.
Formalizamos la decisión para contarla. V_i vale uno si el registro i supera controles y cero en otro caso; s_i es puntuación y tau umbral. A_i indica aceptación simulada. Y_i vale uno solo si todos los campos coinciden con la referencia, conocida en el experimento pero no durante el uso. V e Y son distintos: V se observa sin conocer la respuesta; Y necesita verdad independiente. La fórmula separa cuánto automatizamos de cuántos errores dejamos pasar.
Con umbral 0,95 se aceptan C1, C2, C5, E4 y E5: cinco registros. Siete pasan a revisión. Cobertura 5/12, aproximadamente 41,7%; dos de cinco aceptados son erróneos, un 40%. El segundo porcentaje no divide entre doce: mide riesgo en el subconjunto que evita revisión. Si nada se acepta, el riesgo condicional es indefinido, no cero, porque ese subconjunto no existe: el código registra None. No importar nada no equivale a importar correctamente.
| Umbral | Aceptados | Revisión | Errores aceptados | Riesgo aceptados |
|---|---|---|---|---|
| 0 | 9 | 3 | 3 | 33.3% |
| 0.9 | 8 | 4 | 3 | 37.5% |
| 0.95 | 5 | 7 | 2 | 40.0% |
| 0.98 | 3 | 9 | 1 | 33.3% |
| 1.01 | 0 | 12 | 0 | — |
La tabla compara cinco umbrales en el mismo conjunto. Subirlos no elimina necesariamente los errores más graves: E4, coherente pero distinto de la fuente, puntúa 0,99. El error condicional puede subir al bajar la cobertura, al excluir registros correctos con menor puntuación. No demuestra que los umbrales sean inútiles: muestra por qué hay que verificar su relación con los errores en el dominio de destino. Un número no es probabilidad solo por estar entre cero y uno.
El ahorro se mide después de las correcciones
Supongamos dos minutos para registrar manualmente un documento, diez segundos de trabajo activo para iniciar cada extracción, un minuto para revisar cada documento derivado y cinco minutos para reparar cada error aceptado. No son tiempos medidos. Revisar incluye corregir y registrar los casos derivados; los cinco minutos son trabajo posterior solo en errores escapados. Suponemos revisión perfecta y descubrimiento posterior de todos los errores aceptados. Ambas hipótesis pueden fallar: el modelo temporal no garantiza calidad.
Para saber si se reduce trabajo, sumamos actividades ocultas. n es el número de documentos, a los aceptados automáticamente y e los erróneos entre ellos. t_0, t_r, t_e y t_m son segundos de inicio, revisión, reparación y registro manual. W es trabajo activo total. No calculamos espera ni duración de servicio: el paralelismo puede reducir tiempo transcurrido sin reducir atención humana, y viceversa. La última desigualdad indica cuánto retrabajo cabe antes de perder la ventaja.
Con umbral 0,95 el trabajo inicial es 12×10 + 7×60 = 540 segundos, nueve minutos, menos que veinticuatro minutos manuales. Pero dos errores añaden 2×300 = 600 segundos: total 1140 segundos, diecinueve minutos. Quedan cinco minutos de ventaja hipotética. Si cada reparación exigiera más de 450 segundos, desaparecería; con 450 ambas vías empatan. Son cálculos bajo supuestos, no promesas de ahorro. Faltan software, puesta en marcha, conservación, consecuencias del error y controles posteriores; hay que añadirlos sin contar actividades dos veces.

A la izquierda hay que observar aceptaciones y errores conjuntamente, no solo la barra más alta. A la derecha, comparar trabajo antes y después de reparaciones y referencia manual. El umbral 1,01 excluye todos los registros: el modelo da catorce minutos, dos de inicio y doce de revisión supuesta más rápida que el registro manual. Esa ventaja no demuestra mérito de la IA: nace de suponer un minuto para revisar datos propuestos. Hay que medir esa diferencia antes de justificar la inversión.
Qué mide la investigación y qué medir en la oficina
DocILE, de Šimsa y colaboradores, arXiv v2 del 3 de mayo de 2023, separa localización y agrupación por partidas. Sus métricas principales no equivalen a corrección del registro. Incluye diseños no vistos en entrenamiento. Es referencia metodológica histórica, no clasificación actual. No reproducimos sus modelos ni resultados.
El proceso real necesita evaluación propia. Fijar documentos autorizados, definir una referencia verificable y separar desarrollo y evaluación por proveedor, diseño y periodo evita probar solo formularios usados para elegir reglas. Exactitud de campos, correspondencia de partidas, documentos totalmente correctos, cobertura y errores aceptados responden preguntas distintas. Diez campos correctos de once pueden dejar un documento inutilizable si el undécimo identifica al destinatario del pago. No debe inferirse corrección documental multiplicando exactitudes sin justificar independencia de errores.
Los tiempos merecen igual atención. Comparar tareas equivalentes y registrar inicio, consulta de fuente, corrección, registro y retrabajo. Si se revisan solo campos destacados, errores no destacados pueden no contarse: hay que auditar independientemente parte de los aceptados. El experimento supone verdad conocida; el proyecto real debe construirla y financiarla. No probamos con personas ni presentamos tiempos supuestos como observaciones. La revisión manual también puede fallar: un contraste que la supone perfecta debe declararlo, no esconder errores tras esa hipótesis.
Del validador al sistema de gestión: un recorrido controlable
La consecuencia de diseño es separar propuesta y registro. Conservar original, campos propuestos, coordenadas, versión del extractor, normalizaciones y resultados permite reconstruir la decisión. Revisar debe corregir datos sin reescribir el original y mostrar por qué falla un control. Al preparar la importación hay que conservar identificador de operación y estado: un timeout no demuestra que el sistema no haya registrado ya. Aquí no implementamos integración ni registramos datos reales; identificamos el límite que la evaluación debe cubrir.
Limitar inicialmente el alcance a una familia documental y usar una cola explícita de excepciones vuelve el proceso comprobable. «Requiere revisión» no basta: mostrar qué partidas no cuadran, qué campo falta y qué página comprobar. Un documento fuera de esquema no debe convertirse en ceros para pasar controles. Aprobar sigue siendo una decisión trazable, no certificación automática del modelo. Esto no demuestra que EL-AI tenga ya un producto contable: analizamos una arquitectura posible, sin anunciar un servicio realizado.
Leer el código sin perder la pregunta
make crea registros y conserva la comparación con la referencia. coherent comprueba enteros, moneda e igualdades, no identidad ni normas. policy aplica el umbral, cuenta aceptaciones y errores con verdad conocida y suma tiempos supuestos. Las aserciones prueban errores detectados y coherentes escapados, fijando 5/7/2 y 540/1140 segundos con 0,95. Comprobar sumas crece linealmente con partidas, pero no representa complejidad ni latencia de un modelo visual no ejecutado. Para reproducir, ejecutar experiment.py y después plot.py; resultados y versiones están en el archivo.
Qué podemos decidir y qué queda por demostrar
En el alcance declarado, los controles aritméticos derivan registros incoherentes pero no autorizan por sí solos importar. El contraejemplo de 264 euros lo demuestra sin depender de un modelo. El coste de corregir cambia la decisión: nueve minutos iniciales se vuelven diecinueve bajo nuestros supuestos; más de siete minutos y medio por reparación elimina la ventaja frente al registro manual. Doce casos construidos no estiman cuántas facturas reales son automatizables, ni fijan un umbral universal o prometen rentabilidad.
La decisión útil parte del formato disponible, separa extracción y autorización, mide corrección de aceptados y cuenta todo el trabajo para obtener datos utilizables. Si la importación estructurada cubre la necesidad, quizá no haga falta IA. Si hay que interpretar páginas variables, el modelo debe integrarse en un proceso verificable, no sustituir controles por puntuaciones tranquilizadoras. El próximo experimento es una evaluación independiente sobre documentos y excepciones reales, con contraste manual medido y criterios explícitos de detención, no una demostración más vistosa.
Fuentes y materiales reproducibles
Peppol BIS Billing 3.0 — BR-CO-10, May 2026 release.
Peppol BIS Billing 3.0 — BR-CO-15, May 2026 release.
Šimsa et al. — DocILE, arXiv:2302.05658v2, 3 May 2023; sections 3–5.
Python — decimal; documentation and runtime versions may differ.
import json,sys,copy
from pathlib import Path
BASE=dict(lines=[12000,8000],net=20000,tax=4000,total=24000,supplier="SUP-A",currency="EUR")
def make(name,score,change=None):
x=copy.deepcopy(BASE)
if change:x.update(change)
return dict(id=name,score=score,data=x,correct=x==BASE)
rows=[make("C1",.99),make("C2",.97),make("C3",.94),make("C4",.85),make("C5",.98),make("C6",.92),
make("E1",.99,dict(total=25000)),make("E2",.98,dict(net=21000)),make("E3",.96,dict(tax=4100)),
make("E4",.99,dict(lines=[13200,8800],net=22000,tax=4400,total=26400)),
make("E5",.97,dict(supplier="SUP-B")),make("E6",.90,dict(supplier="SUP-C"))]
def coherent(x):
return (all(type(v) is int for v in x['lines']+[x['net'],x['tax'],x['total']])
and sum(x['lines'])==x['net'] and x['net']+x['tax']==x['total'] and x['currency']=="EUR")
def policy(threshold):
auto=[r for r in rows if coherent(r['data']) and r['score']>=threshold]
errors=sum(not r['correct'] for r in auto);n=len(rows);accepted=len(auto)
return dict(threshold=threshold,accepted=accepted,review=n-accepted,errors=errors,
coverage=accepted/n,conditionalError=errors/accepted if accepted else None,
activeSeconds=n*10+(n-accepted)*60,withRepairSeconds=n*10+(n-accepted)*60+errors*300)
for r in rows:r['coherent']=coherent(r['data'])
assert sum(r['correct'] for r in rows)==6
assert sum(not r['coherent'] for r in rows)==3
assert coherent(rows[9]['data']) and not rows[9]['correct']
assert coherent(rows[10]['data']) and not rows[10]['correct']
policies=[policy(t) for t in [0,.90,.95,.98,1.01]]
r=policy(.95)
assert (r['accepted'],r['review'],r['errors'],r['activeSeconds'],r['withRepairSeconds'])==(5,7,2,540,1140)
result=dict(python=sys.version.split()[0],seed=None,scope='Deterministic synthetic extracted records; no OCR, model, invoices, people or accounting system tested',currency='EUR',amountUnit='integer cents',baselineSeconds=12*120,assumptions=dict(intakeSeconds=10,reviewSeconds=60,repairSeconds=300,manualSeconds=120),records=rows,policies=policies)
Path(__file__).with_name('results.json').write_text(json.dumps(result,indent=2),encoding='utf8')
print(json.dumps(r))
Código, datos e instrucciones · JSON. Cálculos didácticos ejecutados con Python 3.14.0; figuras con Matplotlib 3.11.2. Análisis asistido por IA, sin afirmar revisión por pares ni humana. Portada original ImageGen ilustrativa: no documenta personas, sedes ni instalaciones de EL-AI. Fuentes consultadas el 26 de octubre de 2026.

