GeorgeandClaude Sonnet 5.5 f0ad6aa78e se valida si la factura ya existe en SAP y se avisa cuando SAP está fuera de línea
- sapb1_manager.buscar_factura_existente busca la factura (proveedor, tipo,
  serie, número) en facturas de compra no anuladas y en drafts; si existe no
  se crea otro draft y se responde "ya está registrada" sin pisar el registro
  de una aceptación anterior.
- SapNoDisponible (subclase de ConnectionError) distingue una caída (timeout,
  sin conexión, HTTP 5xx) de un rechazo normal de SAP (HTTP 4xx). Una caída
  de Service Layer con HANA sin resultados ya no se lee como "guía no existe".
- Con SAP o HANA caídos se avisa una sola vez al proveedor con la plantilla
  "En cola" y el correo se reintenta en los ciclos siguientes (hasta 24), sin
  repetir avisos; al agotarse se avisa al equipo.
- La lógica por factura pasa a _procesar_factura; lo ya resuelto dentro de un
  correo no se repite al reintentarlo.
- seguimiento: columna intentos (con migración), registrar_intento y el
  estado de notificación en_espera.
- database_utilities.DB_NAME pasa a ser absoluto (junto al código).

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

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
  → 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
  → 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)

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.

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 de tests/fixtures/correos_prueba/ y la compara con tests/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 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
tools/ Scripts manuales: reprocesar correos, regenerar/inspeccionar 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/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
S
Description
No description provided
Readme
2.2 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 88%
HTML 10.3%
PowerShell 1.7%