Documentación técnica

NOVA3 Pro
Manual de Usuario

Portal de control de costes industriales con extracción automática de facturas por IA y análisis de precios de materiales.

1. Qué es NOVA3 Pro

NOVA3 Pro es una aplicación web de escritorio construida con Streamlit orientada al control de costes de materiales industriales. Sus tres ejes principales son:

EjeDescripción
ExtracciónProcesa facturas en PDF de forma automática mediante OCR + LLM local (Ollama)
AnálisisGenera estadísticas de gasto por proveedor, evolución temporal de precios y comparativas entre grupos de materiales
MercadoLanza un agente que busca precios en internet (DuckDuckGo + OpenAI) y permite etiquetar nuevos proveedores

2. Arquitectura general

PDFs nuevos
    │
    ▼
invoices_in/          ← carpeta de entrada
    │
    ▼  (botón "Procesar" en Dashboard)
process.sh
    │
    ▼
.agent/skills/invoice-router/
scripts/process_invoices.py
    │
    ├── invoice-preprocess  → extrae texto del PDF (PyPDF)
    ├── invoice-router      → detecta proveedor, parsea, valida
    └── csv_export          → escribe CSVs y JSONs de salida
    │
    ├── out/invoices.csv        → cabeceras de facturas
    ├── out/invoice_lines.csv   → líneas de detalle
    ├── facturas_revisadas/     → PDFs procesados con éxito
    └── facturas_error/         → PDFs que fallaron validación
    │
    ▼
app.py (Streamlit UI)   ← lee los CSVs y JSONs, presenta la interfaz

La aplicación no usa base de datos SQL. Todo el estado persiste en archivos CSV y JSON en la carpeta out/.

3. Modelo de datos

Archivos principales

ArchivoContenido
out/invoices.csvUna fila por factura: invoice_key, invoice_number, invoice_date, provider_name, total_amount, source_file
out/invoice_lines.csvUna fila por línea de factura: invoice_key, product_name, quantity, unit_price, line_total
out/confirmed_prices.jsonPrecios validados manualmente: {material, category, price, provider, date}
out/tagged_providers.jsonRed de proveedores web: {"Nombre": {"status": "Alta"/"Baja", "link": "...", "date_included": "..."}}
out/grouped_materials.jsonGrupos de materiales: {"Nombre grupo": {"members": ["variante1", "variante2", ...]}}

Relaciones

invoices (invoice_key) ──< invoice_lines (invoice_key)
invoice_lines (product_name) ──> grouped_materials (members)

4. Pipeline de extracción de facturas

Flujo paso a paso

  1. Depósito: coloca los PDFs en invoices_in/
  2. Disparo: pulsa "Procesar Nuevas Facturas" en el Dashboard
  3. Hash SHA-256: el sistema comprueba si la factura ya fue procesada (idempotencia)
  4. OCR / extracción de texto: invoice-preprocess usa PyPDF para leer el texto
  5. Detección de proveedor: provider_registry puntúa cada parser disponible y elige el de mayor score (umbral mínimo: 0.3)
  6. Parseo: el parser seleccionado extrae campos estructurados (número, fecha, proveedor, líneas)
  7. Normalización: fechas, importes y cantidades se normalizan a tipos Python estándar
  8. Validación contable: comprueba que suma de líneas ≈ total factura
  9. Exportación: se añade al CSV si pasa validación; si no, va a out/review/ para revisión manual
  10. Clasificación de archivo: éxito → facturas_revisadas/, error → facturas_error/

Parsers disponibles

SkillFunción
invoice-parse-genericParser genérico usando Ollama (gemma4:latest) para cualquier formato desconocido
invoice-parse-vendor-templateParsers específicos por proveedor: LECU, LLAVE, IDELLA, vendor_b
invoice-preprocessExtracción de texto puro del PDF
invoice-routerOrquestador del pipeline completo

5. Páginas de la aplicación

5.1 Dashboard

Propósito: visión global y punto de entrada de procesamiento.

KPIs en cabecera:

  • Facturas procesadas totales
  • Importe total acumulado
  • Número de proveedores distintos
  • Archivos pendientes en invoices_in/

Botón "Procesar Nuevas Facturas": ejecuta process.sh, muestra un resumen diferencial (cuántas facturas nuevas, materiales añadidos, errores) y recarga la interfaz.

Grid de proveedores: tarjetas con nombre, total de facturas y fecha de última actividad. Cada tarjeta tiene un expander con el listado de facturas del proveedor y botón de descarga del PDF original.

5.2 Proveedores

Propósito: análisis detallado por proveedor.

  • Selector global de proveedor
  • Pestaña "Listado de Facturas": tabla con todas las facturas del proveedor seleccionado
  • Pestaña "Análisis de Materiales": editor interactivo donde se puede asignar categoría y confirmar el precio unitario de cada material. Al pulsar "Confirmar Precios", los datos se escriben en confirmed_prices.json

5.3 Catálogo de Materiales

Propósito: búsqueda, selección y agrupación de variantes de nombres de materiales.

Flujo de agrupación

  1. Escribe una palabra clave en el buscador (ej: Cable) — la tabla se filtra en tiempo real
  2. Marca las filas que quieres consolidar usando el checkbox de cada fila
  3. El banner verde muestra cuántas filas llevas seleccionadas (persiste aunque cambies el filtro)
  4. Escribe el nombre canónico del grupo (ej: Cable Cobre Unipolar 1.5mm) y pulsa Guardar
  5. Alternativamente, pulsa uno de los botones naranjas para añadir a un grupo ya existente

Panel derecho: lista de grupos existentes con sus miembros. Cada miembro tiene un botón para quitarlo individualmente del grupo.

Truco: puedes filtrar por Cable, marcar los de 1.5mm, luego filtrar por Tubo y marcar los de PVC — la selección acumula materiales de distintos filtros. El botón limpia la selección completa.

5.4 Material Agrupado

Propósito: trazabilidad completa de cada grupo hasta la factura origen.

Por cada grupo se muestra:

  • Variantes incluidas: chips con el nombre de cada variante y botón para eliminarla del grupo
  • Histórico de compras: tabla con todas las facturas en las que aparece cualquier variante del grupo (denominación original, precio, proveedor, fecha, ID de factura)
  • Botón "Eliminar grupo completo"

5.5 Estadísticas Precios Materiales

Propósito: comparativa de precio unitario entre proveedores para un grupo de materiales, con filtros de ventana temporal y proveedor.

Controles

ControlDescripción
Selector de grupoElige el grupo a analizar
Mes/Año inicioPrimer mes de la ventana temporal
Mes/Año finÚltimo mes de la ventana temporal
↺ TodoRestablece la ventana al rango completo
Selector de proveedoresMultiselect para incluir/excluir proveedores

Contenido

KPIs: número de proveedores, compras totales, precio mínimo, medio y máximo en la ventana seleccionada.

Gráfico dumbbell — "Precio unitario por proveedor": línea horizontal de mínimo a máximo, punto sólido en la media, proveedores ordenados de más barato a más caro, línea de media global como referencia.

Gráfico de evolución temporal: una línea por proveedor, banda verde "Zona óptima", marcador destacado en el último punto con el precio más reciente. Si la ventana no es completa: líneas verticales marcando inicio y fin.

Tabla resumen: mínimo, media, máximo, número de compras y fecha de última compra por proveedor. La media más baja aparece en verde, la más alta en rojo.

5.6 Estadísticas

Propósito: análisis global de gasto por proveedor y evolución temporal.

  • KPIs globales: total de proveedores, proveedor principal y ticket medio
  • Gráfico de líneas: evolución del gasto mensual por proveedor, eje X categórico (solo meses con datos), relleno semitransparente, hover unificado
  • Tab "Totales Acumulados": gráfico de barras horizontal con importe total y porcentaje
  • Tab "Micro-Análisis por Material": evolución de precio unitario por proveedor + tabla ranking de optimización de costes

5.7 Analizador de Precios

Propósito: búsqueda en internet de precios de mercado para un material específico, usando DuckDuckGo + GPT-3.5-turbo.

  1. Selecciona un material del catálogo
  2. Introduce tu clave de OpenAI API
  3. Pulsa "Iniciar Agente": el sistema busca en DuckDuckGo, recoge hasta 15 resultados y los envía a GPT-3.5-turbo para que extraiga precios reales
  4. Se muestran cards con nombre del proveedor web, precio detectado y enlace
  5. Cada card tiene un botón para dar de alta ese proveedor en tagged_providers.json

5.8 Red de Proveedores Web

Propósito: gestión de la base de datos de proveedores web (encontrados por el agente o añadidos manualmente).

  • Alta manual: formulario con nombre y URL
  • Listado activo: solo se muestran los proveedores con status = "Alta", con su enlace y fecha de incorporación
  • Dar de baja: cambia el status a "Baja" sin borrar el registro

5.9 Generador de Test (PDF)

Propósito: crear facturas ficticias para probar el pipeline de extracción sin necesidad de facturas reales.

  • Elige empresa ficticia, fecha y número de factura
  • Editor de líneas de materiales (concepto, cantidad, precio unitario)
  • Calcula automáticamente subtotales, IVA (21%) y total
  • Genera el PDF y lo deposita directamente en invoices_in/ listo para procesar

6. Stack tecnológico

ComponenteTecnología
Interfaz de usuarioPython · Streamlit
GráficosPlotly Express + Plotly Graph Objects
Procesado de datospandas
LLM local (OCR)Ollama — modelo gemma4:latest
LLM en la nubeOpenAI gpt-3.5-turbo (solo Analizador de Precios)
Búsqueda webDuckDuckGo HTML scraping + BeautifulSoup
Extracción de PDFPyPDF
PersistenciaArchivos CSV + JSON (sin base de datos)
TipografíasGoogle Fonts: Sora (títulos) · Inter (cuerpo)
Tema visualClaro — fondo #F1F5F9, acento teal #0D9488

7. Estructura de carpetas

NOVA3/
├── app.py                        # Aplicación principal (Streamlit)
├── process.sh                    # Script shell que lanza el pipeline
├── ollama_parser.py              # Cliente directo de Ollama (utilidad)
│
├── .agent/skills/
│   ├── invoice-router/           # Orquestador del pipeline
│   │   └── scripts/
│   │       ├── process_invoices.py
│   │       └── lib/              # normalize, validate, csv_export, models…
│   ├── invoice-preprocess/       # Extracción de texto PDF
│   ├── invoice-parse-generic/    # Parser genérico (Ollama)
│   └── invoice-parse-vendor-template/  # Parsers por proveedor
│       └── scripts/parsers/      # lecu.py · llave.py · idella.py …
│
├── out/
│   ├── invoices.csv
│   ├── invoice_lines.csv
│   ├── confirmed_prices.json
│   ├── tagged_providers.json
│   └── grouped_materials.json
│
├── invoices_in/                  # Bandeja de entrada de PDFs
├── facturas_revisadas/           # PDFs procesados con éxito
├── facturas_error/               # PDFs que fallaron el pipeline
│
├── .streamlit/
│   └── config.toml               # Puerto, tema claro, colores
│
└── tests/                        # Tests unitarios (pytest)
    ├── test_registry.py
    ├── test_validate.py
    └── test_normalize.py
NOVA3 Pro · Documentación · Mayo 2026 Subir