Turnero: toma progresiva por examen, Rubeola solo-profesional, kiosko
- configurar_tomas.php: merge config por examen en lugar de overwrite - ver_formulario_enviado.php: auto-abrir panel de tiempos al cargar; soporte formularios solo_profesional con botón Guardar y completar - get_consentimientos.php: leer campo solo_profesional de lab_formularios - recepcion.php: formularios sin firma paciente muestran badge "Completa en laboratorio" - lugar.php: botón "Completar" para formularios solo_profesional DB: ALTER TABLE lab_formularios ADD solo_profesional; UPDATE Rubeola id=8; UPDATE descripcion Niños kiosko Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4012ae97be
commit
a3c19bf4e7
@@ -41,7 +41,9 @@ if ($tc['datos_respuestas']) {
|
||||
if (is_array($d)) $dr = $d;
|
||||
}
|
||||
|
||||
$dr['_tomas_config'] = $cfg;
|
||||
// Merge: preserve config from other exams already saved
|
||||
if (!isset($dr['_tomas_config']) || !is_array($dr['_tomas_config'])) $dr['_tomas_config'] = [];
|
||||
foreach ($cfg as $k => $v) $dr['_tomas_config'][$k] = $v;
|
||||
if ($examType !== '') $dr['_c8j2g16'] = $examType;
|
||||
if ($otroHora !== '') $dr['_otro_hora'] = $otroHora;
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ $stmt = $pdo->prepare(
|
||||
tc.datos_respuestas,
|
||||
f.nombre AS formulario_nombre,
|
||||
f.esquema AS formulario_esquema,
|
||||
f.es_toma_progresiva AS formulario_es_toma_prog
|
||||
f.es_toma_progresiva AS formulario_es_toma_prog,
|
||||
f.solo_profesional AS formulario_solo_profesional
|
||||
FROM turnero_consentimientos tc
|
||||
LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
|
||||
WHERE tc.turno_id = ?
|
||||
@@ -130,8 +131,9 @@ foreach ($consentimientos as &$c) {
|
||||
}
|
||||
}
|
||||
|
||||
$soloPro = !empty($c['formulario_solo_profesional']);
|
||||
$c['requiere_firma_profesional'] = $tieneFirmaPro;
|
||||
$c['requiere_firma_paciente'] = !($tieneFirmaPro && !$tieneFirmaPac);
|
||||
$c['requiere_firma_paciente'] = $soloPro ? false : !($tieneFirmaPro && !$tieneFirmaPac);
|
||||
$c['origen_lugar_id'] = in_array((int)$c['formulario_id'], $fidsDeLugar, true)
|
||||
? ($lugarDestinoId ?: -1) : null;
|
||||
$c['es_toma_progresiva'] = $esTomaProg;
|
||||
@@ -139,7 +141,7 @@ foreach ($consentimientos as &$c) {
|
||||
$c['tomas_firmadas'] = $tomasFirm;
|
||||
// Exponer campos firma_profesional (ids) para el frontend
|
||||
$c['campos_firma_pro'] = array_column($camposFirmaPro, 'id');
|
||||
unset($c['formulario_esquema'], $c['formulario_es_toma_prog'], $c['datos_respuestas']);
|
||||
unset($c['formulario_esquema'], $c['formulario_es_toma_prog'], $c['formulario_solo_profesional'], $c['datos_respuestas']);
|
||||
}
|
||||
unset($c);
|
||||
|
||||
@@ -302,7 +304,8 @@ if ($incluirSolicitud) {
|
||||
tc.datos_respuestas,
|
||||
f.nombre AS formulario_nombre,
|
||||
f.esquema AS formulario_esquema,
|
||||
f.es_toma_progresiva AS formulario_es_toma_prog
|
||||
f.es_toma_progresiva AS formulario_es_toma_prog,
|
||||
f.solo_profesional AS formulario_solo_profesional
|
||||
FROM turnero_consentimientos tc
|
||||
LEFT JOIN lab_formularios f ON f.id = tc.formulario_id
|
||||
WHERE tc.turno_id = ?
|
||||
@@ -358,15 +361,16 @@ if ($incluirSolicitud) {
|
||||
if (!empty($dr2[$fid2]) && strlen($dr2[$fid2]) > 10) $tomasFirm++;
|
||||
}
|
||||
}
|
||||
$soloPro2 = !empty($c['formulario_solo_profesional']);
|
||||
$c['requiere_firma_profesional'] = $tieneFirmaPro;
|
||||
$c['requiere_firma_paciente'] = !($tieneFirmaPro && !$tieneFirmaPac);
|
||||
$c['requiere_firma_paciente'] = $soloPro2 ? false : !($tieneFirmaPro && !$tieneFirmaPac);
|
||||
$c['origen_lugar_id'] = in_array((int)$c['formulario_id'], $fidsDeLugar, true)
|
||||
? $lugarDestinoId : null;
|
||||
$c['es_toma_progresiva'] = $esTomaProg;
|
||||
$c['tomas_total'] = $tomasTotal2;
|
||||
$c['tomas_firmadas'] = $tomasFirm;
|
||||
$c['campos_firma_pro'] = array_column($camposFirmaPro, 'id');
|
||||
unset($c['formulario_esquema'], $c['formulario_es_toma_prog'], $c['datos_respuestas']);
|
||||
unset($c['formulario_esquema'], $c['formulario_es_toma_prog'], $c['formulario_solo_profesional'], $c['datos_respuestas']);
|
||||
}
|
||||
unset($c);
|
||||
$respuesta['consentimientos'] = $consentimientos;
|
||||
|
||||
@@ -1609,9 +1609,10 @@ function renderConsentimientos(lista) {
|
||||
<i class="fas fa-flask me-1"></i>Siguiente toma
|
||||
</button>`;
|
||||
} else if (LUGAR_FORM_MODO === 'embebido') {
|
||||
const lblAccion = c.requiere_firma_paciente ? 'Firmar' : 'Completar';
|
||||
btnAccion = `<button class="btn btn-primary" title="Abrir formulario"
|
||||
onclick="abrirModalConsentimientoPorToken('${token}')">
|
||||
<i class="fas fa-pen me-1"></i>Firmar
|
||||
<i class="fas fa-pen me-1"></i>${lblAccion}
|
||||
</button>`;
|
||||
} else {
|
||||
btnAccion = `<button class="btn btn-outline-primary" title="Firmar aquí"
|
||||
|
||||
@@ -1983,6 +1983,20 @@ function renderConsentimientos(lista) {
|
||||
const fId = c.formulario_id;
|
||||
const nomJs = (c.formulario_nombre || 'Consentimiento').replace(/'/g, "\\'");
|
||||
|
||||
// Formulario solo profesional: no requiere acción del paciente en recepción
|
||||
if (!c.requiere_firma_paciente) {
|
||||
const labelPro = ya
|
||||
? `<span class="badge bg-success ms-1"><i class="fas fa-check me-1"></i>Completado</span>`
|
||||
: `<span class="badge bg-secondary ms-1" style="font-size:.75rem"><i class="fas fa-flask me-1"></i>Completa en laboratorio</span>`;
|
||||
return `<div class="consent-item ${m.cls}" style="flex-wrap:wrap">
|
||||
<div style="display:flex;align-items:center;gap:.5rem;width:100%">
|
||||
<i class="fas ${m.ico}"></i>
|
||||
<span class="c-nom">${nom}</span>
|
||||
${labelPro}
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// Botón de firma paciente (solo si no está firmado/rechazado)
|
||||
const btnFirmar = (!ya)
|
||||
? `<button class="btn btn-outline-primary" onclick="firmarConsentimiento(${fId}, '${nomJs}')"
|
||||
|
||||
@@ -33,7 +33,7 @@ if ($modoTurnero) {
|
||||
tc.firma_profesional_svg, tc.firmado_profesional_at, tc.datos_respuestas,
|
||||
tc.siguiente_toma_at, tc.toma_inicio_at,
|
||||
f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion,
|
||||
f.esquema, f.es_toma_progresiva, f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina,
|
||||
f.esquema, f.es_toma_progresiva, f.solo_profesional, f.doc_encabezado, f.doc_subtitulo, f.doc_logo_base64, f.doc_color, f.doc_pie_pagina,
|
||||
p.nombre_completo AS paciente_nombre,
|
||||
p.numero_documento, p.tipo_documento,
|
||||
p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps,
|
||||
@@ -243,6 +243,8 @@ if ($modoTurnero && $embebido && isUserLoggedIn()) {
|
||||
} catch (\Throwable $_) {}
|
||||
}
|
||||
}
|
||||
// Formulario marcado explícitamente como solo-profesional (sin firma de ningún tipo)
|
||||
$_formSoloPro = $modoTurnero && $embebido && !empty($tcRow['solo_profesional']);
|
||||
// Pre-scan: formulario que solo requiere firma del profesional (sin firma paciente)
|
||||
$_soloFirmaPro = ($modoTurnero && !empty($tcRow['es_toma_progresiva']))
|
||||
|| (!empty(array_filter($esquema, fn($c) => ($c['tipo'] ?? '') === 'firma_profesional'))
|
||||
@@ -1311,7 +1313,14 @@ function _addExamWizardHtml(string $cid): string {
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- ── Widget firma turnero (fallback solo si el esquema no tiene NINGÚN campo firma) ── -->
|
||||
<?php if ($modoTurnero && $envio['estado'] !== 'firmado' && !$_esquemaTieneFirmaAlguna && !$_soloFirmaPro): ?>
|
||||
<?php if ($_formSoloPro && $envio['estado'] !== 'firmado'): ?>
|
||||
<div class="mt-4 no-print" id="btn-completar-pro-wrap">
|
||||
<button class="btn btn-success fw-semibold" id="btn-completar-pro" style="font-size:1rem;padding:.6rem 1.4rem">
|
||||
<i class="fas fa-check-circle me-2"></i>Guardar y completar
|
||||
</button>
|
||||
<div id="btn-completar-pro-msg" class="mt-2 small"></div>
|
||||
</div>
|
||||
<?php elseif ($modoTurnero && $envio['estado'] !== 'firmado' && !$_esquemaTieneFirmaAlguna && !$_soloFirmaPro): ?>
|
||||
<div class="mt-4 no-print turnero-firma-item" data-cid="__firma_global">
|
||||
<div class="section-title" style="color:#1565c0">
|
||||
<i class="fas fa-pen me-1"></i>Firma del paciente / responsable
|
||||
@@ -1614,7 +1623,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
} catch(e) {}
|
||||
}
|
||||
_mpApplyExamVisibility(examName);
|
||||
if (_mpModoTurnero) _mpRenderBadges();
|
||||
if (_mpModoTurnero) {
|
||||
_mpRenderBadges();
|
||||
var _chkd = Array.from(document.querySelectorAll('[name="_c8j2g16[]"]:checked,[name="_c8j2g16"]:checked'));
|
||||
var _autoT = null;
|
||||
for (var _i = 0; _i < _chkd.length && !_autoT; _i++) {
|
||||
var _n = _chkd[_i].value, _g = _mpGetGroupsForExam(_n);
|
||||
if (!Object.keys(_g).length) continue;
|
||||
var _conf = _mpTomasConfig && Object.keys(_g).some(function(k){ return _mpTomasConfig[k]; });
|
||||
if (!_conf) _autoT = { name: _n, groups: _g, isModify: false };
|
||||
}
|
||||
if (!_autoT && _chkd.length) {
|
||||
var _n = _chkd[0].value, _g = _mpGetGroupsForExam(_n);
|
||||
if (Object.keys(_g).length) _autoT = { name: _n, groups: _g, isModify: true };
|
||||
}
|
||||
if (_autoT) _mpShowCfgPanel(_autoT.name, _autoT.groups, _autoT.isModify);
|
||||
}
|
||||
});
|
||||
|
||||
// Botón "Usar todas"
|
||||
@@ -2505,6 +2529,48 @@ document.querySelectorAll('.turnero-firma-item').forEach(function(widget) {
|
||||
});
|
||||
});
|
||||
});
|
||||
<?php if ($_formSoloPro): ?>
|
||||
(function() {
|
||||
var btn = document.getElementById('btn-completar-pro');
|
||||
if (!btn) return;
|
||||
btn.addEventListener('click', function() {
|
||||
var msgEl = document.getElementById('btn-completar-pro-msg');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Guardando...';
|
||||
var campos = {};
|
||||
document.querySelectorAll('[name]').forEach(function(el) {
|
||||
var raw = el.name, isArr = raw.slice(-2) === '[]', name = isArr ? raw.slice(0,-2) : raw;
|
||||
if (el.type === 'checkbox') { if (el.checked) { if (!Array.isArray(campos[name])) campos[name] = []; campos[name].push(el.value); } }
|
||||
else if (el.type === 'radio') { if (el.checked) campos[name] = el.value; }
|
||||
else if (el.value !== '') campos[name] = el.value;
|
||||
});
|
||||
fetch(window.location.href, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ mp_completar: true, datos_respuestas: campos })
|
||||
})
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(d) {
|
||||
if (d.ok) {
|
||||
document.getElementById('btn-completar-pro-wrap').style.display = 'none';
|
||||
var ok = document.createElement('div');
|
||||
ok.className = 'alert alert-success mt-4 d-flex align-items-center gap-2 no-print';
|
||||
ok.innerHTML = '<i class="fas fa-check-circle fs-4"></i><div><strong>Completado correctamente.</strong></div>';
|
||||
document.getElementById('btn-completar-pro-wrap').parentNode.appendChild(ok);
|
||||
try { window.parent.postMessage({ type: 'turneroFirmado' }, '*'); } catch(e) {}
|
||||
} else {
|
||||
msgEl.innerHTML = '<span class="text-danger">' + (d.error || 'Error al guardar') + '</span>';
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-check-circle me-2"></i>Guardar y completar';
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
msgEl.innerHTML = '<span class="text-danger">Error de conexión.</span>';
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-check-circle me-2"></i>Guardar y completar';
|
||||
});
|
||||
});
|
||||
})();
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
|
||||
<!-- ── Topaz SigWeb overlay ───────────────────────────────────────── -->
|
||||
|
||||
Reference in New Issue
Block a user