Estación de muestras: corregir la ficha del paciente desde el turno
Los campos del formulario F-LAB-08 son vinculados: leen de la ficha del paciente. Si el dato está mal, no había forma de arreglarlo desde la estación —el modal era de solo lectura— y corregirlo únicamente en el documento habría dejado la ficha equivocada, reapareciendo en el próximo turno, orden o consentimiento. Por eso se corrige la ficha y no el documento: el dato queda bien en todo el sistema y el formulario, al ser automático, lo toma solo. La edición tiene dos niveles de fricción. Teléfono, dirección y EPS se editan directo: cambian seguido y el error es de bajo riesgo. Nombre, tipo y número de documento y fecha de nacimiento quedan tras un botón aparte con confirmación, porque identifican al paciente en toda su historia clínica. Si el turno ya tiene documentos firmados se advierte que corregir la ficha no los modifica y que hay que emitirlos de nuevo, para que nadie espere que un PDF ya firmado se actualice solo. Paciente::actualizar registraba en la bitácora solo el valor nuevo, lo que impedía reconstruir el anterior si la corrección resultaba equivocada —justo cuando hace falta consultarlo. Ahora guarda antes y después, y únicamente de los campos que realmente cambiaron. La validación del servidor ya cubría nombre, celular, documento y correo, y la cédula tiene índice único, así que no hizo falta agregar validación. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fd46a86007
commit
57818b180a
@@ -173,8 +173,22 @@ class Paciente {
|
||||
}
|
||||
}
|
||||
|
||||
// Registrar antes y después de lo que realmente cambia. Guardar solo el
|
||||
// valor nuevo impide reconstruir el dato anterior si la corrección
|
||||
// resultó equivocada, que es justo cuando hace falta consultarlo.
|
||||
$antes = $this->db->fetch('SELECT * FROM lab_pacientes WHERE id = ?', [$id]) ?: [];
|
||||
$cambios = [];
|
||||
foreach ($campos as $campo => $nuevo) {
|
||||
$previo = $antes[$campo] ?? null;
|
||||
if ((string)$previo !== (string)$nuevo) {
|
||||
$cambios[$campo] = ['antes' => $previo, 'despues' => $nuevo];
|
||||
}
|
||||
}
|
||||
|
||||
$ok = $this->db->update('lab_pacientes', $campos, 'id = ?', [$id]);
|
||||
$this->log->registrar($adminId, 'pacientes', 'editar', $id, $campos);
|
||||
if ($cambios) {
|
||||
$this->log->registrar($adminId, 'pacientes', 'editar', $id, $cambios);
|
||||
}
|
||||
return $ok > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -520,6 +520,15 @@ try {
|
||||
}
|
||||
/* Historial timeline */
|
||||
.mpac-timeline { padding: 0; }
|
||||
.mpac-lbl { font-size:.7rem; color:#64748b; font-weight:600; display:block; margin-bottom:2px; }
|
||||
.mpac-aviso { font-size:.74rem; color:#1e40af; background:#eff6ff; border:1px solid #bfdbfe;
|
||||
border-radius:8px; padding:7px 10px; margin-bottom:10px; }
|
||||
.mpac-lock { background:#fffbeb; border:1px solid #fde68a; border-radius:8px;
|
||||
padding:9px 11px; margin:4px 0 10px; }
|
||||
.mpac-lock-txt { font-size:.72rem; color:#92400e; margin-bottom:7px; line-height:1.45; }
|
||||
.mpac-aviso-firmados { font-size:.74rem; color:#7f1d1d; background:#fef2f2;
|
||||
border:1px solid #fecaca; border-radius:8px;
|
||||
padding:8px 11px; margin-bottom:10px; line-height:1.45; }
|
||||
.mtl-item {
|
||||
display:flex; gap:10px; align-items:flex-start;
|
||||
padding-bottom:12px; position:relative;
|
||||
@@ -949,6 +958,79 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
||||
<div id="mpac-badge-emb" class="d-none mt-1">
|
||||
<span class="badge text-bg-danger"><i class="fas fa-baby me-1"></i>Paciente embarazada</span>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<button class="btn btn-sm btn-outline-secondary" onclick="mpacEditar(true)"
|
||||
id="mpac-btn-editar" style="font-size:.74rem">
|
||||
<i class="fas fa-pen me-1"></i>Corregir datos
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Edición de la ficha ── -->
|
||||
<div id="mpac-form" class="d-none">
|
||||
<div class="mpac-aviso">
|
||||
<i class="fas fa-info-circle me-1"></i>
|
||||
Lo que corrija aquí cambia la ficha del paciente <b>en todo el sistema</b>.
|
||||
</div>
|
||||
|
||||
<label class="mpac-lbl">Celular</label>
|
||||
<input type="text" class="form-control form-control-sm mb-2" id="mpac-in-tel" placeholder="3001234567">
|
||||
|
||||
<label class="mpac-lbl">Dirección</label>
|
||||
<input type="text" class="form-control form-control-sm mb-2" id="mpac-in-dir">
|
||||
|
||||
<label class="mpac-lbl">EPS</label>
|
||||
<input type="text" class="form-control form-control-sm mb-2" id="mpac-in-eps">
|
||||
|
||||
<!-- Datos de identidad: requieren un paso deliberado -->
|
||||
<div id="mpac-identidad-lock" class="mpac-lock">
|
||||
<div class="mpac-lock-txt">
|
||||
<i class="fas fa-lock me-1"></i>
|
||||
Nombre, documento y fecha de nacimiento identifican al paciente en toda su
|
||||
historia clínica.
|
||||
</div>
|
||||
<button class="btn btn-sm btn-outline-warning w-100" onclick="mpacDesbloquearIdentidad()"
|
||||
style="font-size:.74rem">
|
||||
<i class="fas fa-unlock me-1"></i>Corregir también estos datos
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="mpac-identidad" class="d-none">
|
||||
<label class="mpac-lbl">Nombre completo</label>
|
||||
<input type="text" class="form-control form-control-sm mb-2" id="mpac-in-nombre">
|
||||
|
||||
<div class="d-flex gap-2 mb-2">
|
||||
<div style="width:90px">
|
||||
<label class="mpac-lbl">Tipo</label>
|
||||
<select class="form-select form-select-sm" id="mpac-in-tipodoc">
|
||||
<option>CC</option><option>TI</option><option>RC</option>
|
||||
<option>CE</option><option>PA</option><option>NIT</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<label class="mpac-lbl">Nº documento</label>
|
||||
<input type="text" class="form-control form-control-sm" id="mpac-in-doc">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="mpac-lbl">Fecha de nacimiento</label>
|
||||
<input type="date" class="form-control form-control-sm mb-2" id="mpac-in-fnac">
|
||||
</div>
|
||||
|
||||
<div id="mpac-aviso-firmados" class="mpac-aviso-firmados d-none">
|
||||
<i class="fas fa-exclamation-triangle me-1"></i>
|
||||
Este turno ya tiene documentos firmados. Corregir la ficha
|
||||
<b>no modifica lo que ya se firmó</b>: si un documento salió con datos
|
||||
equivocados, hay que emitirlo de nuevo.
|
||||
</div>
|
||||
|
||||
<div id="mpac-msg" class="small mb-2"></div>
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn btn-sm btn-primary flex-grow-1" onclick="mpacGuardarFicha()" id="mpac-btn-guardar">
|
||||
<i class="fas fa-save me-1"></i>Guardar
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-secondary" onclick="mpacEditar(false)">Cancelar</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Historial -->
|
||||
<div class="mpac-sec-title"><i class="fas fa-history" style="color:#6366f1"></i>Historial de visitas</div>
|
||||
@@ -2386,6 +2468,103 @@ function abrirModalPaciente() {
|
||||
|
||||
function cerrarModalPaciente() {
|
||||
document.getElementById('modal-pac-lugar').classList.remove('show');
|
||||
mpacEditar(false);
|
||||
}
|
||||
|
||||
/* ── Corrección de la ficha del paciente desde la estación ──
|
||||
Los campos del formulario son vinculados: leen de la ficha. Por eso se
|
||||
corrige la ficha y no el documento — así el dato queda bien en el turnero,
|
||||
los domicilios y las órdenes, no solo en la hoja que se está llenando. */
|
||||
|
||||
function mpacEditar(abrir) {
|
||||
document.getElementById('mpac-form').classList.toggle('d-none', !abrir);
|
||||
document.getElementById('mpac-datos').classList.toggle('d-none', abrir);
|
||||
document.getElementById('mpac-msg').textContent = '';
|
||||
|
||||
if (!abrir) { mpacBloquearIdentidad(); return; }
|
||||
|
||||
const p = _pacienteActivo || {};
|
||||
document.getElementById('mpac-in-tel').value = p.telefono || p.celular || '';
|
||||
document.getElementById('mpac-in-dir').value = p.direccion || '';
|
||||
document.getElementById('mpac-in-eps').value = p.eps || '';
|
||||
document.getElementById('mpac-in-nombre').value = p.nombre_completo || '';
|
||||
document.getElementById('mpac-in-tipodoc').value = p.tipo_documento || 'CC';
|
||||
document.getElementById('mpac-in-doc').value = p.numero_documento || p.documento || '';
|
||||
document.getElementById('mpac-in-fnac').value = (p.fecha_nacimiento || '').slice(0, 10);
|
||||
|
||||
mpacBloquearIdentidad();
|
||||
|
||||
// Si ya hay documentos firmados, advertir que corregir no los modifica.
|
||||
// El botón "Ver firmado" solo se renderiza para consentimientos ya firmados.
|
||||
const firmados = document.querySelectorAll('#lista-consent button[title="Ver firmado"]').length > 0;
|
||||
document.getElementById('mpac-aviso-firmados').classList.toggle('d-none', !firmados);
|
||||
}
|
||||
|
||||
function mpacBloquearIdentidad() {
|
||||
document.getElementById('mpac-identidad').classList.add('d-none');
|
||||
document.getElementById('mpac-identidad-lock').classList.remove('d-none');
|
||||
}
|
||||
|
||||
function mpacDesbloquearIdentidad() {
|
||||
if (!confirm('Nombre, documento y fecha de nacimiento identifican al paciente en toda su '
|
||||
+ 'historia clínica.\n\n¿Confirma que quiere corregirlos?')) return;
|
||||
document.getElementById('mpac-identidad').classList.remove('d-none');
|
||||
document.getElementById('mpac-identidad-lock').classList.add('d-none');
|
||||
}
|
||||
|
||||
async function mpacGuardarFicha() {
|
||||
if (!_pacienteActivo?.id) return;
|
||||
const msg = document.getElementById('mpac-msg');
|
||||
const btn = document.getElementById('mpac-btn-guardar');
|
||||
const val = id => document.getElementById(id).value.trim();
|
||||
|
||||
const cuerpo = {
|
||||
id: _pacienteActivo.id,
|
||||
telefono: val('mpac-in-tel'),
|
||||
direccion: val('mpac-in-dir'),
|
||||
eps: val('mpac-in-eps'),
|
||||
};
|
||||
// Los datos de identidad solo se envían si se desbloquearon
|
||||
if (!document.getElementById('mpac-identidad').classList.contains('d-none')) {
|
||||
cuerpo.nombre_completo = val('mpac-in-nombre');
|
||||
cuerpo.tipo_documento = val('mpac-in-tipodoc');
|
||||
cuerpo.numero_documento = val('mpac-in-doc');
|
||||
cuerpo.fecha_nacimiento = val('mpac-in-fnac') || null;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
msg.className = 'small mb-2 text-muted';
|
||||
msg.textContent = 'Guardando…';
|
||||
|
||||
try {
|
||||
const r = await fetch(`${BASE_WA}api/lab/save_paciente.php`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(cuerpo),
|
||||
});
|
||||
const d = await r.json();
|
||||
if (!d.ok) {
|
||||
msg.className = 'small mb-2 text-danger';
|
||||
msg.textContent = d.error || 'No se pudo guardar.';
|
||||
btn.disabled = false;
|
||||
return;
|
||||
}
|
||||
// Reflejar el cambio sin recargar: ficha del modal, tarjeta del turno
|
||||
// y el formulario abierto, cuyos campos vinculados leen de la ficha.
|
||||
Object.assign(_pacienteActivo, cuerpo);
|
||||
msg.className = 'small mb-2 text-success';
|
||||
msg.textContent = 'Ficha actualizada.';
|
||||
setTimeout(() => {
|
||||
mpacEditar(false);
|
||||
abrirModalPaciente();
|
||||
if (turnoActivo?.id) actualizarConsentimientos(turnoActivo.id);
|
||||
const marco = document.querySelector('#modal-consent iframe');
|
||||
if (marco && marco.src) marco.src = marco.src;
|
||||
}, 700);
|
||||
} catch (_) {
|
||||
msg.className = 'small mb-2 text-danger';
|
||||
msg.textContent = 'Error de conexión.';
|
||||
btn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function cargarHistorialModal(pacienteId) {
|
||||
|
||||
Reference in New Issue
Block a user