# FIX 2026-07-01b — YOLANDA no marca ocupado/amarillo (mapa PSTN congelado)

**Servidor:** deselpa.vozsi.com (138.68.97.77) · **Reporta:** Tatiana (coordinadora)
**Síntoma:** "cuando una tarotista termina una llamada tiene que ponerse **amarilla** 4 min
(guarda/descanso) antes de quedar libre; tras el último cambio esto no se señaliza."

## Diagnóstico (todo verificado en vivo, read-only)

El amarillo de cortesía (`esperando`) **funciona bien en general**: verificado en el log del
daemon (`panel-sync-asterisk`) con transiciones limpias `ocupado→disponible` +
`Hora colgada actualizada` para HADA(348), 320, 336, 323, 309, 374…

El fallo real era en **YOLANDA** (y en cualquiera que cambie de ficha/login):

- `pbx/includes/ami_busy_agents.php` → `ami_pstn_agent_map()` cacheaba el mapa
  PSTN→agente en una variable **`static` para TODA la vida del proceso**.
- El daemon es **long-running** → su mapa quedó **CONGELADO** con el estado de login del
  arranque.
- YOLANDA comparte teléfono **950…10** entre dos fichas: **328** (YOLANDA H) y **331**
  (YOLANDA). El desempate del mapa elige la que tiene `estado_login=1`. YOLANDA pasó de la
  ficha 331 a la 328, pero el daemon siguió con el mapa viejo (`950…10 → 331`, ya
  deslogueada).
- Consecuencia: el daemon atribuía las llamadas de YOLANDA a **331** (`activo=0`, invisible
  en el panel). La ficha viva **328 NUNCA se marcaba `ocupado`** →
  1. sin rojo durante la llamada,
  2. al colgar **no había transición `ocupado→disponible`** → **no se guardaba
     `ultima_hora_colgada`** → **sin amarillo de cortesía**,
  3. `estado_ocupacion` de 328 **parpadeaba 1↔0** (el AGI la ponía a 1; el daemon la
     reconciliaba a 0 porque creía a 328 libre) → el "baile" verde/consulta.

**Prueba irrefutable:** un script como root veía `AMIbusy 328=SÍ`, pero el log del daemon
decía `Ocupación desde AMI | agents:[331,…]`. Como 331 ya tenía `login=0`, un cálculo fresco
JAMÁS la habría elegido → el mapa del daemon estaba caducado.

> No lo causó el fix del 01-07 (histéresis / Regla A). Lo disparó el cambio de ficha de
> YOLANDA sin reiniciar el daemon. Es un defecto latente: reaparecería con cualquier cambio
> de ficha/login mientras el daemon siga vivo.

## Cambio aplicado (con backup + reversible)

Fichero: `/var/www/html/pbx/includes/ami_busy_agents.php`
Backup: `…/ami_busy_agents.php.bak_yolanda_20260701_apply`

- `ami_pstn_agent_map()`: caché con **TTL de 30 s** (`static $builtAt`; rebuild si
  `time()-$builtAt >= 30`). Marca `$builtAt` sólo tras un build correcto.
- `ami_valid_agent_codes()`: caché con **TTL de 60 s** (mismo motivo; detectar tarotistas
  nuevas/reactivadas).
- Coste: para scripts por petición (<1 s) sigue siendo 1 sola construcción; para el daemon,
  una consulta indexada barata cada 30/60 s. Un mapa fresco es estrictamente mejor.

Tras subir: `php -l` OK, `systemctl restart panel-sync-asterisk.service`.

## Verificación post-fix

- Log del daemon: `Actualizado: 331 -> offline`, `Actualizado: 328 -> ocupado`,
  `estado_ocupacion: 328 -> 1`. AMI ahora reporta **328** de forma estable.
- Watch de cortesía 100 s: **328 dejó de parpadear**. 337 hizo `esperando→disponible`
  (cortesía expirada, correcto).
- Cross-check AMI↔panel: 328/363/348/320 ocupados en AMI = todos `ocupado` en el panel.
  **331 = offline**.

## Reversión

```bash
F=/var/www/html/pbx/includes/ami_busy_agents.php
cp -p $F.bak_yolanda_20260701_apply $F
systemctl restart panel-sync-asterisk.service
```

## Pendiente / higiene (no bloqueante)

- **Fichas duplicadas por teléfono** (colisiones reales en `agentes.telefono`): 950…10
  (328/331). Convendría dar de baja/limpiar `telefono` de la ficha muerta 331 para evitar
  ambigüedad. Otras colisiones observadas: 931…30 (586/900) y varios placeholders
  999…99 / 777…xx compartidos por muchas fichas login=0.
- **Llamadas muy cortas (<3 s)**: el sondeo AMI del daemon (cada 3 s) puede no verlas; el
  AGI sí marca `estado_ocupacion`, pero al no pasar por `ocupado` en el daemon no se guarda
  colgada → esas no muestran amarillo. Caso límite pre-existente, impacto bajo.
