se responde al remitente con las plantillas de aceptado/rechazado

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>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-22 08:55:54 -05:00
1 parent af9e3961e5
commit 4deb9d4e4d
22 files changed
+1660 -146

No files matched your search

+31 -1
View File
@@ -5,7 +5,8 @@ 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", *cv.VERIFICACION_SSL]
OPCIONALES = ["RUTA_RED_FACTURACION", "RUC_EMPRESA", "LOG_LEVEL", "NOTIFICACION_MODO", "NOTIFICACION_EQUIPO", "LOGO_URL",
*cv.VERIFICACION_SSL]
@pytest.fixture
@@ -74,3 +75,32 @@ def test_verificar_termina_con_codigo_1_si_hay_errores(env_completo, monkeypatch
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)