feat(turnero): opción solo entrega de muestras con prioridad y badge naranja en cola
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
76dda4722a
commit
34004b4d98
@@ -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;
|
||||||
@@ -31,6 +31,7 @@ $metodoPago = isset($datos['metodo_pago']) ? trim((string) $datos['metodo_p
|
|||||||
$obs = isset($datos['observaciones']) ? trim((string) $datos['observaciones']) : null;
|
$obs = isset($datos['observaciones']) ? trim((string) $datos['observaciones']) : null;
|
||||||
$numOrden = isset($datos['numero_orden']) ? trim((string) $datos['numero_orden']) : null;
|
$numOrden = isset($datos['numero_orden']) ? trim((string) $datos['numero_orden']) : null;
|
||||||
$embarazada = !empty($datos['embarazada']) ? 1 : 0;
|
$embarazada = !empty($datos['embarazada']) ? 1 : 0;
|
||||||
|
$soloMuestras = !empty($datos['solo_muestras']) ? 1 : 0;
|
||||||
$pagosDetalle = null;
|
$pagosDetalle = null;
|
||||||
if ($metodoPago === 'combinado' && isset($datos['pagos_detalle']) && is_array($datos['pagos_detalle'])) {
|
if ($metodoPago === 'combinado' && isset($datos['pagos_detalle']) && is_array($datos['pagos_detalle'])) {
|
||||||
$pd = $datos['pagos_detalle'];
|
$pd = $datos['pagos_detalle'];
|
||||||
@@ -46,7 +47,7 @@ if ($numOrden === '') $numOrden = null;
|
|||||||
if ($turnoId <= 0) jsonError('turno_id inválido.');
|
if ($turnoId <= 0) jsonError('turno_id inválido.');
|
||||||
if ($pacienteId <= 0) jsonError('paciente_id inválido.');
|
if ($pacienteId <= 0) jsonError('paciente_id inválido.');
|
||||||
if ($lugarId <= 0) jsonError('lugar_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', ''];
|
$metodosValidos = ['efectivo', 'transferencia', 'tarjeta', 'eps', 'cortesia', 'combinado', ''];
|
||||||
if ($metodoPago && !in_array($metodoPago, $metodosValidos, true)) {
|
if ($metodoPago && !in_array($metodoPago, $metodosValidos, true)) {
|
||||||
@@ -113,12 +114,12 @@ try {
|
|||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
"INSERT INTO turnero_solicitudes
|
"INSERT INTO turnero_solicitudes
|
||||||
(turno_id, paciente_id, lugar_id, numero_orden, total_cobrado, metodo_pago, pagos_detalle, observaciones, embarazada, creado_por)
|
(turno_id, paciente_id, lugar_id, numero_orden, total_cobrado, metodo_pago, pagos_detalle, observaciones, embarazada, solo_muestras, creado_por)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
);
|
);
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
$turnoId, $pacienteId, $lugarId, $numOrden,
|
$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();
|
$solicitudId = (int) $pdo->lastInsertId();
|
||||||
|
|
||||||
|
|||||||
@@ -50,21 +50,20 @@ if ($sesionCerrada) {
|
|||||||
// ── Cola según área ───────────────────────────────────────────
|
// ── Cola según área ───────────────────────────────────────────
|
||||||
if ($area === 'recepcion') {
|
if ($area === 'recepcion') {
|
||||||
// Recepción: todos los turnos en espera/en_recepcion
|
// Recepción: todos los turnos en espera/en_recepcion
|
||||||
$inEstados = "'espera', 'en_recepcion'";
|
$inEstados = "'espera', 'en_recepcion'";
|
||||||
$filtroLugar = '';
|
|
||||||
$bindsCola = [$sesionId];
|
|
||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
"SELECT t.id, t.codigo, t.numero, t.estado, t.paciente_nombre,
|
"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,
|
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.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
|
FROM turnero_turnos t
|
||||||
JOIN turnero_prioridades p ON p.id = t.prioridad_id
|
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)
|
WHERE t.sesion_id = ? AND t.estado IN ($inEstados)
|
||||||
ORDER BY p.orden_peso ASC, t.creado_at ASC"
|
ORDER BY p.orden_peso ASC, t.creado_at ASC"
|
||||||
);
|
);
|
||||||
$stmt->execute($bindsCola);
|
$stmt->execute([$sesionId]);
|
||||||
} else {
|
} else {
|
||||||
// Lugar: cola = en_espera_lugar del grupo + en_servicio en ESTA estación
|
// Lugar: cola = en_espera_lugar del grupo + en_servicio en ESTA estación
|
||||||
$grupoIds = lugarIdsDeGrupo($lugarId);
|
$grupoIds = lugarIdsDeGrupo($lugarId);
|
||||||
@@ -73,13 +72,15 @@ if ($area === 'recepcion') {
|
|||||||
$cols = "t.id, t.codigo, t.numero, t.estado, t.paciente_nombre,
|
$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,
|
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.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(
|
$stmt = $pdo->prepare(
|
||||||
"SELECT * FROM (
|
"SELECT * FROM (
|
||||||
(SELECT $cols
|
(SELECT $cols
|
||||||
FROM turnero_turnos t
|
FROM turnero_turnos t
|
||||||
JOIN turnero_prioridades p ON p.id = t.prioridad_id
|
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 = ?
|
WHERE t.sesion_id = ?
|
||||||
AND t.estado = 'en_espera_lugar'
|
AND t.estado = 'en_espera_lugar'
|
||||||
AND t.lugar_destino_id IN ($inLugares))
|
AND t.lugar_destino_id IN ($inLugares))
|
||||||
@@ -87,11 +88,12 @@ if ($area === 'recepcion') {
|
|||||||
(SELECT $cols
|
(SELECT $cols
|
||||||
FROM turnero_turnos t
|
FROM turnero_turnos t
|
||||||
JOIN turnero_prioridades p ON p.id = t.prioridad_id
|
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 = ?
|
WHERE t.sesion_id = ?
|
||||||
AND t.estado = 'en_servicio'
|
AND t.estado = 'en_servicio'
|
||||||
AND t.lugar_destino_id = ?)
|
AND t.lugar_destino_id = ?)
|
||||||
) AS cola_union
|
) 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]);
|
$stmt->execute([$sesionId, $sesionId, $lugarId]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -465,14 +465,24 @@ function renderCola(snap) {
|
|||||||
border-radius:7px;padding:5px 9px;font-size:.78rem;cursor:pointer">
|
border-radius:7px;padding:5px 9px;font-size:.78rem;cursor:pointer">
|
||||||
<i class="fas fa-bell"></i>
|
<i class="fas fa-bell"></i>
|
||||||
</button>`;
|
</button>`;
|
||||||
|
const esMuestra = t.solo_muestras == 1;
|
||||||
|
const muestraBadge = esMuestra
|
||||||
|
? `<div style="font-size:.6rem;font-weight:700;color:#ea580c;letter-spacing:.04em;margin-top:1px">
|
||||||
|
<i class="fas fa-plus-square me-1"></i>TOMA DE MUESTRAS
|
||||||
|
</div>`
|
||||||
|
: '';
|
||||||
|
const cardStyle = esMuestra
|
||||||
|
? 'cursor:pointer;border:2px solid #ea580c!important;background:#fff7ed!important'
|
||||||
|
: 'cursor:pointer';
|
||||||
return `
|
return `
|
||||||
<div class="cola-card ${enServicio ? 'en-servicio-card' : ''} ${esActivo ? 'activo' : ''}"
|
<div class="cola-card ${enServicio ? 'en-servicio-card' : ''} ${esActivo ? 'activo' : ''}"
|
||||||
style="cursor:pointer" onclick="seleccionarSinLlamar(${t.id})"
|
style="${cardStyle}" onclick="seleccionarSinLlamar(${t.id})"
|
||||||
title="${enServicio ? 'Ver turno en servicio' : `Ver turno ${escHtml(t.codigo)}`}">
|
title="${enServicio ? 'Ver turno en servicio' : `Ver turno ${escHtml(t.codigo)}`}">
|
||||||
<div class="prio-dot" style="background:${t.prioridad_color}">${t.prioridad_codigo}</div>
|
<div class="prio-dot" style="background:${esMuestra ? '#ea580c' : t.prioridad_color}">${esMuestra ? '<i class="fas fa-plus"></i>' : escHtml(t.prioridad_codigo)}</div>
|
||||||
<div class="turno-info">
|
<div class="turno-info">
|
||||||
<div class="cod">${escHtml(t.codigo)}</div>
|
<div class="cod">${escHtml(t.codigo)}</div>
|
||||||
<div class="pac">${escHtml(t.paciente_nombre || 'Paciente')}</div>
|
<div class="pac">${escHtml(t.paciente_nombre || 'Paciente')}</div>
|
||||||
|
${muestraBadge}
|
||||||
</div>
|
</div>
|
||||||
${indicador}
|
${indicador}
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|||||||
@@ -471,6 +471,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
<!-- ── Sección 3: Exámenes ── -->
|
<!-- ── Sección 3: Exámenes ── -->
|
||||||
<div class="ficha-section">
|
<div class="ficha-section">
|
||||||
<h6><i class="fas fa-vial me-1"></i>Exámenes solicitados</h6>
|
<h6><i class="fas fa-vial me-1"></i>Exámenes solicitados</h6>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="chk-solo-muestras" onchange="toggleSoloMuestras()">
|
||||||
|
<label class="form-check-label small fw-semibold text-warning" for="chk-solo-muestras">
|
||||||
|
<i class="fas fa-vial me-1"></i>Solo entrega de muestras
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div id="lista-examenes">
|
<div id="lista-examenes">
|
||||||
<?php foreach ($examenesAgrupados as $cat => $items): ?>
|
<?php foreach ($examenesAgrupados as $cat => $items): ?>
|
||||||
<div class="exam-group-title"><?= htmlspecialchars($cat) ?></div>
|
<div class="exam-group-title"><?= htmlspecialchars($cat) ?></div>
|
||||||
@@ -1284,8 +1290,9 @@ async function guardarSolicitud() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const soloMuestras = document.getElementById('chk-solo-muestras').checked;
|
||||||
const examIds = Array.from(document.querySelectorAll('.exam-chk:checked')).map(c => parseInt(c.value));
|
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');
|
const btn = document.getElementById('btn-guardar');
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
@@ -1308,8 +1315,9 @@ async function guardarSolicitud() {
|
|||||||
transferencia: parseFloat(document.getElementById('comb-transferencia').value) || 0,
|
transferencia: parseFloat(document.getElementById('comb-transferencia').value) || 0,
|
||||||
tarjeta: parseFloat(document.getElementById('comb-tarjeta').value) || 0,
|
tarjeta: parseFloat(document.getElementById('comb-tarjeta').value) || 0,
|
||||||
} : null,
|
} : null,
|
||||||
observaciones: document.getElementById('inp-obs').value.trim() || null,
|
observaciones: document.getElementById('inp-obs').value.trim() || null,
|
||||||
embarazada: document.getElementById('chk-embarazada').checked ? 1 : 0,
|
embarazada: document.getElementById('chk-embarazada').checked ? 1 : 0,
|
||||||
|
solo_muestras: soloMuestras ? 1 : 0,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
@@ -1652,8 +1660,16 @@ async function soltarTurno() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Helpers ───────────────────────────────────────────────────
|
// ── 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() {
|
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('sel-pago').value = '';
|
||||||
document.getElementById('inp-total').value = '';
|
document.getElementById('inp-total').value = '';
|
||||||
document.getElementById('inp-obs').value = '';
|
document.getElementById('inp-obs').value = '';
|
||||||
|
|||||||
Reference in New Issue
Block a user