El turno original no se modifica (queda finalizado igual que antes) — solo se agrega trazabilidad: turnero_muestras.recibida_en_turno_id registra en qué turno se completó una muestra que había quedado pendiente en otra visita. Historial, bandeja y lugar.php ahora muestran un chip/botón "Turno vinculado" en ambos sentidos (origen ⇄ seguimiento) con acceso directo. Además, al abrir un formulario "Datos Toma de Muestras" pendiente para una visita de seguimiento, aparece un botón para cargar las respuestas del último formulario firmado de ese mismo paciente (sin firma ni identidad del profesional anterior) — evita reescribir la historia clínica; la firma y fecha siguen siendo las de hoy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
172 lines
6.8 KiB
PHP
172 lines
6.8 KiB
PHP
<?php
|
|
/**
|
|
* modules/turnero/api/get_bandeja.php
|
|
* GET → lista + stats del día (sesion activa)
|
|
* GET ?turno_id=X → detalle completo de un turno
|
|
*/
|
|
require_once __DIR__ . '/_helpers.php';
|
|
requireTurnero();
|
|
|
|
$pdo = db();
|
|
|
|
$sesionId = (int)($pdo->query(
|
|
"SELECT id FROM turnero_sesiones ORDER BY id DESC LIMIT 1"
|
|
)->fetchColumn() ?: 0);
|
|
|
|
// ── DETALLE ───────────────────────────────────────────────────
|
|
if (isset($_GET['turno_id'])) {
|
|
$tid = (int)$_GET['turno_id'];
|
|
|
|
$turno = $pdo->prepare("
|
|
SELECT t.id, t.codigo, t.estado, t.paciente_nombre, t.inicio_lugar_at, t.fin_lugar_at,
|
|
t.bandeja_visto_at,
|
|
ts.id AS sol_id, ts.numero_orden,
|
|
p.tipo_documento, p.numero_documento, p.fecha_nacimiento, p.telefono,
|
|
l.nombre AS lugar_nombre
|
|
FROM turnero_turnos t
|
|
JOIN turnero_solicitudes ts ON ts.turno_id = t.id
|
|
LEFT JOIN lab_pacientes p ON p.id = ts.paciente_id
|
|
LEFT JOIN turnero_lugares l ON l.id = t.lugar_destino_id
|
|
WHERE t.id = ? LIMIT 1
|
|
");
|
|
$turno->execute([$tid]);
|
|
$data = $turno->fetch(PDO::FETCH_ASSOC);
|
|
if (!$data) jsonError('Turno no encontrado', 404);
|
|
|
|
$solId = (int)$data['sol_id'];
|
|
|
|
// Exámenes agrupados por categoría
|
|
$stmtEx = $pdo->prepare("
|
|
SELECT et.codigo, et.nombre, COALESCE(NULLIF(et.categoria,''),'Otros') AS categoria
|
|
FROM turnero_examen_items tei
|
|
JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
|
WHERE tei.solicitud_id = ?
|
|
ORDER BY categoria, et.nombre
|
|
");
|
|
$stmtEx->execute([$solId]);
|
|
$examenesPorCat = [];
|
|
foreach ($stmtEx->fetchAll(PDO::FETCH_ASSOC) as $e) {
|
|
$examenesPorCat[$e['categoria']][] = $e['codigo'];
|
|
}
|
|
|
|
// Muestras
|
|
$stmtM = $pdo->prepare("
|
|
SELECT tm.id, tm.tipo_muestra, tm.estado, tm.motivo_rechazo, tm.recibida_at
|
|
FROM turnero_muestras tm
|
|
WHERE tm.solicitud_id = ?
|
|
ORDER BY tm.id
|
|
");
|
|
$stmtM->execute([$solId]);
|
|
$muestras = $stmtM->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Consentimientos
|
|
$stmtC = $pdo->prepare("
|
|
SELECT tc.id, tc.estado, tc.token, tc.firmado_at,
|
|
lf.nombre AS formulario_nombre
|
|
FROM turnero_consentimientos tc
|
|
JOIN lab_formularios lf ON lf.id = tc.formulario_id
|
|
WHERE tc.turno_id = ?
|
|
ORDER BY tc.id
|
|
");
|
|
$stmtC->execute([$tid]);
|
|
$consentimientos = $stmtC->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Comentarios (todos los tipos)
|
|
$stmtCom = $pdo->prepare("
|
|
SELECT tipo, usuario_nombre, comentario, creado_at
|
|
FROM turnero_comentarios
|
|
WHERE turno_id = ?
|
|
ORDER BY creado_at ASC
|
|
");
|
|
$stmtCom->execute([$tid]);
|
|
$comentarios = $stmtCom->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Turnos vinculados por muestras pendientes completadas en otra visita (ambos sentidos)
|
|
$relacionados = [];
|
|
$stmtRelFwd = $pdo->prepare("
|
|
SELECT t2.id AS rel_id, t2.codigo AS rel_codigo, s2.fecha AS rel_fecha
|
|
FROM turnero_muestras tm
|
|
JOIN turnero_turnos t2 ON t2.id = tm.recibida_en_turno_id
|
|
JOIN turnero_sesiones s2 ON s2.id = t2.sesion_id
|
|
WHERE tm.solicitud_id = ? AND tm.recibida_en_turno_id IS NOT NULL
|
|
");
|
|
$stmtRelFwd->execute([$solId]);
|
|
foreach ($stmtRelFwd->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
|
$relacionados[] = ['turno_id' => (int)$r['rel_id'], 'codigo' => $r['rel_codigo'], 'fecha' => $r['rel_fecha'], 'direccion' => 'seguimiento'];
|
|
}
|
|
$stmtRelBack = $pdo->prepare("
|
|
SELECT t1.id AS rel_id, t1.codigo AS rel_codigo, s1.fecha AS rel_fecha
|
|
FROM turnero_muestras tm
|
|
JOIN turnero_solicitudes ts1 ON ts1.id = tm.solicitud_id
|
|
JOIN turnero_turnos t1 ON t1.id = ts1.turno_id
|
|
JOIN turnero_sesiones s1 ON s1.id = t1.sesion_id
|
|
WHERE tm.recibida_en_turno_id = ?
|
|
");
|
|
$stmtRelBack->execute([$tid]);
|
|
foreach ($stmtRelBack->fetchAll(PDO::FETCH_ASSOC) as $r) {
|
|
$relacionados[] = ['turno_id' => (int)$r['rel_id'], 'codigo' => $r['rel_codigo'], 'fecha' => $r['rel_fecha'], 'direccion' => 'origen'];
|
|
}
|
|
|
|
jsonOk([
|
|
'turno' => $data,
|
|
'examenes_por_cat'=> $examenesPorCat,
|
|
'muestras' => $muestras,
|
|
'consentimientos' => $consentimientos,
|
|
'comentarios' => $comentarios,
|
|
'relacionados' => $relacionados,
|
|
]);
|
|
}
|
|
|
|
// ── LISTA ─────────────────────────────────────────────────────
|
|
$desde = $_GET['desde'] ?? null;
|
|
$hasta = $_GET['hasta'] ?? null;
|
|
|
|
if ($desde && $hasta) {
|
|
$whereClause = "DATE(t.inicio_lugar_at) BETWEEN ? AND ?";
|
|
$params = [$desde, $hasta];
|
|
} else {
|
|
$whereClause = "t.sesion_id = ?";
|
|
$params = [$sesionId];
|
|
}
|
|
|
|
$stmt = $pdo->prepare("
|
|
SELECT t.id, t.codigo, t.paciente_nombre, t.estado,
|
|
t.inicio_lugar_at, t.fin_lugar_at, t.bandeja_visto_at, t.muestra_espera_at,
|
|
ts.numero_orden,
|
|
l.nombre AS lugar_nombre,
|
|
GROUP_CONCAT(DISTINCT et.codigo ORDER BY et.codigo SEPARATOR ' ') AS examenes_txt,
|
|
SUM(tc.tipo = 'recepcion') AS com_recepcion,
|
|
SUM(tc.tipo = 'muestras') AS com_muestras,
|
|
SUM(tc.tipo = 'general') AS com_general,
|
|
(SELECT COUNT(*) FROM turnero_muestras tm2 WHERE tm2.solicitud_id = ts.id AND tm2.estado = 'rechazada') AS muestras_pendientes
|
|
FROM turnero_turnos t
|
|
JOIN turnero_solicitudes ts ON ts.turno_id = t.id
|
|
JOIN turnero_lugares l ON l.id = t.lugar_destino_id
|
|
LEFT JOIN turnero_examen_items tei ON tei.solicitud_id = ts.id
|
|
LEFT JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
|
LEFT JOIN turnero_comentarios tc ON tc.turno_id = t.id
|
|
WHERE $whereClause AND t.inicio_lugar_at IS NOT NULL
|
|
GROUP BY t.id
|
|
ORDER BY ts.numero_orden ASC
|
|
");
|
|
$stmt->execute($params);
|
|
$todos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$pendientes = array_values(array_filter($todos, fn($t) => $t['bandeja_visto_at'] === null));
|
|
$vistos = array_values(array_filter($todos, fn($t) => $t['bandeja_visto_at'] !== null));
|
|
|
|
$muestrasPendientes = count(array_filter($todos, fn($t) => (int)$t['muestras_pendientes'] > 0));
|
|
$prolongadasPendientes = count(array_filter($todos, fn($t) => !empty($t['muestra_espera_at']) && empty($t['fin_lugar_at'])));
|
|
|
|
jsonOk([
|
|
'pendientes' => $pendientes,
|
|
'vistos' => $vistos,
|
|
'stats' => [
|
|
'total' => count($todos),
|
|
'pendientes' => count($pendientes),
|
|
'vistos' => count($vistos),
|
|
'muestras_pendientes' => $muestrasPendientes,
|
|
'prolongadas_pendientes'=> $prolongadasPendientes,
|
|
],
|
|
]);
|