fix(soporte): el filtro se estaba comiendo correos nuevos, y nadie se enteraba

Una respuesta a un hilo existente saltea el clasificador; un correo nuevo no.
Por eso el sistema parecía funcionar solo con las respuestas: los correos
nuevos que el modelo consideraba "no soporte" desaparecían sin ticket, sin
acuse al cliente y sin más rastro que un renglón de log que nadie mira.

Dos cambios:

- El filtro solo opina sobre desconocidos. Si el remitente es un cliente o un
  usuario del portal, siempre se abre el ticket. Para eso la resolución del
  remitente pasa a correr antes del filtro. A un cliente registrado no se le
  descarta el correo por lo que diga un modelo.

- Lo descartado se ve. "Revisar buzón ahora" informa cuántos dejó afuera el
  filtro, con asunto, remitente y motivo. Guardado en memoria: es diagnóstico
  de hace un rato, no algo que valga una tabla.

Además, si la respuesta automática está apagada, el log lo dice al crear el
ticket — era la otra explicación posible de "no me contestó" y no se distinguía.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-17 19:56:32 -05:00
co-authored by Claude Opus 5
parent 1b599606f7
commit 4674413257
4 changed files with 78 additions and 25 deletions
+32 -1
View File
@@ -139,11 +139,15 @@ func revisarBuzon(cfg *models.SoporteWebhookConfig) (int, int, error) {
return 0, 0, nil
}
fallosAlMarcar := 0
var descartes []string
procesados := 0
for _, correo := range correos {
if IngestarCorreoSoporte(cfg, correo.Correo) {
ok, descarte := IngestarCorreoSoporteConDetalle(cfg, correo.Correo)
if ok {
procesados++
} else if descarte != "" {
descartes = append(descartes, descarte)
}
// Se marca leído aunque se haya ignorado por duplicado: si no, se
// vuelve a bajar en cada corrida para siempre.
@@ -152,6 +156,7 @@ func revisarBuzon(cfg *models.SoporteWebhookConfig) (int, int, error) {
fallosAlMarcar++
}
}
ultimosDescartes.guardar(descartes)
if fallosAlMarcar > 0 {
return len(correos), procesados, fmt.Errorf(
"se procesaron %d correo(s), pero %d no se pudieron marcar como leídos en el servidor: van a volver a leerse",
@@ -160,6 +165,32 @@ func revisarBuzon(cfg *models.SoporteWebhookConfig) (int, int, error) {
return len(correos), procesados, nil
}
// ultimosDescartes guarda lo que el filtro dejó afuera en la última corrida,
// para poder mostrarlo en la pantalla de configuración. En memoria a propósito:
// es información de diagnóstico de hace un rato, no algo que valga una tabla.
var ultimosDescartes = &descartesRecientes{}
type descartesRecientes struct {
mu sync.Mutex
items []string
}
func (d *descartesRecientes) guardar(items []string) {
d.mu.Lock()
defer d.mu.Unlock()
if len(items) > 0 {
d.items = items
}
}
// UltimosCorreosDescartados devuelve los descartes de la última corrida que
// tuvo alguno.
func UltimosCorreosDescartados() []string {
ultimosDescartes.mu.Lock()
defer ultimosDescartes.mu.Unlock()
return append([]string(nil), ultimosDescartes.items...)
}
// criterioNoLeidos arma la búsqueda: no leídos y, si hay ventana configurada,
// recibidos dentro de ella.
//