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:
co-authored by
Claude Sonnet 4.6
parent
892b01493a
commit
a6f6449707
@@ -29,6 +29,8 @@ $total = isset($datos['total_cobrado']) && $datos['total_cobrado'] !== nul
|
|||||||
? (float) $datos['total_cobrado'] : null;
|
? (float) $datos['total_cobrado'] : null;
|
||||||
$metodoPago = isset($datos['metodo_pago']) ? trim((string) $datos['metodo_pago']) : null;
|
$metodoPago = isset($datos['metodo_pago']) ? trim((string) $datos['metodo_pago']) : null;
|
||||||
$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;
|
||||||
|
if ($numOrden === '') $numOrden = null;
|
||||||
|
|
||||||
// ── Validaciones ──────────────────────────────────────────────
|
// ── Validaciones ──────────────────────────────────────────────
|
||||||
if ($turnoId <= 0) jsonError('turno_id inválido.');
|
if ($turnoId <= 0) jsonError('turno_id inválido.');
|
||||||
@@ -90,11 +92,11 @@ try {
|
|||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
"INSERT INTO turnero_solicitudes
|
"INSERT INTO turnero_solicitudes
|
||||||
(turno_id, paciente_id, lugar_id, total_cobrado, metodo_pago, observaciones, creado_por)
|
(turno_id, paciente_id, lugar_id, numero_orden, total_cobrado, metodo_pago, observaciones, creado_por)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)"
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
);
|
);
|
||||||
$stmt->execute([
|
$stmt->execute([
|
||||||
$turnoId, $pacienteId, $lugarId,
|
$turnoId, $pacienteId, $lugarId, $numOrden,
|
||||||
$total, $metodoPago ?: null, $obs ?: null, adminId(),
|
$total, $metodoPago ?: null, $obs ?: null, adminId(),
|
||||||
]);
|
]);
|
||||||
$solicitudId = (int) $pdo->lastInsertId();
|
$solicitudId = (int) $pdo->lastInsertId();
|
||||||
|
|||||||
@@ -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]);
|
||||||
@@ -330,6 +330,22 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Sección 1: Paciente ── -->
|
<!-- ── 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">
|
<div class="ficha-section">
|
||||||
<h6><i class="fas fa-user me-1"></i>Paciente</h6>
|
<h6><i class="fas fa-user me-1"></i>Paciente</h6>
|
||||||
|
|
||||||
@@ -722,6 +738,18 @@ async function rellamarActivo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Abrir ficha ───────────────────────────────────────────────
|
// ── 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) {
|
function abrirFicha(turno) {
|
||||||
turnoActivo = turno;
|
turnoActivo = turno;
|
||||||
pacienteActivo = null;
|
pacienteActivo = null;
|
||||||
@@ -730,6 +758,8 @@ function abrirFicha(turno) {
|
|||||||
document.getElementById('ficha-placeholder').classList.add('d-none');
|
document.getElementById('ficha-placeholder').classList.add('d-none');
|
||||||
document.getElementById('ficha-turno').classList.remove('d-none');
|
document.getElementById('ficha-turno').classList.remove('d-none');
|
||||||
|
|
||||||
|
cargarConsecutivo();
|
||||||
|
|
||||||
// Datos del turno
|
// Datos del turno
|
||||||
document.getElementById('ficha-codigo').textContent = turno.codigo;
|
document.getElementById('ficha-codigo').textContent = turno.codigo;
|
||||||
document.getElementById('ficha-prio-nombre').textContent = turno.prioridad_nombre || '';
|
document.getElementById('ficha-prio-nombre').textContent = turno.prioridad_nombre || '';
|
||||||
@@ -1023,6 +1053,7 @@ async function guardarSolicitud() {
|
|||||||
paciente_id: pacienteActivo.id,
|
paciente_id: pacienteActivo.id,
|
||||||
lugar_id: lugarId,
|
lugar_id: lugarId,
|
||||||
exam_tipo_ids: examIds,
|
exam_tipo_ids: examIds,
|
||||||
|
numero_orden: document.getElementById('inp-consecutivo').value.trim() || null,
|
||||||
total_cobrado: parseFloat(document.getElementById('inp-total').value) || null,
|
total_cobrado: parseFloat(document.getElementById('inp-total').value) || null,
|
||||||
metodo_pago: document.getElementById('sel-pago').value || null,
|
metodo_pago: document.getElementById('sel-pago').value || null,
|
||||||
observaciones: document.getElementById('inp-obs').value.trim() || null,
|
observaciones: document.getElementById('inp-obs').value.trim() || null,
|
||||||
|
|||||||
Reference in New Issue
Block a user