feat: config anidada por examen en tomas prolongadas + F-LAB-08 mejoras
- configurar_tomas.php: almacena _tomas_config como { examName: { groupKey: [fids] } }
en vez de flat, detecta y resetea formato antiguo, valida exam_type requerido
- ver_formulario_enviado.php: rendering aplana nested→flat para filtrar secciones;
JS lee _mpTomasConfig[examName][gk] en inSaved y _mpRenderBadges; auto-open
verifica per-examen; _mpActiveConfigExam evita race entre exámenes simultáneos
- get_consentimientos.php: flatten de nested o flat para calcular allowedFids
en ambos loops de tomas progresivas
- F-LAB-08 (id=16): añade 'Grupo sanguíneo' a opciones de _m5n865g;
agrega campos condicionales '¿Qué tipo de cáncer?' y 'Especifique grupo sanguíneo'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
0ea411ce62
commit
915fa3ba5c
@@ -19,6 +19,7 @@ $otroHora = trim($body['otro_hora'] ?? '');
|
|||||||
|
|
||||||
if (!$token) jsonError('token requerido.');
|
if (!$token) jsonError('token requerido.');
|
||||||
if (!is_array($cfg) || empty($cfg)) jsonError('tomas_config requerido.');
|
if (!is_array($cfg) || empty($cfg)) jsonError('tomas_config requerido.');
|
||||||
|
if ($examType === '') jsonError('exam_type requerido.');
|
||||||
|
|
||||||
foreach ($cfg as $grupo => $ids) {
|
foreach ($cfg as $grupo => $ids) {
|
||||||
if (!is_array($ids) || empty($ids)) jsonError("El grupo '$grupo' no tiene tomas seleccionadas.");
|
if (!is_array($ids) || empty($ids)) jsonError("El grupo '$grupo' no tiene tomas seleccionadas.");
|
||||||
@@ -41,9 +42,15 @@ if ($tc['datos_respuestas']) {
|
|||||||
if (is_array($d)) $dr = $d;
|
if (is_array($d)) $dr = $d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge: preserve config from other exams already saved
|
// Store per-exam nested: { examName: { groupKey: [firmaIds] } }
|
||||||
if (!isset($dr['_tomas_config']) || !is_array($dr['_tomas_config'])) $dr['_tomas_config'] = [];
|
$existing = isset($dr['_tomas_config']) && is_array($dr['_tomas_config']) ? $dr['_tomas_config'] : [];
|
||||||
foreach ($cfg as $k => $v) $dr['_tomas_config'][$k] = $v;
|
// Reset old flat format (values were arrays of strings, not arrays of arrays)
|
||||||
|
if (!empty($existing)) {
|
||||||
|
$__first = reset($existing);
|
||||||
|
if (is_array($__first) && !empty($__first) && is_string(reset($__first))) $existing = [];
|
||||||
|
}
|
||||||
|
$existing[$examType] = $cfg;
|
||||||
|
$dr['_tomas_config'] = $existing;
|
||||||
// Guardar selección completa de exámenes (array) para que el reload restaure todos
|
// Guardar selección completa de exámenes (array) para que el reload restaure todos
|
||||||
$examTypes = isset($body['exam_types']) && is_array($body['exam_types']) ? array_values(array_filter($body['exam_types'])) : [];
|
$examTypes = isset($body['exam_types']) && is_array($body['exam_types']) ? array_values(array_filter($body['exam_types'])) : [];
|
||||||
if ($examTypes) {
|
if ($examTypes) {
|
||||||
|
|||||||
@@ -120,7 +120,15 @@ foreach ($consentimientos as &$c) {
|
|||||||
// Si hay config de tomas guardada, restringir al subconjunto seleccionado
|
// Si hay config de tomas guardada, restringir al subconjunto seleccionado
|
||||||
$tomasConfig = is_array($dr['_tomas_config'] ?? null) ? $dr['_tomas_config'] : null;
|
$tomasConfig = is_array($dr['_tomas_config'] ?? null) ? $dr['_tomas_config'] : null;
|
||||||
if ($tomasConfig !== null) {
|
if ($tomasConfig !== null) {
|
||||||
$allowedFids = array_merge(...array_values($tomasConfig));
|
$allowedFids = [];
|
||||||
|
foreach ($tomasConfig as $__v) {
|
||||||
|
if (!is_array($__v)) continue;
|
||||||
|
$__inner = reset($__v);
|
||||||
|
// nested: exam => { group => [fids] }; flat: group => [fids]
|
||||||
|
if (is_array($__inner)) { foreach ($__v as $__fids) foreach ($__fids as $__f) $allowedFids[] = $__f; }
|
||||||
|
else { foreach ($__v as $__f) $allowedFids[] = $__f; }
|
||||||
|
}
|
||||||
|
$allowedFids = array_unique($allowedFids);
|
||||||
$relevantIds = array_values(array_filter($relevantIds, fn($id) => in_array($id, $allowedFids, true)));
|
$relevantIds = array_values(array_filter($relevantIds, fn($id) => in_array($id, $allowedFids, true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +361,14 @@ if ($incluirSolicitud) {
|
|||||||
}
|
}
|
||||||
$cfg2 = is_array($dr2['_tomas_config'] ?? null) ? $dr2['_tomas_config'] : null;
|
$cfg2 = is_array($dr2['_tomas_config'] ?? null) ? $dr2['_tomas_config'] : null;
|
||||||
if ($cfg2 !== null) {
|
if ($cfg2 !== null) {
|
||||||
$allowed2 = array_merge(...array_values($cfg2));
|
$allowed2 = [];
|
||||||
|
foreach ($cfg2 as $__v2) {
|
||||||
|
if (!is_array($__v2)) continue;
|
||||||
|
$__i2 = reset($__v2);
|
||||||
|
if (is_array($__i2)) { foreach ($__v2 as $__fids2) foreach ($__fids2 as $__f2) $allowed2[] = $__f2; }
|
||||||
|
else { foreach ($__v2 as $__f2) $allowed2[] = $__f2; }
|
||||||
|
}
|
||||||
|
$allowed2 = array_unique($allowed2);
|
||||||
$relevantIds2 = array_values(array_filter($relevantIds2, fn($id) => in_array($id, $allowed2, true)));
|
$relevantIds2 = array_values(array_filter($relevantIds2, fn($id) => in_array($id, $allowed2, true)));
|
||||||
}
|
}
|
||||||
$tomasTotal2 = count($relevantIds2);
|
$tomasTotal2 = count($relevantIds2);
|
||||||
|
|||||||
+32
-13
@@ -315,14 +315,30 @@ if ($modoTurnero && $embebido && $_soloFirmaPro) {
|
|||||||
// Aplicar filtro de ciclos si el profesional ya configuró las tomas para este paciente
|
// Aplicar filtro de ciclos si el profesional ya configuró las tomas para este paciente
|
||||||
$__rawCfg = $datosCliente['_tomas_config'] ?? null;
|
$__rawCfg = $datosCliente['_tomas_config'] ?? null;
|
||||||
if (is_array($__rawCfg)) {
|
if (is_array($__rawCfg)) {
|
||||||
$_tomasConfig = $__rawCfg;
|
$_tomasConfig = $__rawCfg; // exported to JS as-is (nested format)
|
||||||
|
// Flatten nested { examName: { groupKey: [fids] } } → { groupKey: [fids] } for rendering
|
||||||
|
$__first = reset($__rawCfg);
|
||||||
|
$__isNested = is_array($__first) && !empty($__first) && is_array(reset($__first));
|
||||||
|
$__flatCfg = [];
|
||||||
|
if ($__isNested) {
|
||||||
|
foreach ($__rawCfg as $__examCfg) {
|
||||||
|
if (!is_array($__examCfg)) continue;
|
||||||
|
foreach ($__examCfg as $__gk => $__fids) {
|
||||||
|
foreach ($__fids as $__fid) $__flatCfg[$__gk][] = $__fid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($__flatCfg as &$__v) $__v = array_values(array_unique($__v));
|
||||||
|
unset($__v);
|
||||||
|
} else {
|
||||||
|
$__flatCfg = $__rawCfg;
|
||||||
|
}
|
||||||
foreach ($_mpGroups as $__gk => &$__gsecs) {
|
foreach ($_mpGroups as $__gk => &$__gsecs) {
|
||||||
if (!isset($_tomasConfig[$__gk])) {
|
if (!isset($__flatCfg[$__gk])) {
|
||||||
foreach ($__gsecs as $__s) { $_mpSkippedSepIds[$__s['sep_id']] = true; }
|
foreach ($__gsecs as $__s) { $_mpSkippedSepIds[$__s['sep_id']] = true; }
|
||||||
$__gsecs = [];
|
$__gsecs = [];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$__allowed = array_flip($_tomasConfig[$__gk]);
|
$__allowed = array_flip($__flatCfg[$__gk]);
|
||||||
foreach ($__gsecs as $__s) {
|
foreach ($__gsecs as $__s) {
|
||||||
if (!isset($__allowed[$__s['firma']])) {
|
if (!isset($__allowed[$__s['firma']])) {
|
||||||
$_mpSkippedSepIds[$__s['sep_id']] = true;
|
$_mpSkippedSepIds[$__s['sep_id']] = true;
|
||||||
@@ -1415,7 +1431,10 @@ function _mpChipLabel(label) {
|
|||||||
return label.replace(/^Toma\s*·\s*/i, '').trim();
|
return label.replace(/^Toma\s*·\s*/i, '').trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _mpActiveConfigExam = '';
|
||||||
|
|
||||||
function _mpShowCfgPanel(examName, groups, isModify) {
|
function _mpShowCfgPanel(examName, groups, isModify) {
|
||||||
|
_mpActiveConfigExam = examName;
|
||||||
var savedFirmas = window._mpSavedFirmas || {};
|
var savedFirmas = window._mpSavedFirmas || {};
|
||||||
var html = '';
|
var html = '';
|
||||||
var multiGrupo = Object.keys(groups).length > 1;
|
var multiGrupo = Object.keys(groups).length > 1;
|
||||||
@@ -1427,8 +1446,8 @@ function _mpShowCfgPanel(examName, groups, isModify) {
|
|||||||
for (var i = 0; i < secs.length; i++) {
|
for (var i = 0; i < secs.length; i++) {
|
||||||
var s = secs[i];
|
var s = secs[i];
|
||||||
var isSigned = !!savedFirmas[s.firma];
|
var isSigned = !!savedFirmas[s.firma];
|
||||||
var inSaved = _mpTomasConfig && _mpTomasConfig[gk]
|
var _examCfg = _mpTomasConfig && _mpTomasConfig[examName];
|
||||||
&& _mpTomasConfig[gk].indexOf(s.firma) !== -1;
|
var inSaved = _examCfg && _examCfg[gk] && _examCfg[gk].indexOf(s.firma) !== -1;
|
||||||
var isMin0 = _mpChipLabel(s.label || '') === '0';
|
var isMin0 = _mpChipLabel(s.label || '') === '0';
|
||||||
var isActive = isSigned || inSaved || (!isModify && isMin0);
|
var isActive = isSigned || inSaved || (!isModify && isMin0);
|
||||||
var isOtro = /otro/i.test(s.label || '');
|
var isOtro = /otro/i.test(s.label || '');
|
||||||
@@ -1564,13 +1583,12 @@ function _mpRenderBadges() {
|
|||||||
var groups = _mpGetGroupsForExam(name);
|
var groups = _mpGetGroupsForExam(name);
|
||||||
var totalTomas = Object.values(groups).reduce(function(s, g) { return s + g.length; }, 0);
|
var totalTomas = Object.values(groups).reduce(function(s, g) { return s + g.length; }, 0);
|
||||||
var groupKeys = Object.keys(groups);
|
var groupKeys = Object.keys(groups);
|
||||||
// Verificar si este examen ya está configurado en _mpTomasConfig
|
// Verificar si este examen ya está configurado en _mpTomasConfig (formato anidado por examen)
|
||||||
var configured = _mpTomasConfig !== null && groupKeys.some(function(k) { return _mpTomasConfig[k]; });
|
var _examConf = _mpTomasConfig && _mpTomasConfig[name];
|
||||||
|
var configured = !!_examConf && groupKeys.every(function(k) { return _examConf[k]; });
|
||||||
var tomasCount = 0;
|
var tomasCount = 0;
|
||||||
if (configured) {
|
if (configured) {
|
||||||
groupKeys.forEach(function(k) {
|
groupKeys.forEach(function(k) { if (_examConf[k]) tomasCount += _examConf[k].length; });
|
||||||
if (_mpTomasConfig[k]) tomasCount += _mpTomasConfig[k].length;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
html += '<div class="mp-exam-badge' + (configured ? ' configured' : '') + '">'
|
html += '<div class="mp-exam-badge' + (configured ? ' configured' : '') + '">'
|
||||||
+ '<span class="mp-exam-badge-name">' + name + '</span>';
|
+ '<span class="mp-exam-badge-name">' + name + '</span>';
|
||||||
@@ -1630,7 +1648,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
for (var _i = 0; _i < _chkd.length && !_autoT; _i++) {
|
for (var _i = 0; _i < _chkd.length && !_autoT; _i++) {
|
||||||
var _n = _chkd[_i].value, _g = _mpGetGroupsForExam(_n);
|
var _n = _chkd[_i].value, _g = _mpGetGroupsForExam(_n);
|
||||||
if (!Object.keys(_g).length) continue;
|
if (!Object.keys(_g).length) continue;
|
||||||
var _conf = _mpTomasConfig && Object.keys(_g).every(function(k){ return _mpTomasConfig[k]; });
|
var _eCfg = _mpTomasConfig && _mpTomasConfig[_n];
|
||||||
|
var _conf = !!_eCfg && Object.keys(_g).every(function(k){ return _eCfg[k]; });
|
||||||
if (!_conf) _autoT = { name: _n, groups: _g, isModify: false };
|
if (!_conf) _autoT = { name: _n, groups: _g, isModify: false };
|
||||||
}
|
}
|
||||||
if (_autoT) _mpShowCfgPanel(_autoT.name, _autoT.groups, _autoT.isModify);
|
if (_autoT) _mpShowCfgPanel(_autoT.name, _autoT.groups, _autoT.isModify);
|
||||||
@@ -1639,7 +1658,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
// Botón "Usar todas"
|
// Botón "Usar todas"
|
||||||
document.getElementById('mp-cfg-todas').addEventListener('click', function() {
|
document.getElementById('mp-cfg-todas').addEventListener('click', function() {
|
||||||
var examName = _mpGetExamName() || '';
|
var examName = _mpActiveConfigExam || _mpGetExamName() || '';
|
||||||
var cfg = {};
|
var cfg = {};
|
||||||
document.querySelectorAll('.mp-cfg-chk').forEach(function(chk) {
|
document.querySelectorAll('.mp-cfg-chk').forEach(function(chk) {
|
||||||
if (!cfg[chk.dataset.group]) cfg[chk.dataset.group] = [];
|
if (!cfg[chk.dataset.group]) cfg[chk.dataset.group] = [];
|
||||||
@@ -1655,7 +1674,7 @@ document.getElementById('mp-cfg-todas').addEventListener('click', function() {
|
|||||||
|
|
||||||
// Botón "Iniciar protocolo"
|
// Botón "Iniciar protocolo"
|
||||||
document.getElementById('mp-cfg-iniciar').addEventListener('click', function() {
|
document.getElementById('mp-cfg-iniciar').addEventListener('click', function() {
|
||||||
var examName = _mpGetExamName() || '';
|
var examName = _mpActiveConfigExam || _mpGetExamName() || '';
|
||||||
var byGroup = {};
|
var byGroup = {};
|
||||||
document.querySelectorAll('.mp-cfg-chk').forEach(function(chk) {
|
document.querySelectorAll('.mp-cfg-chk').forEach(function(chk) {
|
||||||
if (!byGroup[chk.dataset.group]) byGroup[chk.dataset.group] = [];
|
if (!byGroup[chk.dataset.group]) byGroup[chk.dataset.group] = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user