Saltar al contenido
juancespedes.dev
Todos los proyectos
Caso de estudioAnonimizado

Extractor de facturas de energía en PDF para dos formatos

Aplicación de escritorio en Python que convierte facturas de energía en PDF de dos empresas con formatos distintos en datos estructurados, las exporta a Excel y las cruza contra la base de datos corporativa.

Ficha del proyecto

Rol
Desarrollador único, del análisis de las plantillas al empaquetado
Periodo
feb de 2026 a jun de 2026
Enlaces públicos
Sistema interno: el código es privado, y los nombres, datos y diagramas se omitieron o se recrearon.
  • 73

    facturas reales fijadas como corpus de regresión, con 26 campos verificados en cada unaFuente: Suite de regresión del repositorio, junio de 2026
  • 4 en 1

    proyectos previos, uno por empresa, unificados en una sola base de códigoFuente: Historial de git y carpetas de las versiones anteriores
  • 40+

    patrones de extracción, cada uno auditado contra una matriz de robustezFuente: Auditoría de cobertura de patrones del repositorio, 2026

El problema

En cada ciclo de facturación había que digitar y verificar a mano decenas de facturas de energía en PDF, de dos contrapartes con formatos completamente distintos, y compararlas contra los valores registrados en la base de datos corporativa. Era lento, propenso a errores y estaba repartido en cuatro scripts que hacían partes del trabajo.

Mi rol

  • Analicé las plantillas de cada contraparte, incluida la de notas crédito de reliquidación.
  • Unifiqué cuatro proyectos previos en una arquitectura con un paquete por empresa y la misma estructura interna.
  • Construí la interfaz gráfica y el empaquetado para usuarios de negocio sin Python instalado.
  • Escribí la suite de regresión y la auditoría de cobertura de patrones.

Restricciones

  • Usuarios de negocio sin conocimientos técnicos ni Python en sus equipos.
  • PDF generados por terceros, con problemas de codificación y plantillas que cambian sin aviso.
  • Un cero real debe distinguirse de un concepto que la factura no trae.

Decisiones

  1. 01

    Un paquete por empresa con la misma estructura

    Cada contraparte tiene su extractor, su procesamiento y su exportación, y la interfaz elige el motor en tiempo de ejecución. Agregar un formato nuevo es agregar un paquete.

    Descartado

    • Un solo extractor lleno de condicionales por empresa
  2. 02

    Extracción por coordenadas de página

    En el formato tabular, el texto se reconstruye agrupando las líneas por su posición vertical, lo que mantiene unidas las columnas que una extracción plana mezcla.

    Descartado

    • Extraer texto plano y separarlo solo con expresiones regulares
  3. 03

    Corpus dorado antes de tocar un patrón

    73 facturas reales congeladas en un snapshot hacen fallar la suite ante cualquier cambio de valor, y el snapshot solo se regenera después de una verificación manual.

    Descartado

    • Probar con unas pocas facturas de ejemplo
  4. 04

    Los campos no extraídos también son datos

    Cada factura lleva la lista de conceptos que la plantilla no trajo, así una plantilla nueva se detecta en el Excel en lugar de convertirse en ceros silenciosos.

    Descartado

    • Rellenar con cero lo que no se encuentre

Arquitectura

La interfaz gráfica recibe un PDF o una carpeta, elige el motor de la empresa y procesa en segundo plano. Cada motor extrae, limpia y exporta a Excel, y cruza los valores contra la base de datos corporativa.
  1. Entrada

    • Facturas en PDFUna factura o una carpeta completa
  2. Interfaz

    • Aplicación de escritorioCustomTkinter, procesamiento en un hilo aparte
  3. Motores

    • Motor de la empresa APDF a CSV y más de 40 patrones
    • Motor de la empresa BCoordenadas de página y líneas de ítems
  4. Salidas y referencia

    • Excel multihojaPor factura o consolidado por lote
    • PostgreSQL corporativoValores de referencia para el cruce

Cómo se mueven los datos

  1. Facturas en PDFhaciaAplicación de escritorioSelección del usuario
  2. Aplicación de escritoriohaciaMotor de la empresa ASegún el tipo de factura
  3. Aplicación de escritoriohaciaMotor de la empresa BSegún el tipo de factura
  4. PostgreSQL corporativohaciaMotor de la empresa AValores para comparar
  5. PostgreSQL corporativohaciaMotor de la empresa BValores para comparar
  6. Motor de la empresa AhaciaExcel multihojaFacturas, conceptos y parámetros
  7. Motor de la empresa BhaciaExcel multihojaConsolidado maestro con comparación

Resultados

  • La revisión de cada ciclo pasó de digitar factura por factura a seleccionar una carpeta y revisar las diferencias que marca el Excel.
  • Las diferencias contra la base corporativa salen campo por campo en una hoja de comparación.
  • Un ejecutable de Windows funciona sin instalar Python ni dependencias.

Qué haría distinto

  • Separaría desde el inicio el núcleo de extracción de la interfaz, para poder correrlo también por línea de comandos o programado en un servidor.
  • Construiría el corpus dorado antes de unificar los proyectos previos; habría hecho la unificación más rápida y más segura.

Tecnologías

  • Python
  • pdfminer.six
  • pandas
  • PostgreSQL
  • Excel
  • CustomTkinter
  • PyInstaller