La comparación abs(a - b) < 0.01 no era fiable por la coma flotante: el mismo céntimo se aceptaba o rechazaba según el importe (431.41 contra 431.40 se rechazaba y 624.39 contra 624.38 se aceptaba). pipeline_utils.importes_coinciden redondea la diferencia a 2 decimales, lo que muestra un comprobante, y admite hasta 1 céntimo. Se usa en la validación de precios y en la comparación del valor referencial. Con datos reales de SAP (49 líneas) ningún resultado cambió. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7.0 KiB
descarga_factura_transporte
Demonio que descarga las facturas de transporte (PDF/XML SUNAT) recibidas en un buzón de Office 365, valida sus precios contra SAP Business One y crea el borrador (Draft) de la factura de compra. Al terminar, notifica el resultado por correo al remitente.
Qué hace con cada correo
Bandeja de entrada (Microsoft Graph)
→ descarga adjuntos, descomprime ZIP, se queda con PDF/XML
→ extrae datos de PDF y XML y asigna las guías de remisión por línea
→ comprueba que la factura no exista ya en SAP
→ valida precios de cada guía contra SAP (Service Layer, con fallback a HANA)
→ crea el Draft en SAP B1 si todos los precios coinciden
→ si SAP no responde, avisa "en cola" y reintenta en los ciclos siguientes
→ responde a quien envió el correo con la plantilla de aceptado o rechazado
(por defecto en modo prueba: la respuesta va al equipo; ver docs/respuesta_proveedor.md)
Cada correo se registra en una base SQLite (emails.db) y no se vuelve a procesar. Detalle del flujo en docs/pipeline.md.
Requisitos
- Python 3.11 o superior.
- Acceso a: Microsoft Graph (app registrada en Azure AD), SAP B1 Service Layer y SAP HANA.
Instalación
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env # y completar los valores
El .env nunca se sube a git. Todas las variables están documentadas en .env.example. Al arrancar, config_validator termina con un error claro si falta alguna obligatoria.
Uso
python main.py # demonio; consulta los últimos 2 días (--dias 2)
python main.py --dias 5 # ventana de búsqueda de 5 días
python tools/consulta_rapida.py --set <nombre> # reprocesar correos por ID (sets en tools/ids_prueba.json)
python tools/verificar_conexiones.py # comprueba .env, Graph, SAP, HANA y la ruta de red
El demonio trabaja por bloques horarios (cada 1, 5, 30 o 60 minutos según la hora) y duerme fuera de ellos. Los bloques están en HORARIOS de main.py y se explican en docs/main.md.
Despliegue
En producción corre como servicio de Windows con NSSM: arranca con el servidor y se reinicia solo. La carpeta deploy/ trae los scripts (instalar, actualizar a una versión etiquetada y volver atrás, desinstalar) y docs/despliegue_windows.md la guía completa. Antes de instalar, python tools/verificar_conexiones.py comprueba el .env, Microsoft Graph, SAP, HANA y la ruta de red. Las versiones son etiquetas de git (v1.2.1); el historial está en CHANGELOG.md.
Pruebas
pip install -e ".[dev]" # instala pytest
pytest # ~95 pruebas, unos 3 segundos; no tocan SAP, HANA ni Outlook
- Extracción (
tests/test_extraccion_correos.py): corre la extracción real sobre cada correo detests/fixtures/correos_prueba/y la compara contests/golden/<caso>.json. Esos resultados esperados fijan el comportamiento actual; no prueban que sea correcto. Si cambias la extracción a propósito, revisa el diff y regenéralos conUPDATE_GOLDEN=1 pytest tests/test_extraccion_correos.py. - Unitarias: validación de precios, construcción del draft, notificaciones, guías, copia a red, filtrado de adjuntos y validación del
.env. - Flujo completo (
tests/test_pipeline_flujo.py):_procesar_un_correocon SAP, HANA, Outlook y la BD simulados.
Los scripts de tools/ (procesar_pdfs_prueba.py, procesar_xmls_prueba.py, etc.) son anteriores a la suite: escriben xml_resultado_*.json y pdf_resultado_*.json dentro de cada carpeta de tests/fixtures/correos_prueba/. Esos archivos no los usa ninguna prueba y pueden estar desactualizados. tools/descargar_correos_prueba.py borra y vuelve a descargar toda esa carpeta de correos reales.
Carpetas de salida (ignoradas por git)
| Ruta | Contenido |
|---|---|
adjuntos/ |
PDF/XML descargados (DOWNLOAD_FOLDER) |
resultado/ |
JSON de datos extraídos y de drafts, para depuración (OUTPUT_FOLDER) |
logs/ |
Log con rotación diaria y 30 días de historial. LOG_LEVEL controla el nivel |
emails.db |
Correos ya procesados y comprobantes con su código de seguimiento |
Estructura del proyecto
| Módulo | Rol |
|---|---|
main.py |
Demonio y horarios |
pipeline.py |
Orquesta el proceso de cada correo |
adjuntos.py, documentos.py, persistencia.py |
Descarga de adjuntos, extracción de PDF/XML, guardado de JSON |
draft_sap.py, notificaciones.py |
Validación de precios y construcción del Draft; correo técnico para el equipo |
respuesta_proveedor.py, observaciones.py, plantillas.py |
Respuesta de aceptado/rechazado al remitente con las plantillas HTML (plantilla/) |
outlook_utilities.py, sapb1_manager.py, hana_manager.py |
Clientes de Microsoft Graph, SAP Service Layer y SAP HANA |
sunat_schema.py, pdf_utilities.py |
Lectura de XML SUNAT y de PDF |
database_utilities.py, seguimiento.py, email_utilities.py |
SQLite local; códigos de seguimiento y resultado por comprobante; ZIP y filtrado de adjuntos |
logger_manager.py, config_validator.py, pipeline_utils.py |
Logging, validación del .env, utilidades |
deploy/ |
Scripts de PowerShell para instalar el servicio de Windows con NSSM |
tools/ |
Scripts manuales: verificar conexiones, vista previa de las plantillas, reprocesar correos, regenerar los correos de prueba, aberio.http |
tests/ |
Suite pytest, correos de ejemplo (tests/fixtures/) y resultados esperados (tests/golden/) |
Documentación
| Documento | Tema |
|---|---|
docs/inventario.md |
Archivos, dependencias, flujo de datos y bugs corregidos |
docs/main.md |
Demonio y horarios |
docs/pipeline.md |
Flujo por correo y funciones por módulo |
docs/procesar_pdfs.md / docs/procesar_xmls.md |
Extracción de datos de PDF y XML |
docs/validar_precios.md |
Validación de precios contra SAP |
docs/construir_draft.md |
Construcción del Draft SAP B1 |
docs/respuesta_proveedor.md |
Respuesta de aceptado/rechazado al proveedor: modos, protecciones y observaciones |
docs/seguimiento.md |
Códigos de seguimiento y resultado por comprobante |
docs/despliegue_windows.md |
Instalación como servicio de Windows con NSSM, operación y rollback |
docs/configurar_msal.md |
Cómo obtener CLIENT_ID, TENANT_ID y CLIENT_SECRET en Azure |
docs/outlook_utilities.md |
Cliente de Microsoft Graph |
docs/hana_manager.md |
Consultas directas a SAP HANA |