Files
whatsapp/modules/turnero/api/cancelar_toma_pendiente.php
Lizandro GuarnizoandClaude Opus 5 487673dc0f Historial y bandeja: mostrar qué pasó con cada turno
Para saber quién retiró un formulario de un turno había que consultar la base
a mano. La información existía, pero repartida en cinco tablas y sin ninguna
pantalla que la juntara.

get_traza_turno.php arma una sola línea de tiempo con el recorrido del turno
(con quién atendió en cada punto), los documentos enviados y firmados, los
comentarios del personal —donde caen las ausencias con su motivo—, las
muestras recibidas y rechazadas, y las acciones administrativas auditadas.
Se muestra en el detalle desplegable de Historial y en el panel de Bandeja.

Del chat de WhatsApp solo se indica cuántos mensajes hubo ese día, con enlace
a la conversación. Volcar los mensajes sería esparcir datos personales del
paciente por una pantalla de consulta.

Y la parte que faltaba: cinco acciones no dejaban ningún rastro. Ahora se
auditan cambiar_estado, resetear_consentimiento, resetear_toma,
vincular_paciente y cancelar_toma_pendiente — las que borran una firma,
descartan datos de un protocolo o mandan la atención a otra historia clínica.
La auditoría va en try/catch: si falla, no tumba la operación.

La respuesta declara en `sinRastro` lo que el sistema todavía no registra,
para que la ausencia de un evento no se lea como prueba de que no ocurrió.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 12:33:55 -05:00

66 lines
2.4 KiB
PHP

<?php
/**
* POST /modules/turnero/api/cancelar_toma_pendiente.php
* Marca una toma progresiva en_progreso como rechazada (paciente no quiere continuar).
* Body: { consentimiento_id }
*/
require_once __DIR__ . '/_helpers.php';
require_once __DIR__ . '/../../../classes/lab/ActividadAdmin.php';
requireMethod('POST');
requireTurnero();
$body = inputJson();
$consentId = (int)($body['consentimiento_id'] ?? 0);
$turnoId = (int)($body['turno_id'] ?? 0);
if (!$consentId) jsonError('consentimiento_id requerido.');
if (!$turnoId) jsonError('turno_id requerido.');
$pdo = db();
// Verificar que el consentimiento pertenece al mismo paciente que el turno activo.
// Previene que un turnero cancele tomas de pacientes que no tiene abiertos (IDOR).
$stmt = $pdo->prepare(
"UPDATE turnero_consentimientos tc
JOIN turnero_turnos t_old ON t_old.id = tc.turno_id
JOIN turnero_turnos t_cur ON t_cur.id = ? AND t_cur.paciente_id IS NOT NULL
AND t_cur.paciente_id = t_old.paciente_id
SET tc.estado = 'rechazado'
WHERE tc.id = ? AND tc.estado = 'en_progreso'"
);
$stmt->execute([$turnoId, $consentId]);
if ($stmt->rowCount() === 0) jsonError('Toma no encontrada o el paciente no coincide.', 404);
// Cancelar una toma pendiente cierra un protocolo que quedó a medias en otra
// visita: conviene saber quién lo dio por terminado.
try {
$inf = $pdo->prepare(
"SELECT tc.turno_id, t.codigo, f.nombre AS formulario
FROM turnero_consentimientos tc
JOIN turnero_turnos t ON t.id = tc.turno_id
JOIN lab_formularios f ON f.id = tc.formulario_id
WHERE tc.id = ? LIMIT 1"
);
$inf->execute([$consentId]);
$d = $inf->fetch(PDO::FETCH_ASSOC) ?: [];
(new ActividadAdmin())->registrar(
adminId(),
'turnero',
'cancelar_toma_pendiente',
$consentId,
[
// Se registra bajo el turno donde se hizo la cancelación, que es
// donde alguien la va a buscar en el historial.
'turno_id' => $turnoId,
'turno_origen_id' => isset($d['turno_id']) ? (int)$d['turno_id'] : null,
'turno_origen' => $d['codigo'] ?? null,
'formulario_nombre' => $d['formulario'] ?? null,
]
);
} catch (\Throwable $e) {
error_log('[cancelar_toma_pendiente] auditoría: ' . $e->getMessage());
}
jsonOk(['cancelado' => true]);