- 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).
112 lines
4.0 KiB
Python
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()
|
|
# ============================================================================ |