up
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
/**
|
||||
* modules/turnero/api/get_dashboard.php
|
||||
* GET ?fecha=YYYY-MM-DD (por defecto = hoy)
|
||||
*
|
||||
* Devuelve métricas del día para el dashboard del turnero:
|
||||
* - resumen global (total, atendidos, pendientes, ausentes, tiempo promedio)
|
||||
* - desglose por prioridad
|
||||
* - desglose por lugar
|
||||
* - lista de turnos del día (para tabla detalle)
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
|
||||
requireTurnero();
|
||||
requireMethod('GET');
|
||||
|
||||
$fecha = trim($_GET['fecha'] ?? '');
|
||||
if ($fecha === '' || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $fecha)) {
|
||||
$fecha = date('Y-m-d');
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// ── 1. Sesión del día ─────────────────────────────────────────
|
||||
$stmtSesion = $pdo->prepare(
|
||||
'SELECT id, inicio_at, fin_at FROM turnero_sesiones WHERE fecha = ? LIMIT 1'
|
||||
);
|
||||
$stmtSesion->execute([$fecha]);
|
||||
$sesion = $stmtSesion->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$sesion) {
|
||||
jsonOk([
|
||||
'fecha' => $fecha,
|
||||
'sesion' => null,
|
||||
'resumen' => ['total' => 0, 'atendidos' => 0, 'en_espera' => 0,
|
||||
'ausentes' => 0, 'cancelados' => 0, 'tiempo_promedio_min' => null],
|
||||
'por_prioridad' => [],
|
||||
'por_lugar' => [],
|
||||
'turnos' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
$sesionId = (int)$sesion['id'];
|
||||
|
||||
// ── 2. Resumen global ─────────────────────────────────────────
|
||||
$stmtRes = $pdo->prepare(
|
||||
"SELECT
|
||||
COUNT(*) AS total,
|
||||
SUM(estado IN ('finalizado','en_servicio')) AS atendidos,
|
||||
SUM(estado IN ('espera','en_recepcion','en_espera_lugar')) AS en_espera,
|
||||
SUM(estado = 'ausente') AS ausentes,
|
||||
SUM(estado = 'cancelado') AS cancelados,
|
||||
ROUND(
|
||||
AVG(
|
||||
CASE
|
||||
WHEN inicio_recepcion_at IS NOT NULL AND creado_at IS NOT NULL
|
||||
THEN TIMESTAMPDIFF(SECOND, creado_at, inicio_recepcion_at) / 60.0
|
||||
END
|
||||
), 1
|
||||
) AS tiempo_espera_promedio_min,
|
||||
ROUND(
|
||||
AVG(
|
||||
CASE
|
||||
WHEN fin_lugar_at IS NOT NULL AND inicio_lugar_at IS NOT NULL
|
||||
THEN TIMESTAMPDIFF(SECOND, inicio_lugar_at, fin_lugar_at) / 60.0
|
||||
END
|
||||
), 1
|
||||
) AS tiempo_servicio_promedio_min
|
||||
FROM turnero_turnos
|
||||
WHERE sesion_id = ?"
|
||||
);
|
||||
$stmtRes->execute([$sesionId]);
|
||||
$resumen = $stmtRes->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 3. Desglose por prioridad ─────────────────────────────────
|
||||
$stmtPri = $pdo->prepare(
|
||||
"SELECT p.codigo, p.nombre, p.color,
|
||||
COUNT(t.id) AS total,
|
||||
SUM(t.estado IN ('finalizado','en_servicio')) AS atendidos,
|
||||
SUM(t.estado IN ('espera','en_recepcion','en_espera_lugar')) AS pendientes,
|
||||
SUM(t.estado = 'ausente') AS ausentes
|
||||
FROM turnero_turnos t
|
||||
JOIN turnero_prioridades p ON p.id = t.prioridad_id
|
||||
WHERE t.sesion_id = ?
|
||||
GROUP BY p.id
|
||||
ORDER BY p.orden_peso ASC"
|
||||
);
|
||||
$stmtPri->execute([$sesionId]);
|
||||
$porPrioridad = $stmtPri->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 4. Desglose por lugar ─────────────────────────────────────
|
||||
$stmtLug = $pdo->prepare(
|
||||
"SELECT l.nombre AS lugar,
|
||||
COUNT(t.id) AS total,
|
||||
SUM(t.estado IN ('finalizado','en_servicio')) AS atendidos,
|
||||
SUM(t.estado IN ('en_espera_lugar')) AS en_espera,
|
||||
ROUND(AVG(
|
||||
CASE
|
||||
WHEN t.fin_lugar_at IS NOT NULL AND t.inicio_lugar_at IS NOT NULL
|
||||
THEN TIMESTAMPDIFF(SECOND, t.inicio_lugar_at, t.fin_lugar_at) / 60.0
|
||||
END
|
||||
), 1) AS tiempo_servicio_promedio_min
|
||||
FROM turnero_turnos t
|
||||
JOIN turnero_lugares l ON l.id = t.lugar_destino_id
|
||||
WHERE t.sesion_id = ?
|
||||
GROUP BY l.id
|
||||
ORDER BY l.sort_order ASC, l.nombre ASC"
|
||||
);
|
||||
$stmtLug->execute([$sesionId]);
|
||||
$porLugar = $stmtLug->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 5. Lista de turnos del día ────────────────────────────────
|
||||
$stmtTurnos = $pdo->prepare(
|
||||
"SELECT t.id, t.codigo, t.numero, t.estado,
|
||||
t.paciente_nombre, t.paciente_cel,
|
||||
t.creado_at, t.inicio_recepcion_at, t.fin_recepcion_at,
|
||||
t.inicio_lugar_at, t.fin_lugar_at,
|
||||
p.codigo AS prioridad_codigo, p.nombre AS prioridad_nombre, p.color AS prioridad_color,
|
||||
l.nombre AS lugar_nombre,
|
||||
s.nombre_completo AS paciente_bd,
|
||||
ROUND(TIMESTAMPDIFF(SECOND, t.creado_at, COALESCE(t.inicio_recepcion_at, NOW())) / 60.0, 1) AS espera_min,
|
||||
ROUND(TIMESTAMPDIFF(SECOND, t.inicio_lugar_at, COALESCE(t.fin_lugar_at, NOW())) / 60.0, 1) AS servicio_min
|
||||
FROM turnero_turnos t
|
||||
JOIN turnero_prioridades p ON p.id = t.prioridad_id
|
||||
LEFT JOIN turnero_lugares l ON l.id = t.lugar_destino_id
|
||||
LEFT JOIN turnero_solicitudes ts ON ts.turno_id = t.id
|
||||
LEFT JOIN lab_pacientes s ON s.id = ts.paciente_id
|
||||
WHERE t.sesion_id = ?
|
||||
ORDER BY t.numero ASC"
|
||||
);
|
||||
$stmtTurnos->execute([$sesionId]);
|
||||
$turnos = $stmtTurnos->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 6. Consentimientos del día ────────────────────────────────
|
||||
$stmtcons = $pdo->prepare(
|
||||
"SELECT tc.estado, COUNT(*) AS cnt
|
||||
FROM turnero_consentimientos tc
|
||||
JOIN turnero_turnos t ON t.id = tc.turno_id
|
||||
WHERE t.sesion_id = ?
|
||||
GROUP BY tc.estado"
|
||||
);
|
||||
$stmtcons->execute([$sesionId]);
|
||||
$consentStats = [];
|
||||
foreach ($stmtcons->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
||||
$consentStats[$r['estado']] = (int)$r['cnt'];
|
||||
}
|
||||
|
||||
jsonOk([
|
||||
'fecha' => $fecha,
|
||||
'sesion' => [
|
||||
'id' => $sesionId,
|
||||
'inicio' => $sesion['inicio_at'] ? date('H:i', strtotime($sesion['inicio_at'])) : null,
|
||||
'fin' => $sesion['fin_at'] ? date('H:i', strtotime($sesion['fin_at'])) : null,
|
||||
'abierta' => $sesion['fin_at'] === null,
|
||||
],
|
||||
'resumen' => $resumen,
|
||||
'por_prioridad' => $porPrioridad,
|
||||
'por_lugar' => $porLugar,
|
||||
'consent_stats' => $consentStats,
|
||||
'turnos' => $turnos,
|
||||
]);
|
||||
Reference in New Issue
Block a user