# 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`](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 ```bash 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`](.env.example). Al arrancar, `config_validator` termina con un error claro si falta alguna obligatoria. ## Uso ```bash 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 # 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`](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/`](deploy/) trae los scripts (instalar, actualizar a una versión etiquetada y volver atrás, desinstalar) y [`docs/despliegue_windows.md`](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.2`); el historial está en [`CHANGELOG.md`](CHANGELOG.md). ## Pruebas ```bash pip install -e ".[dev]" # instala pytest pytest # más de 300 pruebas, unos 4 segundos; no tocan SAP, HANA ni Outlook ``` - **Extracción** (`tests/test_extraccion_correos.py`): corre la extracción real sobre cada correo de `tests/fixtures/correos_prueba/` y la compara con `tests/golden/.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 con `UPDATE_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_correo` con 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 | | `tests/` | Suite pytest, correos de ejemplo (`tests/fixtures/`) y resultados esperados (`tests/golden/`) | ## Documentación | Documento | Tema | |-----------|------| | [`docs/inventario.md`](docs/inventario.md) | Archivos, dependencias, flujo de datos y bugs corregidos | | [`docs/main.md`](docs/main.md) | Demonio y horarios | | [`docs/pipeline.md`](docs/pipeline.md) | Flujo por correo y funciones por módulo | | [`docs/procesar_pdfs.md`](docs/procesar_pdfs.md) / [`docs/procesar_xmls.md`](docs/procesar_xmls.md) | Extracción de datos de PDF y XML | | [`docs/validar_precios.md`](docs/validar_precios.md) | Validación de precios contra SAP | | [`docs/construir_draft.md`](docs/construir_draft.md) | Construcción del Draft SAP B1 | | [`docs/respuesta_proveedor.md`](docs/respuesta_proveedor.md) | Respuesta de aceptado/rechazado al proveedor: modos, protecciones y observaciones | | [`docs/seguimiento.md`](docs/seguimiento.md) | Códigos de seguimiento y resultado por comprobante | | [`docs/despliegue_windows.md`](docs/despliegue_windows.md) | Instalación como servicio de Windows con NSSM, operación y rollback | | [`docs/configurar_msal.md`](docs/configurar_msal.md) | Cómo obtener `CLIENT_ID`, `TENANT_ID` y `CLIENT_SECRET` en Azure | | [`docs/outlook_utilities.md`](docs/outlook_utilities.md) | Cliente de Microsoft Graph | | [`docs/sapb1_manager.md`](docs/sapb1_manager.md) | SAP Service Layer: drafts, guías, facturas existentes y manejo de caídas | | [`docs/hana_manager.md`](docs/hana_manager.md) | Consultas directas a SAP HANA |