Dashboard del turnero: desglose por recepcionista y por bacteriólogo
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
* - resumen global (total, atendidos, pendientes, ausentes, tiempo promedio)
|
||||
* - desglose por prioridad
|
||||
* - desglose por lugar
|
||||
* - desglose por recepcionista y por bacteriólogo (quién atendió a cuántos)
|
||||
* - lista de turnos del día (para tabla detalle)
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
@@ -41,10 +42,12 @@ if (!$sesion) {
|
||||
'tiempo_espera_promedio_min' => null,
|
||||
'tiempo_servicio_promedio_min' => null,
|
||||
],
|
||||
'por_prioridad' => [],
|
||||
'por_lugar' => [],
|
||||
'consent_stats' => [],
|
||||
'turnos' => [],
|
||||
'por_prioridad' => [],
|
||||
'por_lugar' => [],
|
||||
'por_recepcionista' => [],
|
||||
'por_bacteriologo' => [],
|
||||
'consent_stats' => [],
|
||||
'turnos' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -125,6 +128,55 @@ $stmtLug = $pdo->prepare(
|
||||
$stmtLug->execute([$sesionId]);
|
||||
$porLugar = $stmtLug->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 4b. Desglose por recepcionista ────────────────────────────
|
||||
// Mismo molde que el ranking de enfermeras de lab_domicilios
|
||||
// (api/lab/get_metricas.php). atendido_recepcion_por guarda al PRIMER
|
||||
// recepcionista que tomó el turno (COALESCE en cambiar_estado.php).
|
||||
$stmtRec = $pdo->prepare(
|
||||
"SELECT u.id,
|
||||
COALESCE(NULLIF(u.full_name, ''), u.username) AS nombre,
|
||||
COUNT(t.id) AS total,
|
||||
SUM(t.estado IN ('finalizado','en_servicio','en_espera_lugar')) AS atendidos,
|
||||
SUM(t.estado = 'ausente') AS ausentes,
|
||||
SUM(t.estado = 'cancelado') AS cancelados,
|
||||
ROUND(AVG(
|
||||
CASE
|
||||
WHEN t.fin_recepcion_at IS NOT NULL AND t.inicio_recepcion_at IS NOT NULL
|
||||
THEN TIMESTAMPDIFF(SECOND, t.inicio_recepcion_at, t.fin_recepcion_at) / 60.0
|
||||
END
|
||||
), 1) AS tiempo_promedio_min
|
||||
FROM turnero_turnos t
|
||||
JOIN admin_users u ON u.id = t.atendido_recepcion_por
|
||||
WHERE t.sesion_id = ?
|
||||
GROUP BY u.id, u.full_name, u.username
|
||||
ORDER BY atendidos DESC, total DESC"
|
||||
);
|
||||
$stmtRec->execute([$sesionId]);
|
||||
$porRecepcionista = $stmtRec->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 4c. Desglose por bacteriólogo (quien atendió en el lugar) ──
|
||||
$stmtBac = $pdo->prepare(
|
||||
"SELECT u.id,
|
||||
COALESCE(NULLIF(u.full_name, ''), u.username) AS nombre,
|
||||
COUNT(t.id) AS total,
|
||||
SUM(t.estado = 'finalizado') AS finalizados,
|
||||
SUM(t.estado = 'en_servicio') AS en_servicio,
|
||||
SUM(t.estado = 'ausente') AS ausentes,
|
||||
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_promedio_min
|
||||
FROM turnero_turnos t
|
||||
JOIN admin_users u ON u.id = t.atendido_lugar_por
|
||||
WHERE t.sesion_id = ?
|
||||
GROUP BY u.id, u.full_name, u.username
|
||||
ORDER BY finalizados DESC, total DESC"
|
||||
);
|
||||
$stmtBac->execute([$sesionId]);
|
||||
$porBacteriologo = $stmtBac->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ── 5. Lista de turnos del día ────────────────────────────────
|
||||
$stmtTurnos = $pdo->prepare(
|
||||
"SELECT t.id, t.codigo, t.numero, t.estado,
|
||||
@@ -157,22 +209,47 @@ $stmtTurnos = $pdo->prepare(
|
||||
$stmtTurnos->execute([$sesionId]);
|
||||
$turnos = $stmtTurnos->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Enriquecer con exámenes y comentarios
|
||||
foreach ($turnos as &$turno) {
|
||||
// Enriquecer con exámenes y comentarios — en lote.
|
||||
// Antes eran 2 consultas por turno dentro del foreach (N+1): con 80 turnos en
|
||||
// el día eran 160 consultas evitables. Mismo patrón que get_historial.php.
|
||||
$turnoIds = array_column($turnos, 'id');
|
||||
$examenesPorTurno = [];
|
||||
$comentariosPorTurno = [];
|
||||
|
||||
if ($turnoIds) {
|
||||
$ph = implode(',', array_fill(0, count($turnoIds), '?'));
|
||||
|
||||
$stmtEx = $pdo->prepare(
|
||||
"SELECT DISTINCT et.nombre FROM turnero_examen_items tei
|
||||
JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
||||
WHERE tei.solicitud_id = (SELECT id FROM turnero_solicitudes WHERE turno_id = ? LIMIT 1)"
|
||||
"SELECT DISTINCT ts.turno_id, et.nombre
|
||||
FROM turnero_solicitudes ts
|
||||
JOIN turnero_examen_items tei ON tei.solicitud_id = ts.id
|
||||
JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
||||
WHERE ts.turno_id IN ($ph)
|
||||
ORDER BY et.nombre ASC"
|
||||
);
|
||||
$stmtEx->execute([$turno['id']]);
|
||||
$turno['examenes'] = $stmtEx->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmtEx->execute($turnoIds);
|
||||
foreach ($stmtEx->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||
$examenesPorTurno[(int)$row['turno_id']][] = ['nombre' => $row['nombre']];
|
||||
}
|
||||
|
||||
$stmtCom = $pdo->prepare(
|
||||
"SELECT usuario_nombre, comentario, tipo, creado_at
|
||||
FROM turnero_comentarios WHERE turno_id = ? ORDER BY creado_at ASC"
|
||||
"SELECT turno_id, usuario_nombre, comentario, tipo, creado_at
|
||||
FROM turnero_comentarios
|
||||
WHERE turno_id IN ($ph)
|
||||
ORDER BY turno_id, creado_at ASC"
|
||||
);
|
||||
$stmtCom->execute([$turno['id']]);
|
||||
$turno['comentarios'] = $stmtCom->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmtCom->execute($turnoIds);
|
||||
foreach ($stmtCom->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||
$tid = (int)$row['turno_id'];
|
||||
unset($row['turno_id']);
|
||||
$comentariosPorTurno[$tid][] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($turnos as &$turno) {
|
||||
$tid = (int)$turno['id'];
|
||||
$turno['examenes'] = $examenesPorTurno[$tid] ?? [];
|
||||
$turno['comentarios'] = $comentariosPorTurno[$tid] ?? [];
|
||||
}
|
||||
unset($turno);
|
||||
|
||||
@@ -201,6 +278,8 @@ jsonOk([
|
||||
'resumen' => $resumen,
|
||||
'por_prioridad' => $porPrioridad,
|
||||
'por_lugar' => $porLugar,
|
||||
'por_recepcionista' => $porRecepcionista,
|
||||
'por_bacteriologo' => $porBacteriologo,
|
||||
'consent_stats' => $consentStats,
|
||||
'turnos' => $turnos,
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user