From 34004b4d98b8735ca2a9ece26b8a8d80c62f2ae5 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 3 Jul 2026 00:07:05 -0500 Subject: [PATCH] =?UTF-8?q?feat(turnero):=20opci=C3=B3n=20solo=20entrega?= =?UTF-8?q?=20de=20muestras=20con=20prioridad=20y=20badge=20naranja=20en?= =?UTF-8?q?=20cola?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- migrations/20260703_solo_muestras.sql | 4 ++++ modules/turnero/api/create_solicitud.php | 9 +++++---- modules/turnero/api/get_cola.php | 18 ++++++++++-------- modules/turnero/views/lugar.php | 14 ++++++++++++-- modules/turnero/views/recepcion.php | 24 ++++++++++++++++++++---- 5 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 migrations/20260703_solo_muestras.sql diff --git a/migrations/20260703_solo_muestras.sql b/migrations/20260703_solo_muestras.sql new file mode 100644 index 0000000..714e71f --- /dev/null +++ b/migrations/20260703_solo_muestras.sql @@ -0,0 +1,4 @@ +ALTER TABLE turnero_solicitudes + ADD COLUMN solo_muestras TINYINT(1) NOT NULL DEFAULT 0 + COMMENT 'Paciente solo entrega muestras, sin exámenes a registrar' + AFTER embarazada; diff --git a/modules/turnero/api/create_solicitud.php b/modules/turnero/api/create_solicitud.php index 906414b..bf806e4 100644 --- a/modules/turnero/api/create_solicitud.php +++ b/modules/turnero/api/create_solicitud.php @@ -31,6 +31,7 @@ $metodoPago = isset($datos['metodo_pago']) ? trim((string) $datos['metodo_p $obs = isset($datos['observaciones']) ? trim((string) $datos['observaciones']) : null; $numOrden = isset($datos['numero_orden']) ? trim((string) $datos['numero_orden']) : null; $embarazada = !empty($datos['embarazada']) ? 1 : 0; +$soloMuestras = !empty($datos['solo_muestras']) ? 1 : 0; $pagosDetalle = null; if ($metodoPago === 'combinado' && isset($datos['pagos_detalle']) && is_array($datos['pagos_detalle'])) { $pd = $datos['pagos_detalle']; @@ -46,7 +47,7 @@ if ($numOrden === '') $numOrden = null; if ($turnoId <= 0) jsonError('turno_id inválido.'); if ($pacienteId <= 0) jsonError('paciente_id inválido.'); if ($lugarId <= 0) jsonError('lugar_id inválido.'); -if (empty($examIds)) jsonError('Debe seleccionar al menos un examen.'); +if (empty($examIds) && !$soloMuestras) jsonError('Debe seleccionar al menos un examen.'); $metodosValidos = ['efectivo', 'transferencia', 'tarjeta', 'eps', 'cortesia', 'combinado', '']; if ($metodoPago && !in_array($metodoPago, $metodosValidos, true)) { @@ -113,12 +114,12 @@ try { $stmt = $pdo->prepare( "INSERT INTO turnero_solicitudes - (turno_id, paciente_id, lugar_id, numero_orden, total_cobrado, metodo_pago, pagos_detalle, observaciones, embarazada, creado_por) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + (turno_id, paciente_id, lugar_id, numero_orden, total_cobrado, metodo_pago, pagos_detalle, observaciones, embarazada, solo_muestras, creado_por) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ); $stmt->execute([ $turnoId, $pacienteId, $lugarId, $numOrden, - $total, $metodoPago ?: null, $pagosDetalle, $obs ?: null, $embarazada, adminId(), + $total, $metodoPago ?: null, $pagosDetalle, $obs ?: null, $embarazada, $soloMuestras, adminId(), ]); $solicitudId = (int) $pdo->lastInsertId(); diff --git a/modules/turnero/api/get_cola.php b/modules/turnero/api/get_cola.php index 92fe407..748c27d 100644 --- a/modules/turnero/api/get_cola.php +++ b/modules/turnero/api/get_cola.php @@ -50,21 +50,20 @@ if ($sesionCerrada) { // ── Cola según área ─────────────────────────────────────────── if ($area === 'recepcion') { // Recepción: todos los turnos en espera/en_recepcion - $inEstados = "'espera', 'en_recepcion'"; - $filtroLugar = ''; - $bindsCola = [$sesionId]; - + $inEstados = "'espera', 'en_recepcion'"; $stmt = $pdo->prepare( "SELECT t.id, t.codigo, t.numero, t.estado, t.paciente_nombre, t.recepcion_desk_id, t.creado_at, t.llamado_recepcion_at, t.llamado_lugar_at, p.codigo AS prioridad_codigo, p.nombre AS prioridad_nombre, - p.color AS prioridad_color, p.orden_peso + p.color AS prioridad_color, p.orden_peso, + COALESCE(s.solo_muestras, 0) AS solo_muestras FROM turnero_turnos t JOIN turnero_prioridades p ON p.id = t.prioridad_id + LEFT JOIN turnero_solicitudes s ON s.turno_id = t.id WHERE t.sesion_id = ? AND t.estado IN ($inEstados) ORDER BY p.orden_peso ASC, t.creado_at ASC" ); - $stmt->execute($bindsCola); + $stmt->execute([$sesionId]); } else { // Lugar: cola = en_espera_lugar del grupo + en_servicio en ESTA estación $grupoIds = lugarIdsDeGrupo($lugarId); @@ -73,13 +72,15 @@ if ($area === 'recepcion') { $cols = "t.id, t.codigo, t.numero, t.estado, t.paciente_nombre, t.recepcion_desk_id, t.creado_at, t.llamado_recepcion_at, t.llamado_lugar_at, p.codigo AS prioridad_codigo, p.nombre AS prioridad_nombre, - p.color AS prioridad_color, p.orden_peso"; + p.color AS prioridad_color, p.orden_peso, + COALESCE(s.solo_muestras, 0) AS solo_muestras"; $stmt = $pdo->prepare( "SELECT * FROM ( (SELECT $cols FROM turnero_turnos t JOIN turnero_prioridades p ON p.id = t.prioridad_id + LEFT JOIN turnero_solicitudes s ON s.turno_id = t.id WHERE t.sesion_id = ? AND t.estado = 'en_espera_lugar' AND t.lugar_destino_id IN ($inLugares)) @@ -87,11 +88,12 @@ if ($area === 'recepcion') { (SELECT $cols FROM turnero_turnos t JOIN turnero_prioridades p ON p.id = t.prioridad_id + LEFT JOIN turnero_solicitudes s ON s.turno_id = t.id WHERE t.sesion_id = ? AND t.estado = 'en_servicio' AND t.lugar_destino_id = ?) ) AS cola_union - ORDER BY orden_peso ASC, creado_at ASC" + ORDER BY solo_muestras DESC, orden_peso ASC, creado_at ASC" ); $stmt->execute([$sesionId, $sesionId, $lugarId]); } diff --git a/modules/turnero/views/lugar.php b/modules/turnero/views/lugar.php index 7055922..d16936b 100644 --- a/modules/turnero/views/lugar.php +++ b/modules/turnero/views/lugar.php @@ -465,14 +465,24 @@ function renderCola(snap) { border-radius:7px;padding:5px 9px;font-size:.78rem;cursor:pointer"> `; + const esMuestra = t.solo_muestras == 1; + const muestraBadge = esMuestra + ? `
+ TOMA DE MUESTRAS +
` + : ''; + const cardStyle = esMuestra + ? 'cursor:pointer;border:2px solid #ea580c!important;background:#fff7ed!important' + : 'cursor:pointer'; return `
-
${t.prioridad_codigo}
+
${esMuestra ? '' : escHtml(t.prioridad_codigo)}
${escHtml(t.codigo)}
${escHtml(t.paciente_nombre || 'Paciente')}
+ ${muestraBadge}
${indicador}
`; diff --git a/modules/turnero/views/recepcion.php b/modules/turnero/views/recepcion.php index 3c0b026..0a1ef17 100644 --- a/modules/turnero/views/recepcion.php +++ b/modules/turnero/views/recepcion.php @@ -471,6 +471,12 @@ document.addEventListener('DOMContentLoaded', function() {
Exámenes solicitados
+
+ + +
$items): ?>
@@ -1284,8 +1290,9 @@ async function guardarSolicitud() { return; } + const soloMuestras = document.getElementById('chk-solo-muestras').checked; const examIds = Array.from(document.querySelectorAll('.exam-chk:checked')).map(c => parseInt(c.value)); - if (!examIds.length) { mostrarError('Seleccione al menos un examen.'); return; } + if (!soloMuestras && !examIds.length) { mostrarError('Seleccione al menos un examen.'); return; } const btn = document.getElementById('btn-guardar'); btn.disabled = true; @@ -1308,8 +1315,9 @@ async function guardarSolicitud() { transferencia: parseFloat(document.getElementById('comb-transferencia').value) || 0, tarjeta: parseFloat(document.getElementById('comb-tarjeta').value) || 0, } : null, - observaciones: document.getElementById('inp-obs').value.trim() || null, - embarazada: document.getElementById('chk-embarazada').checked ? 1 : 0, + observaciones: document.getElementById('inp-obs').value.trim() || null, + embarazada: document.getElementById('chk-embarazada').checked ? 1 : 0, + solo_muestras: soloMuestras ? 1 : 0, }), }); const json = await res.json(); @@ -1652,8 +1660,16 @@ async function soltarTurno() { } // ── Helpers ─────────────────────────────────────────────────── +function toggleSoloMuestras() { + const solo = document.getElementById('chk-solo-muestras').checked; + document.querySelectorAll('.exam-chk').forEach(c => { c.checked = false; c.disabled = solo; }); + document.getElementById('lista-examenes').style.opacity = solo ? '0.4' : ''; +} + function resetCheckboxes() { - document.querySelectorAll('.exam-chk').forEach(c => c.checked = false); + document.getElementById('chk-solo-muestras').checked = false; + document.querySelectorAll('.exam-chk').forEach(c => { c.checked = false; c.disabled = false; }); + document.getElementById('lista-examenes').style.opacity = ''; document.getElementById('sel-pago').value = ''; document.getElementById('inp-total').value = ''; document.getElementById('inp-obs').value = '';