Files
descarga_factura_transporte/docs/inventario.md
T
GeorgeandClaude Sonnet 5.5 7d2f3212c0 se divide pipeline.py en módulos (adjuntos, documentos, persistencia, draft_sap, notificaciones)
Las funciones anidadas de _procesar_un_correo pasan a funciones de módulo
con parámetros explícitos; pipeline.py queda solo como orquestador.
copiar_a_red lee las variables de entorno al ejecutarse. Se actualizan docs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 22:03:38 -05:00

9.9 KiB

Inventario del código

Archivos

Archivo Líneas Rol
main.py 134 Demonio orquestador (loop de horarios)
pipeline.py 230 Orquestador del pipeline (autenticar, descargar correos, procesar un correo)
pipeline_utils.py 15 log() con indentación de árbol y ruta_carpeta()
adjuntos.py 81 Descarga de adjuntos (Graph) y filtrado PDF/XML
documentos.py 371 Extracción PDF/XML, asignación de guías, copia a red
persistencia.py 163 Guardado de JSON de resultados y de drafts
draft_sap.py 413 Validación de precios contra SAP, valor referencial y construcción del draft
notificaciones.py 117 Cuerpos HTML de los correos de notificación
sunat_schema.py 720 Parseo de XML SUNAT (Invoice, DespatchAdvice)
pdf_utilities.py 464 Parseo de PDFs (factura, guías)
sapb1_manager.py 321 Comunicación con SAP B1 Service Layer
outlook_utilities.py 234 Comunicación con Microsoft Graph
hana_manager.py 123 Comunicación con SAP HANA directa (fallback de sapb1_manager y valor referencial)
database_utilities.py 116 SQLite local (cache de correos)
consulta_rapida.py 113 Script auxiliar para reprocesar correos por ID
email_utilities.py 52 Utilitarios de adjuntos (ZIP, filtrado)
logger_manager.py 149 Logging a archivo rotado (30 días) + consola + captura de print()

Dependencias entre archivos

main.py
  ├── logger_manager.py
  └── pipeline.py
        ├── sunat_schema.py
        ├── pdf_utilities.py
        ├── sapb1_manager.py
        │     └── hana_manager.py
        ├── hana_manager.py            (valor referencial, Sp_ObtenerValorReferencial)
        ├── outlook_utilities.py
        ├── email_utilities.py
        └── database_utilities.py

Módulos que pipeline.py orquesta (todos usan pipeline_utils.py):

pipeline.py
  ├── adjuntos.py        → outlook_utilities
  ├── documentos.py      → sunat_schema, pdf_utilities
  ├── persistencia.py    → sunat_schema, pdf_utilities
  ├── draft_sap.py       → sapb1_manager, hana_manager
  └── notificaciones.py

consulta_rapida.py
  ├── logger_manager.py
  ├── database_utilities.py
  └── pipeline.py (_procesar_un_correo, step_authenticate)

Flujo de datos

main()
  └── run_pipeline()
        ├── step_authenticate() → token MS Graph
        ├── step_fetch_emails() → emails[]
        └── _procesar_un_correo() (por cada email)
              ├── BD: verificar duplicado
              ├── adjuntos.descargar_adjuntos() → archivos
              ├── email_utilities.descomprimir_adjuntos() ZIPs
              ├── adjuntos.filtrar_y_limpiar() → solo PDF/XML
              ├── documentos.procesar_pdfs() → pdf_cache
              │     └── pdf_utilities.extraer_datos_pdf()
              ├── documentos.procesar_xmls(pdf_cache) → documentos[]
              │     ├── sunat_schema.extraer_datos_xml()
              │     └── documentos.copiar_a_red() → copia PDF/XML a ruta de red (RUTA_RED_FACTURACION)
              ├── documentos.completar_guias(documentos, pdf_cache) → completa guías faltantes desde PDF
              ├── documentos.validar_guias(documentos) → advierte guías con datos incompletos
              ├── persistencia.guardar_resultado(documentos)
              ├── draft_sap.validate_prices(factura) → (ok, resultados)
              │     └── sapb1_manager.get_delivery_notes()
              │           ├── SL (Service Layer) GET /DeliveryNotes
              │           ├── HANA fallback (get_delivery: ODLN, luego OWTR)
              │           └── si vino de OWTR: GET StockTransfers(DocEntry)
              │                 → U_IDC_NUMOV → GET Orders(U_IDC_NUMOV)
              ├── draft_sap.obtener_valor_referencial_sap(factura) → guias_valor_ref
              │     └── hana_manager.obtener_valor_referencial() (Sp_ObtenerValorReferencial)
              ├── draft_sap.build_sap_draft(factura, resultados) → draft (incluye U_VS_ANEXO_PDF/XML)
              │     └── sapb1_manager.obtener_condicion_pago(CardCode) → DocDueDate
              ├── persistencia.guardar_draft_json(draft)
              ├── sapb1_manager.create_draft(draft)
              └── outlook_utilities.send_email(notificación)

Problemas conocidos hasta ahora

# Problema Archivo Estado
1 _extraer_serie_numero_desde_texto no limpiaba leading zeros sunat_schema.py ✅ Corregido
2 Al asignar guías por línea, si hay +refs que líneas, las sobrantes se perdían pipeline.py ✅ Corregido
3 SL sin fallback a HANA sapb1_manager.py ✅ Corregido
4 Ctrl+C mostraba traceback main.py ✅ Corregido
5 .env.dev vs .env inconsistente sapb1_manager.py ✅ Corregido
6 HANA_HOST vs HANA_SERVER en .env hana_manager.py ✅ Corregido
7 Columna Cancelled vs CANCELED en HANA hana_manager.py ✅ Corregido
8 Bloque if __name__ == "__main__" borraba un correo real de la BD al ejecutar el módulo directo database_utilities.py ✅ Corregido
9 extraer_datos_xml solo procesaba guías tipo 31; tipo 09 (remitente) se descartaba pese a estar documentado sunat_schema.py ✅ Corregido
10 DatosComprobante.__str__ usaba ref.id (campo que ya no existe en DocumentoReferencia) sunat_schema.py ✅ Corregido
11 Log de error HTTP con print("%s", ...) no interpolaba el mensaje sapb1_manager.py ✅ Corregido
12 Fuga de conexión HANA si cursor() fallaba (quedaba fuera del try) hana_manager.py ✅ Corregido
13 razon_social_emisor se llenaba con el nombre del receptor en el JSON de depuración del PDF pipeline.py ✅ Corregido
14 Typo VERIFI_SSL en vez de VERIFY_SSL outlook_utilities.py / .env ✅ Corregido
15 Conexiones SQLite sin try/finally (fuga si fallaba una consulta a mitad de camino) database_utilities.py ✅ Corregido
16 Código muerto sin llamadores (quitar_correos_ya_registrados_en_base_de_datos, procesar_adjuntos_email) email_utilities.py ✅ Corregido (eliminado)
17 logger_utilities.py (redirección global de stdout, sin niveles ni rotación real) reemplazado por logger_manager.py (logging estándar, rotación diaria 30 días, captura de print()) logger_manager.py ✅ Corregido
18 task()/last_task() de logger_manager.py no devolvían el sub-logger (with ... as sub daba siempre None) logger_manager.py ✅ Corregido
19 DOWNLOAD_FOLDER duplicado en .env .env ✅ Corregido
20 Guías tipo 09 no se encontraban si el documento estaba en OWTR (Traslado de Inventario) en vez de ODLN hana_manager.py ✅ Corregido (fallback ODLN → OWTR)
21 Parámetros tipo/serie cruzados al llamar get_delivery/get_delivery_notes (mapeaban al revés a U_BPP_MDSD/U_BPP_MDTD) hana_manager.py, sapb1_manager.py, pipeline.py ✅ Corregido (orden natural tipo, serie, numero)
22 StockTransfers (OWTR) no tiene líneas FL*, por lo que la validación de precios fallaba siempre para esas guías sapb1_manager.py ✅ Corregido (resuelve la Orden de Venta vía U_IDC_NUMOV y valida contra Orders(DocEntry))
23 DocDueDate del draft usaba fecha_emision del XML, sin considerar la condición de pago del proveedor pipeline.py, sapb1_manager.py ✅ Corregido (DocDueDate = fecha de contabilización + días de PaymentTermsTypes)
24 Patrón regex de valor referencial no reconocía la variante truncada "VALOR REFER" (ej. "VALOR REFER:S/ 1431.16") sunat_schema.py ✅ Corregido

Funciones por módulo

Antes eran funciones anidadas en _procesar_un_correo; ahora son funciones de módulo que reciben explícitamente email, download_folder, output_folder, etc. pipeline.py solo las orquesta.

Módulo Función Propósito
pipeline_utils ruta_carpeta Resuelve una ruta relativa al directorio del proyecto
pipeline_utils log Imprime con indentación de árbol (niveles 1-4)
adjuntos descargar_adjuntos Descarga adjuntos vía Graph API
adjuntos filtrar_y_limpiar Filtra PDF/XML, elimina el resto
documentos copiar_a_red Copia PDF/XML a la ruta de red de Facturación Electrónica (RUTA_RED_FACTURACION)
documentos procesar_pdfs Extrae datos de PDFs, renombra, genera cache
documentos procesar_xmls Procesa XMLs, cruza con PDF, asigna guías, copia a red
documentos completar_guias Completa guías faltantes en líneas XML desde el PDF cache
documentos validar_guias Advierte (log) guías con datos incompletos
persistencia guardar_resultado Guarda JSON con datos extraídos (XML y PDF)
persistencia guardar_draft_json Guarda draft JSON para depuración
draft_sap calcular_fecha_vencimiento Calcula DocDueDate = fecha de contabilización + días de la condición de pago (PaymentTermsTypes)
draft_sap build_sap_draft Construye payload del draft SAP B1
draft_sap validate_prices Valida precios contra DeliveryNotes / Orders (SAP)
draft_sap obtener_valor_referencial_sap Consulta Sp_ObtenerValorReferencial en HANA por guía
notificaciones build_validation_html Genera tabla HTML de validación de precios
notificaciones build_valor_referencial_html Genera tabla HTML comparando valor referencial XML vs SAP
notificaciones build_notification_body Arma cuerpo del email de notificación