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

+11 -4
View File
@@ -22,6 +22,7 @@ Los datos viven en la tabla `comprobantes` de `emails.db`. El esquema lo crea `d
| `doc_entry` | DocEntry del draft creado en SAP |
| `veces_recibido` | Cuántos correos distintos trajeron este comprobante |
| `notificacion_estado`, `notificacion_error`, `notificacion_fecha` | `pendiente`, `enviada`, `fallida` u `omitida`, y su motivo |
| `notificacion_destinatario` | Direcciones a las que se envió **de verdad** (en modo prueba no son las del remitente) |
| `creado_en`, `actualizado_en` | Marcas de tiempo |
## Funciones
@@ -32,7 +33,8 @@ Los datos viven en la tabla `comprobantes` de `emails.db`. El esquema lo crea `d
| `registrar_correo(email_id)` | Igual, para un correo sin comprobante. Idempotente por correo. |
| `obtener(codigo)` | Devuelve el registro o `None`. |
| `actualizar_resultado(codigo, estado, observaciones=None, doc_entry=None)` | Guarda el resultado. `ValueError` si el estado no es válido, `LookupError` si no existe el código. |
| `registrar_notificacion(codigo, estado, error=None)` | Guarda el estado de la notificación. Mismas excepciones. |
| `registrar_notificacion(codigo, estado, error=None, destinatario=None)` | Guarda el estado de la notificación y a quién se envió. Mismas excepciones. |
| `contar_respuestas_correo(remitente, horas=24)` | Respuestas `enviada` a ese remitente en correos sin comprobante: el freno contra bucles de `respuesta_proveedor`. |
## Uso en el pipeline
@@ -44,12 +46,17 @@ En `pipeline._procesar_un_correo`, cada factura se registra al empezar (`_regist
| Precios no coinciden con SAP | `rechazado` | `[{"codigo": "precios_no_coinciden"}]` |
| Error al crear el draft | `error` | `[{"codigo": "error_sap", "detalle": "..."}]` |
`init_db` agrega la columna `notificacion_destinatario` a una tabla creada antes sin ella, sin tocar los datos.
El seguimiento **nunca impide procesar la factura**: si falla la base de datos, se registra un `WARNING` y el flujo continúa. Si el comprobante ya había llegado antes, se registra un `WARNING` con las veces recibidas y el estado anterior, pero **no se bloquea** la creación de otro draft.
## Estado actual y pendiente
## Observaciones guardadas
- Los `observaciones` guardados hoy son mínimos. Se reemplazarán por observaciones estructuradas (título, filas, cómo corregir) cuando se definan las validaciones de rechazo.
- `registrar_correo` y `registrar_notificacion` están implementados y probados, pero el pipeline todavía no los llama: los usarán las notificaciones al proveedor.
- Rechazo de una factura: la lista de observaciones completa (`codigo`, `titulo`, `filas`, `como_corregir`; ver `observaciones.py`).
- Error: `[{"codigo": "error_interno", "detalle": "..."}]`.
- Correo sin comprobante: la observación del motivo (`sin_pdf_xml`, `falta_xml`, `sin_factura`).
Las notificaciones las registra `respuesta_proveedor` (`enviada`, `fallida` u `omitida` con su motivo).
## Notas