versión 1.2.0: despliegue como servicio de Windows con NSSM

- deploy/: scripts de PowerShell para instalar el servicio (cuenta de servicio
  con acceso a la ruta de red, reinicio automático, parada con Ctrl+C,
  rotación de la salida, PYTHONUTF8), actualizar a una versión etiquetada o
  volver a una anterior, y desinstalar.
- docs/despliegue_windows.md: requisitos, instalación, operación, rollback y
  problemas frecuentes.
- tools/verificar_conexiones.py: comprueba .env, Graph, SAP, HANA y la ruta de
  red sin modificar nada.
- CHANGELOG.md, README e inventario; pyproject.toml pasa a 1.2.0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-22 12:08:38 -05:00
1 parent f01f21b1c3
commit cdcecc2b56
9 files changed
+416 -15

No files matched your search

+85
View File
@@ -0,0 +1,85 @@
"""
Comprueba, sin modificar nada, que el servidor puede trabajar: configuración del .env, credenciales de
Microsoft Graph y lectura del buzón, SAP Service Layer, SAP HANA y la ruta de red de facturación.
Uso (desde cualquier carpeta):
python tools/verificar_conexiones.py
Termina con código 1 si alguna comprobación falla. No imprime secretos.
"""
import logging
import os
import re
import sys
from datetime import datetime, timedelta
RAIZ = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
sys.path.insert(0, RAIZ)
from dotenv import load_dotenv
load_dotenv(dotenv_path=os.path.join(RAIZ, ".env"))
logging.disable(logging.CRITICAL) # solo interesa el resultado de cada comprobación
import config_validator
import hana_manager
import outlook_utilities
import sapb1_manager
fallos = 0
def resultado(ok: bool, nombre: str, detalle: str = "") -> None:
global fallos
fallos += 0 if ok else 1
print(f"{'✅' if ok else '❌'} {nombre}{(': ' + detalle) if detalle else ''}")
def resumen_error(ex: Exception) -> str:
return ", ".join(re.findall(r"AADSTS\d+", str(ex))) or f"{type(ex).__name__}: {str(ex)[:110]}"
# 1. Configuración
errores, avisos = config_validator.validar_configuracion()
resultado(not errores, "Configuración (.env)", "; ".join(errores))
for aviso in avisos:
print(f" ⚠️ {aviso}")
# 2. Microsoft Graph: token y lectura de la bandeja
token = None
try:
token = outlook_utilities.get_access_token()
resultado(bool(token), "Microsoft Graph: token")
except Exception as ex:
resultado(False, "Microsoft Graph: token", resumen_error(ex))
if token:
try:
hoy = datetime.now()
correos = outlook_utilities.get_emails(os.getenv("EMAIL", ""), token, (hoy - timedelta(days=1)).strftime("%Y-%m-%d"), hoy.strftime("%Y-%m-%d"))
resultado(True, "Microsoft Graph: lectura de la bandeja", f"{len(correos)} correos en el último día")
except Exception as ex:
resultado(False, "Microsoft Graph: lectura de la bandeja", resumen_error(ex))
# 3. SAP Service Layer
try:
resultado(True, "SAP Service Layer", f"{len(sapb1_manager.get_zonas())} zonas")
except Exception as ex:
resultado(False, "SAP Service Layer", resumen_error(ex))
# 4. SAP HANA
conexion = hana_manager.get_connection()
resultado(conexion is not None, "SAP HANA")
if conexion is not None:
conexion.close()
# 5. Ruta de red de facturación electrónica (opcional)
ruta = os.getenv("RUTA_RED_FACTURACION", "").strip()
if ruta:
existe = os.path.isdir(ruta)
resultado(existe and os.access(ruta, os.W_OK), "Ruta de red de facturación", "" if existe else "no existe o no es accesible con esta cuenta")
else:
print(" ⚠️ RUTA_RED_FACTURACION no definida: no se copia a la red (no se comprueba)")
print()
print("Todo listo." if not fallos else f"{fallos} comprobación(es) con fallo.")
sys.exit(1 if fallos else 0)