Hasta ahora, para que el paciente firmara el consentimiento de bienvenida había que girarle el monitor a la recepcionista o pasarle el mouse: el botón Firmar abre el formulario en la pantalla de ella. Se agrega una pantalla aparte (/erp.php?m=turnero&v=firma) para poner frente al paciente. Sola, sin que la recepcionista haga nada: cuando el turno entra a ese puesto y le falta el F-LAB-01, aparece su nombre y un botón grande de firmar; al terminar dice gracias y vuelve a reposo. Reutiliza lo que ya existía: el formulario de ver_formulario_enviado.php, el aviso 'turneroFirmado' que ya emite al firmar, y el sondeo de recepción, que seguirá poniendo el renglón en verde sin cambios. Sobre el acceso: va en PUBLIC_ROUTES porque nadie va a iniciar sesión cada mañana en una tablet que manipula el público. No queda abierta: se identifica por la cookie del dispositivo, y sin ella no muestra ningún dato. El endpoint devuelve solo el turno que está en ese puesto en ese instante —no permite buscar, ni ver otros, ni consultar historial— y descarta turnos de días anteriores, igual que el televisor. La tablet debe quedar en modo kiosco. Falta registrar el dispositivo de Recepción 4 desde Configuración; hoy no tiene ninguno. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
135 lines
5.0 KiB
PHP
135 lines
5.0 KiB
PHP
<?php
|
|
/**
|
|
* GET /modules/turnero/api/get_firma_pendiente.php
|
|
*
|
|
* Le dice a la tablet del paciente qué mostrar: si hay alguien siendo atendido
|
|
* en su puesto y le falta firmar el consentimiento de bienvenida (F-LAB-01).
|
|
*
|
|
* SIN SESIÓN DE OPERADOR, a propósito: esta tablet la manipula el público y
|
|
* nadie va a iniciar sesión en ella cada mañana. Se identifica por la cookie
|
|
* del dispositivo, que es un token de 64 caracteres registrado en Configuración.
|
|
*
|
|
* Por eso devuelve lo mínimo: el turno que está en ese puesto en este instante
|
|
* y nada más. No permite consultar otros turnos, ni buscar, ni ver historial.
|
|
* Sin dispositivo reconocido no responde nada.
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../../config/config.php';
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('X-Content-Type-Options: nosniff');
|
|
header('Cache-Control: no-store');
|
|
|
|
/** El único formulario que se firma en esta tablet: el de bienvenida. */
|
|
const FORMULARIO_BIENVENIDA = 17;
|
|
|
|
function responder(array $datos): void {
|
|
echo json_encode($datos, JSON_UNESCAPED_UNICODE);
|
|
exit;
|
|
}
|
|
|
|
$pdo = Database::getInstance()->getConnection();
|
|
|
|
// ── 1. ¿Qué puesto es esta tablet? ────────────────────────────────────────
|
|
// Solo por token de navegador. La IP no sirve aquí: varias tablets salen por
|
|
// la misma y acabaríamos mostrándole a un paciente los datos de otro puesto.
|
|
$token = trim($_COOKIE['turnero_token'] ?? '');
|
|
if ($token === '') {
|
|
responder(['ok' => false, 'motivo' => 'sin_dispositivo']);
|
|
}
|
|
|
|
$stmt = $pdo->prepare(
|
|
"SELECT td.lugar_id, td.nombre AS dispositivo, tl.nombre AS lugar, tl.tipo
|
|
FROM turnero_dispositivos td
|
|
JOIN turnero_lugares tl ON tl.id = td.lugar_id
|
|
WHERE td.token = ? AND td.activo = 1
|
|
LIMIT 1"
|
|
);
|
|
$stmt->execute([$token]);
|
|
$disp = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$disp || $disp['tipo'] !== 'recepcion') {
|
|
responder(['ok' => false, 'motivo' => 'sin_dispositivo']);
|
|
}
|
|
|
|
// ── 2. ¿Hay alguien siendo atendido ahí ahora? ────────────────────────────
|
|
// Mismo criterio que la pantalla del televisor: el turno vale hasta la
|
|
// medianoche de su día, para no mostrar a un paciente que ya se fue.
|
|
// La sesión está abierta mientras fin_at siga en nulo; no hay columna de estado.
|
|
$stmt = $pdo->prepare(
|
|
"SELECT t.id, t.codigo, t.paciente_id, t.paciente_nombre
|
|
FROM turnero_turnos t
|
|
JOIN turnero_sesiones s ON s.id = t.sesion_id
|
|
WHERE t.estado = 'en_recepcion'
|
|
AND t.recepcion_desk_id = ?
|
|
AND DATE(t.llamado_recepcion_at) = CURDATE()
|
|
AND s.fin_at IS NULL
|
|
ORDER BY t.llamado_recepcion_at DESC
|
|
LIMIT 1"
|
|
);
|
|
$stmt->execute([(int)$disp['lugar_id']]);
|
|
$turno = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$turno) {
|
|
responder(['ok' => true, 'estado' => 'reposo', 'lugar' => $disp['lugar']]);
|
|
}
|
|
|
|
// Sin paciente vinculado no hay a quién atribuirle la firma
|
|
if (empty($turno['paciente_id'])) {
|
|
responder(['ok' => true, 'estado' => 'reposo', 'lugar' => $disp['lugar']]);
|
|
}
|
|
|
|
// ── 3. ¿Le falta firmar el consentimiento de bienvenida? ──────────────────
|
|
$stmt = $pdo->prepare(
|
|
"SELECT token, estado FROM turnero_consentimientos
|
|
WHERE turno_id = ? AND formulario_id = ?
|
|
LIMIT 1"
|
|
);
|
|
$stmt->execute([(int)$turno['id'], FORMULARIO_BIENVENIDA]);
|
|
$consent = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($consent && in_array($consent['estado'], ['firmado', 'rechazado'], true)) {
|
|
responder([
|
|
'ok' => true,
|
|
'estado' => 'firmado',
|
|
'turno_id' => (int)$turno['id'],
|
|
'codigo' => $turno['codigo'],
|
|
]);
|
|
}
|
|
|
|
// Si el consentimiento todavía no existe se crea aquí. Es lo que permite que
|
|
// la tablet aparezca sola, sin que la recepcionista tenga que mandarlo.
|
|
if (!$consent) {
|
|
$tokenFirma = sprintf(
|
|
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
|
mt_rand(0, 0xffff),
|
|
mt_rand(0, 0x0fff) | 0x4000,
|
|
mt_rand(0, 0x3fff) | 0x8000,
|
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
|
);
|
|
$ins = $pdo->prepare(
|
|
"INSERT IGNORE INTO turnero_consentimientos
|
|
(turno_id, formulario_id, token, estado, creado_por)
|
|
VALUES (?, ?, ?, 'pendiente', NULL)"
|
|
);
|
|
$ins->execute([(int)$turno['id'], FORMULARIO_BIENVENIDA, $tokenFirma]);
|
|
|
|
// INSERT IGNORE puede no haber insertado si otra petición se adelantó:
|
|
// se relee para quedarse con el token que realmente quedó guardado.
|
|
$stmt->execute([(int)$turno['id'], FORMULARIO_BIENVENIDA]);
|
|
$consent = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
if (!$consent) {
|
|
responder(['ok' => false, 'motivo' => 'no_se_pudo_crear']);
|
|
}
|
|
}
|
|
|
|
responder([
|
|
'ok' => true,
|
|
'estado' => 'por_firmar',
|
|
'turno_id' => (int)$turno['id'],
|
|
'codigo' => $turno['codigo'],
|
|
'paciente' => $turno['paciente_nombre'],
|
|
'url' => BASE_URL . 'ver_formulario_enviado.php?token=' . urlencode($consent['token']),
|
|
]);
|