Files
IPSExtractor/docs/application/flows.md
T

90 lines
3.6 KiB
Markdown

# `application/flows.py`
## Propósito
Orquesta el procesamiento por radicado para:
- Calcular encabezados CSV unificados a partir de muestras y selección de campos.
- Extraer información de factura y, opcionalmente, preformato.
- Escribir filas en CSV y emitir JSON a la interfaz gráfica mediante callbacks.
Incluye una heurística para inferir qué listas deben expandirse por filas y cuáles agregarse como columnas (en preformato).
## API pública
### `compute_csv_header_union(...) -> tuple[list[str] | None, dict[str, str]]`
Calcula el encabezado CSV común (unión) desde datos de muestra y paths seleccionados, aplicando alias y resolviendo duplicados.
Parámetros clave:
- `sample_fact`, `sample_pre`: ejemplos (dict o compatible) para derivar columnas.
- `selected_fields_fact`, `selected_fields_pre`: paths seleccionados por documento.
- `pre_enabled`: habilita el cálculo para preformato.
- `alias_map_fact`, `alias_map_pre`: alias opcionales path->nombre.
Devuelve:
- Lista de encabezados finales (o `None` si no hay columnas).
- Mapa `path -> alias final` aplicado.
Notas:
- `radicado` siempre se incluye como columna.
- Duplicados de alias se desambiguarán con sufijos `(n)`.
### `process_radicados_parallel(...) -> None`
Procesa en paralelo los radicados, realizando:
1) Extracción de datos de factura y preformato (si está habilitado).
2) Emisión de JSON via `on_output`.
3) Escritura incremental en CSV con encabezado dado (`csv_header_union`) o derivado.
Parámetros clave:
- `service`: Debe exponer `extract_full_from_pdf(...)` y `_append_rows_to_csv(...)`.
- `root`, `keywords`, `pre_keywords`: Búsqueda de documentos por radicado.
- `selected_fields_fact`, `selected_fields_pre`: paths de salida.
- `csv_path`: Archivo CSV destino (si `None`, no escribe).
- `on_output`: Callback que recibe texto JSON por radicado.
- `on_progress`: Callback `(radicado, done, total)` para progreso.
- `instruction_invoice`, `instruction_pre`: instrucciones LLM.
- `alias_final_map`: alias finales a aplicar a encabezados/filas.
Concurrencia:
- Usa `ThreadPoolExecutor` con `max_workers=4` para balancear IO/CPU.
- Los errores por documento se capturan y se registran sin detener el flujo.
## Consideraciones
- Si se define `csv_header_union`, éste manda sobre encabezados derivados por radicado.
- Para preformato, la heurística `_infer_aggregate_list_paths_from_selected` selecciona la lista principal y las listas a agregar; si no hay inferencia, se consulta `profiles`.
- `on_output` y `on_progress` son opcionales y tolerantes a errores (capturados).
## Ejemplos
### Cálculo de encabezado
```python
from application.flows import compute_csv_header_union
header, alias_map = compute_csv_header_union(
sample_fact={'radicado': 'x', 'items': [{'codigo': 'A1', 'cantidad': 2}]},
sample_pre=None,
selected_fields_fact=['radicado', 'items/*/codigo', 'items/*/cantidad'],
selected_fields_pre=None,
pre_enabled=False,
)
# header ~= ['radicado', 'items/*/codigo', 'items/*/cantidad']
```
### Proceso por radicado (escritura CSV)
```python
from application.flows import process_radicados_parallel
process_radicados_parallel(
service=my_service, # Debe implementar extract_full_from_pdf y _append_rows_to_csv
root="C:/carpeta/raiz",
keywords=["FACTURA", "RADICADO"],
pre_enabled=True,
pre_keywords=["PREFORMATO"],
selected_fields_fact=['radicado', 'items/*/codigo', 'items/*/cantidad'],
selected_fields_pre=['radicado', 'dx/*/descripcion'],
csv_path="salida.csv",
on_output=lambda txt: print(txt),
on_progress=lambda r,d,t: print(f"{d}/{t} -> {r}"),
)
```