Files
descarga_factura_transporte/config_validator.py
T

83 lines
3.0 KiB
Python
Raw Normal View History

"""
Validación de la configuración (.env) al arrancar el proceso.
Falla rápido con un mensaje claro si falta alguna variable obligatoria, en
lugar de descubrirlo a mitad de un ciclo (por ejemplo, adjuntos descargados
en la raíz del proyecto por un ``DOWNLOAD_FOLDER`` vacío, o consultas a HANA
que devuelven 0 en silencio por credenciales ausentes).
"""
import os
import sys
import logging
logger = logging.getLogger(__name__)
# Variables obligatorias, agrupadas por servicio para el mensaje de error.
OBLIGATORIAS = {
"Pipeline": ["EMAIL", "DOWNLOAD_FOLDER", "OUTPUT_FOLDER"],
"Microsoft Graph": ["CLIENT_ID", "CLIENT_SECRET", "TENANT_ID"],
"SAP B1 Service Layer": ["SAP_B1_URL", "SAP_B1_COMPANY", "SAP_B1_USER", "SAP_B1_PASSWORD"],
"SAP HANA": ["HANA_SERVER", "HANA_USER", "HANA_PASSWORD", "HANA_SCHEMA"],
}
# Variable de verificación SSL → servicio al que aplica. Cada módulo solo
# la activa con el valor "true" (cualquier otro valor, o ausente, la desactiva).
VERIFICACION_SSL = {
"VERIFY_SSL": "Microsoft Graph",
"SAP_B1_VERIFY_SSL": "SAP B1 Service Layer",
}
def validar_configuracion() -> tuple[list[str], list[str]]:
"""
Revisa las variables de entorno ya cargadas (tras ``load_dotenv``).
Returns:
tuple[list[str], list[str]]: ``(errores, advertencias)``. Los errores
impiden arrancar; las advertencias solo se registran.
"""
errores: list[str] = []
advertencias: list[str] = []
for servicio, variables in OBLIGATORIAS.items():
faltan = [v for v in variables if not os.getenv(v, "").strip()]
if faltan:
errores.append(f"{servicio}: faltan {', '.join(faltan)}")
ruta_red = os.getenv("RUTA_RED_FACTURACION", "").strip()
ruc_empresa = os.getenv("RUC_EMPRESA", "").strip()
if ruta_red and not ruc_empresa:
errores.append("Ruta de red: RUTA_RED_FACTURACION está definida pero falta RUC_EMPRESA")
elif not ruta_red:
advertencias.append(
"RUTA_RED_FACTURACION no definida: no se copiarán PDF/XML a la red "
"y U_VS_ANEXO_PDF/XML irán vacíos en el draft"
)
nivel = os.getenv("LOG_LEVEL", "").strip()
if nivel and not isinstance(getattr(logging, nivel.upper(), None), int):
advertencias.append(f"LOG_LEVEL='{nivel}' no es un nivel válido; se usará INFO")
for variable, servicio in VERIFICACION_SSL.items():
if os.getenv(variable, "").strip().lower() != "true":
advertencias.append(f"Verificación SSL desactivada para {servicio} ({variable} distinto de 'true')")
return errores, advertencias
def verificar_configuracion() -> None:
"""
Registra las advertencias y, si hay errores, los registra y termina el
proceso con código 1.
"""
errores, advertencias = validar_configuracion()
for a in advertencias:
logger.warning(f"⚠️ Configuración: {a}")
if errores:
logger.error("❌ Configuración incompleta en .env:")
for e in errores:
logger.error(f" - {e}")
sys.exit(1)