# FIX 2026-07-15 — URLs públicas de estado para clientes no coincidían con el panel

## Síntoma
Clientes de las URLs de estado (`/pbx/public/{GAMA|RUTH|NOPE}/main.php`, admin en
`/var/www/html/pbx/tarotist_url_manager.php`) veían tarotistas en verde que en el
panel (`/var/www/html/panel`) figuraban ocupadas o en cortesía. El panel era el correcto.

## Causa raíz
`/var/www/html/pbx/includes/tarotist_status_functions.php` calculaba la ocupación POR SU
CUENTA (AMI `core show channels concise` + CEL), sin leer la verdad del panel
(`panel_tarot.tarotistas`). Dos defectos concretos, confirmados en vivo:

1. **Sin cortesía**: el panel marca `esperando` los N minutos tras colgar
   (`configuraciones.tiempo_cortesia_minutos`, hoy 4) y en ese estado la tarotista NO
   recibe llamadas; la URL la pintaba verde. Ocurría tras CADA llamada (caso ROSY 329).
2. **Detección de ocupado obsoleta**: buscaba el código del agente en el CallerID de los
   canales `switch` (patrones `5\d\d{cod}` o `{cod}` exacto). Las llamadas DISA→PSTN
   (`Dial PJSIP/<tel>@switch` desde `disa-capture`) generan la pata switch con CallerID
   `s` → no matcheaba → verde en plena llamada (caso YOLANDA 331, 35 min en llamada).
   Es la misma clase de bug que el panel arregló el 2026-07-01 con pstnMap/Regla A en
   `ami_busy_agents.php`; este código quedó con la detección vieja.

   Extras del código viejo: descartaba accountcode/peeraccount al parsear (patrones 3/4
   eran código muerto) y SELECTeaba `agentes.estado_ocupacion` "como fallback" sin usarlo.

## Fix aplicado
`/var/www/html/pbx/includes/tarotist_status_functions.php`
(backup: `tarotist_status_functions.php.bak_estado_panel_20260715`):

- Nueva `get_panel_estado_efectivo($users_list)`: una consulta cross-DB (misma conexión
  mysqli del pbx, el usuario tiene SELECT sobre `panel_tarot`) que replica la lógica de
  `estado_operadoras.php`: CASE cortesía sobre `ultima_hora_colgada` con el valor
  dinámico de `configuraciones.tiempo_cortesia_minutos` (fallback 4).
- `get_tarotist_status()`: el roster sigue saliendo de `asterisk.agentes` con
  `estado_login=1` (quién aparece no cambia), pero `is_free` ahora es
  `estado_efectivo='disponible' AND activo AND !bloqueado` según el panel. Pausa,
  reservado, esperando, etc. cuentan como NO libre — igual que el panel.
- Tiempo en estado: `TIMESTAMPDIFF` en SQL sobre
  `GREATEST(ultima_actualizacion, ultima_hora_colgada)` (TIMESTAMP, sesión ya en
  Europe/Madrid → coherente). Fallback: `agentes.updated_at`.
- Degradación: si la consulta al panel falla, cae a `agentes.estado_ocupacion`
  (antes ni eso).
- Las funciones AMI/CEL viejas (`get_agent_bridge_status_from_cel`,
  `get_active_channels_from_asterisk`, `tarotist_ami_fast.php`) quedan SIN USO, no se
  borraron para minimizar el diff. Formatos de salida (html/text/json) intactos.

## Verificación (2026-07-15 12:42)
- `php -l` OK; las 3 URLs responden HTTP 200 en ~30 ms (antes 20-65 ms con AMI).
- Comparador read-only URL vs panel sobre 52 agentes: **0 mismatches**
  (antes del parche: ROSY verde/esperando y YOLANDA verde/ocupado).
- Caso vivo post-parche: ZAMIRA 369 en cortesía → URL en rojo (correcto);
  YOLANDA 331 en llamada → rojo (correcto).

## Notas
- Fuente de verdad ÚNICA: si el panel cambia su lógica de estados, las URLs la heredan.
- El indicador de tiempo del formato text (0/3) ahora sale de los timestamps del panel.
- Copia de este doc en el servidor: `/var/www/html/PROYECTO_CENTRALITA_TAROT/docs/`.
