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).
This commit is contained in:
1 parent
1503d6a2ec
commit
277d07dfeb
22 files changed
+1081
-750
No files matched your search
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
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()
|
||||
# ============================================================================
|
||||
Reference in new issue
Block a user