se valida la configuración (.env) al arrancar
config_validator.verificar_configuracion termina con código 1 si faltan variables obligatorias (pipeline, Graph, SAP B1, HANA), si hay ruta de red sin RUC_EMPRESA, y advierte por SSL desactivado, ruta de red ausente o LOG_LEVEL inválido. Se invoca desde main.py y tools/consulta_rapida.py. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
79378a70e1
commit
74be942a3e
6 files changed
+98
-8
No files matched your search
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
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)
|
||||
@@ -19,6 +19,7 @@
|
||||
| `hana_manager.py` | 123 | Comunicación con SAP HANA directa (fallback de `sapb1_manager` y valor referencial) |
|
||||
| `database_utilities.py` | 116 | SQLite local (cache de correos) |
|
||||
| `tools/consulta_rapida.py` | 121 | Script auxiliar para reprocesar correos por ID (sets en `tools/ids_prueba.json`) |
|
||||
| `config_validator.py` | 83 | Valida el `.env` al arrancar (obligatorias, ruta de red, avisos de SSL) |
|
||||
| `email_utilities.py` | 52 | Utilitarios de adjuntos (ZIP, filtrado) |
|
||||
| `logger_manager.py` | 149 | Logging a archivo rotado (30 días) + consola + captura de `print()` |
|
||||
|
||||
|
||||
+7
-2
@@ -96,7 +96,12 @@ if __name__ == "__main__":
|
||||
1. logger_manager.setup_logging()
|
||||
└── Configura logging a archivo rotado (logs/descarga_factura_transporte.log,
|
||||
rotación diaria, 30 días de historial) + consola, y redirige print()/stderr
|
||||
al mismo log (no hace falta migrar cada print a logger.info).
|
||||
2. print(...) banner de inicio, incluyendo logger_manager.LOG_FILE
|
||||
al mismo log (los módulos del pipeline ya usan logger con nivel explícito;
|
||||
los print() restantes se registran como INFO).
|
||||
2. logger.info(...) banner de inicio, incluyendo logger_manager.LOG_FILE
|
||||
3. main()
|
||||
└── Tras load_dotenv(), config_validator.verificar_configuracion():
|
||||
termina con código 1 si falta alguna variable obligatoria del .env
|
||||
(ver config_validator.OBLIGATORIAS) y advierte si la verificación SSL
|
||||
está desactivada o no hay ruta de red.
|
||||
```
|
||||
@@ -6,6 +6,7 @@ from datetime import datetime, timedelta
|
||||
from dotenv import load_dotenv
|
||||
|
||||
import logger_manager
|
||||
from config_validator import verificar_configuracion
|
||||
from pipeline import run_pipeline
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -70,6 +71,7 @@ def main() -> None:
|
||||
|
||||
# Ruta absoluta: no depende del directorio de trabajo desde el que se lance el proceso
|
||||
load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), ".env"))
|
||||
verificar_configuracion()
|
||||
|
||||
EMAIL = os.getenv("EMAIL", "")
|
||||
DOWNLOAD_FOLDER = os.getenv("DOWNLOAD_FOLDER", "")
|
||||
|
||||
@@ -19,6 +19,7 @@ dependencies = [
|
||||
[tool.setuptools]
|
||||
py-modules = [
|
||||
"adjuntos",
|
||||
"config_validator",
|
||||
"database_utilities",
|
||||
"documentos",
|
||||
"draft_sap",
|
||||
|
||||
@@ -19,6 +19,7 @@ sys.path.insert(0, RAIZ)
|
||||
|
||||
import database_utilities
|
||||
import logger_manager
|
||||
from config_validator import verificar_configuracion
|
||||
from pipeline import _procesar_un_correo, step_authenticate
|
||||
|
||||
|
||||
@@ -54,13 +55,10 @@ def get_email_by_id(user_email: str, token: str, message_id: str) -> dict | None
|
||||
def run_pipeline_for_ids(ids: list[str]) -> None:
|
||||
# Ruta absoluta: no depende del directorio de trabajo desde el que se lance el proceso
|
||||
load_dotenv(dotenv_path=os.path.join(RAIZ, ".env"))
|
||||
verificar_configuracion()
|
||||
email_addr = os.getenv("EMAIL", "")
|
||||
download_folder = os.getenv("DOWNLOAD_FOLDER", "adjuntos")
|
||||
output_folder = os.getenv("OUTPUT_FOLDER", "resultado")
|
||||
|
||||
if not email_addr:
|
||||
print("❌ EMAIL no configurado en .env")
|
||||
return
|
||||
download_folder = os.getenv("DOWNLOAD_FOLDER", "")
|
||||
output_folder = os.getenv("OUTPUT_FOLDER", "")
|
||||
|
||||
database_utilities.init_db()
|
||||
token = step_authenticate()
|
||||
|
||||
Reference in new issue
Block a user