feat: número de orden consecutivo en recepción

- Campo N.° Orden editable en la ficha, antes de seleccionar paciente
- Se carga automáticamente al abrir un turno (YYYYMMDD-001, 002…)
- Botón para regenerar el siguiente consecutivo
- Columna numero_orden en turnero_solicitudes (VARCHAR 20)
- Nuevo endpoint get_consecutivo.php calcula el siguiente del día
- create_solicitud.php guarda el numero_orden junto con la solicitud

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-23 23:12:23 -05:00
co-authored by Claude Sonnet 4.6
parent 892b01493a
commit a6f6449707
3 changed files with 59 additions and 3 deletions
+5 -3
View File
@@ -29,6 +29,8 @@ $total = isset($datos['total_cobrado']) && $datos['total_cobrado'] !== nul
? (float) $datos['total_cobrado'] : null;
$metodoPago = isset($datos['metodo_pago']) ? trim((string) $datos['metodo_pago']) : null;
$obs = isset($datos['observaciones']) ? trim((string) $datos['observaciones']) : null;
$numOrden = isset($datos['numero_orden']) ? trim((string) $datos['numero_orden']) : null;
if ($numOrden === '') $numOrden = null;
// ── Validaciones ──────────────────────────────────────────────
if ($turnoId <= 0) jsonError('turno_id inválido.');
@@ -90,11 +92,11 @@ try {
$stmt = $pdo->prepare(
"INSERT INTO turnero_solicitudes
(turno_id, paciente_id, lugar_id, total_cobrado, metodo_pago, observaciones, creado_por)
VALUES (?, ?, ?, ?, ?, ?, ?)"
(turno_id, paciente_id, lugar_id, numero_orden, total_cobrado, metodo_pago, observaciones, creado_por)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
);
$stmt->execute([
$turnoId, $pacienteId, $lugarId,
$turnoId, $pacienteId, $lugarId, $numOrden,
$total, $metodoPago ?: null, $obs ?: null, adminId(),
]);
$solicitudId = (int) $pdo->lastInsertId();
+23
View File
@@ -0,0 +1,23 @@
<?php
/**
* GET modules/turnero/api/get_consecutivo.php
* Devuelve el siguiente número de orden del día (YYYYMMDD-NNN).
*/
require_once __DIR__ . '/_helpers.php';
requireTurnero();
requireMethod('GET');
$pdo = db();
$prefix = date('Ymd') . '-';
$row = $pdo->prepare(
"SELECT MAX(CAST(SUBSTRING_INDEX(numero_orden,'-',-1) AS UNSIGNED)) AS ultimo
FROM turnero_solicitudes
WHERE numero_orden LIKE ?"
);
$row->execute([$prefix . '%']);
$ultimo = (int)($row->fetch(PDO::FETCH_ASSOC)['ultimo'] ?? 0);
$siguiente = $prefix . str_pad($ultimo + 1, 3, '0', STR_PAD_LEFT);
jsonOk(['consecutivo' => $siguiente]);
+31
View File
@@ -330,6 +330,22 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
</div>
<!-- ── Sección 1: Paciente ── -->
<!-- ── Número de orden ── -->
<div class="ficha-section" style="padding-bottom:10px;border-bottom:1px solid #f1f5f9;margin-bottom:4px">
<div class="d-flex align-items-center gap-2">
<label style="font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:#94a3b8;white-space:nowrap;margin:0">
<i class="fas fa-hashtag me-1"></i>N.° Orden
</label>
<input type="text" id="inp-consecutivo"
class="form-control form-control-sm"
style="max-width:140px;font-weight:700;font-size:.95rem;letter-spacing:.04em"
placeholder="Cargando…" autocomplete="off">
<button class="btn btn-outline-secondary btn-sm" title="Regenerar siguiente" onclick="recargarConsecutivo()" type="button">
<i class="fas fa-rotate-right" style="font-size:.75rem"></i>
</button>
</div>
</div>
<div class="ficha-section">
<h6><i class="fas fa-user me-1"></i>Paciente</h6>
@@ -722,6 +738,18 @@ async function rellamarActivo() {
}
// ── Abrir ficha ───────────────────────────────────────────────
async function cargarConsecutivo() {
const inp = document.getElementById('inp-consecutivo');
if (!inp) return;
inp.value = '…';
try {
const r = await fetch(API + 'get_consecutivo.php');
const d = await r.json();
if (d.ok) inp.value = d.consecutivo;
} catch(_) { inp.value = ''; }
}
function recargarConsecutivo() { cargarConsecutivo(); }
function abrirFicha(turno) {
turnoActivo = turno;
pacienteActivo = null;
@@ -730,6 +758,8 @@ function abrirFicha(turno) {
document.getElementById('ficha-placeholder').classList.add('d-none');
document.getElementById('ficha-turno').classList.remove('d-none');
cargarConsecutivo();
// Datos del turno
document.getElementById('ficha-codigo').textContent = turno.codigo;
document.getElementById('ficha-prio-nombre').textContent = turno.prioridad_nombre || '';
@@ -1023,6 +1053,7 @@ async function guardarSolicitud() {
paciente_id: pacienteActivo.id,
lugar_id: lugarId,
exam_tipo_ids: examIds,
numero_orden: document.getElementById('inp-consecutivo').value.trim() || null,
total_cobrado: parseFloat(document.getElementById('inp-total').value) || null,
metodo_pago: document.getElementById('sel-pago').value || null,
observaciones: document.getElementById('inp-obs').value.trim() || null,