Files
whatsapp/modules/turnero/api/get_cola.php
T
2026-06-16 08:53:28 -05:00

147 lines
5.2 KiB
PHP

<?php
/**
* GET /modules/turnero/api/get_cola.php
* Devuelve el estado de la cola para pantallas TV y kiosko.
* No requiere autenticación (acceso público).
*
* Query params:
* area string requerido "recepcion" | "lugar"
* lugar_id int requerido si area = "lugar"
*/
require_once __DIR__ . '/_helpers.php';
requireMethod('GET');
$area = isset($_GET['area']) ? trim($_GET['area']) : '';
$lugarId = isset($_GET['lugar_id']) ? (int) $_GET['lugar_id'] : null;
if (!in_array($area, ['recepcion', 'lugar'], true)) {
jsonError('area debe ser "recepcion" o "lugar".');
}
if ($area === 'lugar' && !$lugarId) {
jsonError('lugar_id es obligatorio cuando area = "lugar".');
}
$pdo = db();
// ── Sesión de hoy ─────────────────────────────────────────────
// Si no existe sesión hoy o está cerrada (fin_at set), pantalla limpia.
$_ses = sesionHoy();
$sesionCerrada = (!$_ses || $_ses['fin_at'] !== null);
// Usar sesion_id real solo si está abierta; 0 hace que las queries devuelvan vacío.
$sesionId = ($sesionCerrada) ? 0 : (int)$_ses['id'];
if ($sesionCerrada) {
jsonOk([
'sesion_cerrada' => true,
'activo' => null,
'cola' => [],
'stats' => [
'total' => 0, 'en_espera' => 0, 'en_recepcion' => 0,
'en_espera_lugar' => 0, 'en_servicio' => 0,
'finalizados' => 0, 'no_atendidos' => 0,
'tiempo_promedio_atencion' => null,
],
'timestamp' => date('c'),
]);
exit;
}
// ── Cola según área ───────────────────────────────────────────
if ($area === 'recepcion') {
$estadosCola = ["'espera'", "'en_recepcion'"];
$filtroLugar = '';
$bindsCola = [];
} else {
$estadosCola = ["'en_espera_lugar'", "'en_servicio'"];
$filtroLugar = 'AND t.lugar_destino_id = ?';
$bindsCola = [$lugarId];
}
$inEstados = implode(', ', $estadosCola);
$stmt = $pdo->prepare(
"SELECT t.id,
t.codigo,
t.numero,
t.estado,
t.paciente_nombre,
t.recepcion_desk_id,
t.creado_at,
t.llamado_recepcion_at,
t.llamado_lugar_at,
p.codigo AS prioridad_codigo,
p.nombre AS prioridad_nombre,
p.color AS prioridad_color,
p.orden_peso
FROM turnero_turnos t
JOIN turnero_prioridades p ON p.id = t.prioridad_id
WHERE t.sesion_id = ?
AND t.estado IN ({$inEstados})
{$filtroLugar}
ORDER BY p.orden_peso ASC, t.creado_at ASC"
);
array_unshift($bindsCola, $sesionId);
$stmt->execute($bindsCola);
$cola = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ── Turno actualmente en pantalla (último llamado) ────────────
$campoLlamado = $area === 'recepcion' ? 'llamado_recepcion_at' : 'llamado_lugar_at';
$estadoActivo = $area === 'recepcion' ? "'en_recepcion'" : "'en_servicio'";
$bindActivo = $area === 'lugar' ? [$sesionId, $lugarId] : [$sesionId];
$filtroActivo = $area === 'lugar' ? 'AND t.lugar_destino_id = ?' : '';
$stmt = $pdo->prepare(
"SELECT t.id,
t.codigo,
t.numero,
t.estado,
t.paciente_nombre,
t.{$campoLlamado} AS llamado_at,
p.codigo AS prioridad_codigo,
p.nombre AS prioridad_nombre,
p.color AS prioridad_color
FROM turnero_turnos t
JOIN turnero_prioridades p ON p.id = t.prioridad_id
WHERE t.sesion_id = ?
AND t.estado = {$estadoActivo}
{$filtroActivo}
ORDER BY t.{$campoLlamado} DESC
LIMIT 1"
);
$stmt->execute($bindActivo);
$activo = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
// ── Estadísticas de la sesión ─────────────────────────────────
$stmt = $pdo->prepare(
"SELECT
COUNT(*) AS total,
SUM(estado = 'espera') AS en_espera,
SUM(estado = 'en_recepcion') AS en_recepcion,
SUM(estado = 'en_espera_lugar') AS en_espera_lugar,
SUM(estado = 'en_servicio') AS en_servicio,
SUM(estado = 'finalizado') AS finalizados,
SUM(estado IN ('ausente','cancelado')) AS no_atendidos,
SEC_TO_TIME(
AVG(
CASE WHEN fin_lugar_at IS NOT NULL AND creado_at IS NOT NULL
THEN TIMESTAMPDIFF(SECOND, creado_at, fin_lugar_at)
ELSE NULL END
)
) AS tiempo_promedio_atencion
FROM turnero_turnos
WHERE sesion_id = ?"
);
$stmt->execute([$sesionId]);
$stats = $stmt->fetch(PDO::FETCH_ASSOC);
jsonOk([
'sesion_id' => $sesionId,
'area' => $area,
'lugar_id' => $lugarId,
'activo' => $activo,
'cola' => $cola,
'stats' => $stats,
'timestamp' => date('c'),
]);