Files
descarga_cpe_sovos/core.py
T
George 277d07dfeb Migra el servicio a arquitectura Docker persistente y mueve credenciales HANA a .env
- Reemplaza config_loader/config_model/hana_client/logger_utilities/outlook_utilities
  por core.py (pipeline funcional), hana_manager.py, logger_manager.py, scheduler.py y
  descargador_sovos.py (Playwright/Firefox) según la plantilla de servicios.
- main.py pasa a loop continuo dirigido por scheduler.json, con manejo de SIGINT/SIGTERM.
- Agrega Dockerfile, docker-compose.yml (restart unless-stopped) y certs/ para despliegue.
- Agrega smb_transfer.py para la transferencia a carpeta compartida.
- Saca las credenciales de HANA de config.json y las mueve a .env (HANA_HOST/PORT/USER/PASSWORD).
2026-08-25 09:29:35 -05:00

112 lines
4.0 KiB
Python

"""
core.py — Pipeline funcional del servicio de descarga CPE (Sovos).
Reescribe las funciones de la plantilla:
* describir_servicio() : banner del log.
* obtener_datos() : consulta HANA multi-schema.
* procesar_y_descargar(): descarga PDF/XML de Sovos y marca en HANA.
"""
import os
import json
from pathlib import Path
from dotenv import load_dotenv
from logger_manager import get_logger
from hana_manager import obtener_pendientes, cerrar_conexion, obtener_config_hana
from descargador_sovos import descargar_documentos_pendientes
from smb_transfer import get_mount_base, transferir_a_smb
# ============================================================================
load_dotenv()
logger = get_logger("core")
CONFIG_FILE = Path(os.getenv("CONFIG_PATH", Path(__file__).parent / "config.json"))
# ============================================================================
def _cargar_config(path: str | None = None) -> dict:
p = Path(path) if path else CONFIG_FILE
with open(p, encoding="utf-8") as f:
return json.load(f)
CFG = _cargar_config()
def empresas_activas(cfg: dict) -> list[dict]:
return [e for e in cfg.get("empresas", []) if not e.get("locked", False)]
# ============================================================================
# Específico del servicio
# ============================================================================
def describir_servicio() -> str:
return "DESCARGA COMPROBANTES ELECTRÓNICOS (SUNAT)"
def obtener_datos(empresa: dict) -> list[dict]:
schema = empresa["schema"]
rucs = CFG.get("rucs", [])
dias = CFG.get("consulta", {}).get("dias", 240)
logger.info(f" 💾 Consultando HANA schema={schema}")
return obtener_pendientes(schema, rucs, dias)
def procesar_y_descargar(datos: list[dict], dir_empresa: Path) -> dict:
return descargar_documentos_pendientes(datos, dir_empresa)
# ============================================================================
# Pipeline (genérico)
# ============================================================================
def ejecutar(cfg: dict | None = None):
cfg = cfg if cfg is not None else CFG
base = Path(cfg.get("files", {}).get("path", "downloads")).resolve()
activas = empresas_activas(cfg)
logger.info("=" * 60)
logger.info(f"🚀 {describir_servicio()}")
cfg_hana = obtener_config_hana()
logger.info(f"💾 HANA: {cfg_hana['host']}:{cfg_hana['port']}")
logger.info("=" * 60)
logger.info(f"🏢 Empresas configuradas: {len(cfg.get('empresas', []))}")
logger.info(f"📁 Descargas base: {base}")
if not activas:
logger.info("⏭️ No hay empresas activas (todas LOCKED). Fin.")
return
# LOOP 1: datos + procesamiento por empresa
for emp in activas:
nombre = emp["nombre"]
dir_empresa = base / nombre
logger.info("#" * 60)
logger.info(f"# 🏢 Empresa: {nombre}")
logger.info("#" * 60)
datos = obtener_datos(emp)
if not datos:
logger.info(" ✅ No hay documentos pendientes")
continue
logger.info(f" 📄 Documentos pendientes obtenidos: {len(datos)}")
procesar_y_descargar(datos, dir_empresa)
# LOOP 2: transferencia a carpeta compartida (conserva si no está montada)
logger.info("=" * 60)
logger.info("🔁 Transferencia a carpeta compartida (SMB)")
logger.info("=" * 60)
mount_base = get_mount_base()
auto_mount = os.getenv("SMB_AUTO_MOUNT", "false").lower() == "true"
logger.info(f" Montaje base: {mount_base} | automontaje: {auto_mount}")
resultados = transferir_a_smb(activas, mount_base, auto_mount)
logger.info("📊 Resumen transferencias:")
for r in resultados:
logger.info(f" • {r['empresa']}: {r['estado']}")
logger.info("\n👋 Proceso finalizado.")
cerrar_conexion()
# ============================================================================
if __name__ == "__main__":
ejecutar()
# ============================================================================