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

+35 -9
View File
@@ -14,7 +14,10 @@ Módulos que orquesta _procesar_un_correo():
├── documentos.py procesar_pdfs, procesar_xmls, completar_guias, validar_guias, copiar_a_red
├── persistencia.py guardar_resultado, guardar_draft_json
├── draft_sap.py validate_prices, obtener_valor_referencial_sap, build_sap_draft
├── notificaciones.py build_validation_html, build_valor_referencial_html, build_notification_body
├── notificaciones.py build_validation_html, build_valor_referencial_html, build_notification_body (correo técnico)
├── observaciones.py motivos de rechazo con sus textos
├── respuesta_proveedor.py respuesta con plantilla al remitente (modo prueba/real, protecciones)
├── plantillas.py renderizador de las plantillas HTML
└── pipeline_utils.py log, ruta_carpeta
```
@@ -54,29 +57,34 @@ flowchart TD
F -- Sí --> G[4. _descomprimir ZIPs]
G --> H[5. filtrar_y_limpiar]
H --> I{Hay PDF/XML?}
I -- No --> C
I -- No --> RC[Rechazo del correo<br>responder al remitente]
I -- Sí --> J[6. procesar_pdfs]:::highlight
J --> K[7. procesar_xmls]:::highlight
K --> K2[8. completar_guias]
K2 --> K3[9. validar_guias]
K3 --> L{Hay documentos?}
L -- No --> C
L -- No --> RC
L -- Sí --> M[10. guardar_resultado]
M --> N[11. Filtrar facturas tipo 01]
N --> O{Hay facturas?}
O -- No --> C
O -- No --> RC
O -- Sí --> P[Bucle: por cada factura]
P --> Q[12. validate_prices]:::highlight
Q --> Q2[12.5 obtener_valor_referencial_sap]
Q2 --> R[13. build_sap_draft]:::highlight
R --> S[14. guardar_draft_json]
S --> T{Todas coinciden?}
T -- Sí --> U[15. sapb1_manager.create_draft]
T -- No --> V[⏭️ Draft NO creado]
U --> W[16. outlook_utilities.send_email]
S --> T{¿Error de SAP/HANA?}
T -- Sí --> X[estado error]
T -- No --> T2{Todas coinciden?}
T2 -- Sí --> U[15. sapb1_manager.create_draft]
T2 -- No --> V[estado rechazado + observaciones]
U --> U2[estado aceptado]
U2 --> W[16. Correo técnico al equipo<br>+ respuesta con plantilla al remitente]
V --> W
X --> W2[16. Correo técnico al equipo<br>NO se responde al proveedor]
W --> P
W2 --> P
classDef highlight fill:#fff3e0,stroke:#e65100,stroke-width:3px;
```
@@ -174,5 +182,23 @@ run_pipeline
│ ├── guardar_draft_json
│ ├── sapb1_manager.create_draft (si todas las líneas coinciden)
│ ├── build_notification_body
│ └── outlook_utilities.send_email
│ ├── respuesta_proveedor.enviar_a_equipo (correo técnico, solo equipo)
│ └── respuesta_proveedor.responder (plantilla aceptado/rechazado, ver respuesta_proveedor.md)
```
---
## Qué se envía y a quién (paso 16)
| Resultado de la factura | Correo técnico (tablas de SAP, JSON adjuntos) | Respuesta con plantilla |
|-------------------------|-----------------------------------------------|-------------------------|
| `aceptado` (draft creado) | Equipo | Aceptado, al remitente |
| `rechazado` (precio, guía…) | Equipo | Rechazado con observaciones, al remitente |
| `error` (SAP/HANA, fallo inesperado) | Equipo | **Ninguna**: es una falla nuestra, no del proveedor |
| Correo sin comprobante válido (sin PDF/XML, sin XML, sin factura) | — | Rechazado sin comprobante, al remitente |
| Correo sin adjuntos | — | Ninguna |
"Al remitente" depende de `NOTIFICACION_MODO` (en modo `prueba` va al equipo) y de las protecciones. Todo en [respuesta_proveedor.md](respuesta_proveedor.md).
Un fallo inesperado al procesar una factura ya no interrumpe el ciclo: se registra como `error`, se avisa al equipo y se sigue con la siguiente.