El sistema contesta a quien envió el correo con la plantilla que corresponda. Por defecto (NOTIFICACION_MODO=prueba) la respuesta va solo al equipo con el asunto "[PRUEBA → remitente]"; en modo real va al remitente con copia oculta al equipo. El correo técnico (tablas de SAP, JSON) pasa a ir solo al equipo. - respuesta_proveedor.py: contextos de las plantillas, envío y protecciones (remitente desconocido o sin dominio, propio buzón, no-reply, mensajes automáticos, respuestas a notificaciones, límite de 3 por remitente/24 h). - observaciones.py: motivos de rechazo con título, filas y cómo corregir (borrador de textos); también para correos sin comprobante válido. - Un error de SAP/HANA o un fallo inesperado no se le comunica al proveedor y ya no tumba el ciclo; "guía no encontrada" exige que HANA responda. - outlook_utilities: es_mensaje_automatico y copia oculta en send_email. - seguimiento: notificacion_destinatario (con migración) y contar_respuestas_correo. - config_validator anuncia el modo activo; documentación y pruebas. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
107 lines
4.0 KiB
Python
107 lines
4.0 KiB
Python
import logging
|
|
|
|
import pytest
|
|
|
|
import config_validator as cv
|
|
|
|
OBLIGATORIAS = [v for grupo in cv.OBLIGATORIAS.values() for v in grupo]
|
|
OPCIONALES = ["RUTA_RED_FACTURACION", "RUC_EMPRESA", "LOG_LEVEL", "NOTIFICACION_MODO", "NOTIFICACION_EQUIPO", "LOGO_URL",
|
|
*cv.VERIFICACION_SSL]
|
|
|
|
|
|
@pytest.fixture
|
|
def env_completo(monkeypatch):
|
|
"""Entorno válido y sin variables opcionales (para partir de un estado conocido)."""
|
|
for v in OBLIGATORIAS:
|
|
monkeypatch.setenv(v, "valor")
|
|
for v in OPCIONALES:
|
|
monkeypatch.delenv(v, raising=False)
|
|
|
|
|
|
def test_entorno_completo_no_tiene_errores(env_completo):
|
|
errores, _ = cv.validar_configuracion()
|
|
assert errores == []
|
|
|
|
|
|
def test_faltantes_se_agrupan_por_servicio(env_completo, monkeypatch):
|
|
monkeypatch.delenv("CLIENT_ID")
|
|
monkeypatch.setenv("HANA_USER", " ") # solo espacios cuenta como vacío
|
|
errores, _ = cv.validar_configuracion()
|
|
|
|
assert len(errores) == 2
|
|
assert any(e.startswith("Microsoft Graph") and "CLIENT_ID" in e for e in errores)
|
|
assert any(e.startswith("SAP HANA") and "HANA_USER" in e for e in errores)
|
|
|
|
|
|
def test_ruta_de_red_sin_ruc_es_error(env_completo, monkeypatch):
|
|
monkeypatch.setenv("RUTA_RED_FACTURACION", "//srv/facturas")
|
|
errores, _ = cv.validar_configuracion()
|
|
assert any("RUC_EMPRESA" in e for e in errores)
|
|
|
|
|
|
def test_sin_ruta_de_red_solo_advierte(env_completo):
|
|
errores, advertencias = cv.validar_configuracion()
|
|
assert errores == []
|
|
assert any("RUTA_RED_FACTURACION" in a for a in advertencias)
|
|
|
|
|
|
def test_advertencias_de_ssl(env_completo, monkeypatch):
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert sum("Verificación SSL" in a for a in advertencias) == 2
|
|
|
|
monkeypatch.setenv("VERIFY_SSL", "TRUE") # no distingue mayúsculas
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert not any("Microsoft Graph" in a and "SSL" in a for a in advertencias)
|
|
assert any("SAP B1" in a and "SSL" in a for a in advertencias)
|
|
|
|
|
|
def test_log_level_invalido_advierte(env_completo, monkeypatch):
|
|
monkeypatch.setenv("LOG_LEVEL", "CHISME")
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert any("LOG_LEVEL" in a for a in advertencias)
|
|
|
|
monkeypatch.setenv("LOG_LEVEL", "debug")
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert not any("LOG_LEVEL" in a for a in advertencias)
|
|
|
|
|
|
def test_verificar_termina_con_codigo_1_si_hay_errores(env_completo, monkeypatch, caplog):
|
|
monkeypatch.delenv("EMAIL")
|
|
with caplog.at_level(logging.ERROR), pytest.raises(SystemExit) as salida:
|
|
cv.verificar_configuracion()
|
|
assert salida.value.code == 1
|
|
assert "EMAIL" in caplog.text
|
|
|
|
|
|
def test_verificar_no_termina_si_todo_esta_bien(env_completo):
|
|
cv.verificar_configuracion() # no debe lanzar SystemExit
|
|
|
|
|
|
def test_el_modo_de_notificacion_se_anuncia_al_arrancar(env_completo, monkeypatch):
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert any("PRUEBA" in a for a in advertencias) and not any("REAL" in a for a in advertencias)
|
|
|
|
monkeypatch.setenv("NOTIFICACION_MODO", "Real")
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert any("REAL" in a and "quien envía el correo" in a for a in advertencias)
|
|
assert not any("PRUEBA" in a for a in advertencias)
|
|
|
|
|
|
def test_modo_de_notificacion_invalido_cae_en_prueba(env_completo, monkeypatch):
|
|
monkeypatch.setenv("NOTIFICACION_MODO", "produccion")
|
|
errores, advertencias = cv.validar_configuracion()
|
|
assert errores == []
|
|
assert any("produccion" in a and "se usará prueba" in a for a in advertencias)
|
|
|
|
|
|
def test_equipo_y_logo_sin_definir_solo_advierten(env_completo, monkeypatch):
|
|
errores, advertencias = cv.validar_configuracion()
|
|
assert errores == []
|
|
assert any("NOTIFICACION_EQUIPO" in a for a in advertencias) and any("LOGO_URL" in a for a in advertencias)
|
|
|
|
monkeypatch.setenv("NOTIFICACION_EQUIPO", "a@x.com")
|
|
monkeypatch.setenv("LOGO_URL", "https://x.com/logo.png")
|
|
_, advertencias = cv.validar_configuracion()
|
|
assert not any("NOTIFICACION_EQUIPO" in a or "LOGO_URL" in a for a in advertencias)
|
|
|