Files
whatsapp/api/lab/save_tomas_config.php
T
Lizandro GuarnizoandClaude Sonnet 4.6 2eefe3f5c8 feat: ciclos configurables + gestión de exámenes en Tomas Prolongadas
Feature 1 — Ciclos configurables por paciente:
- ver_formulario_enviado.php: pantalla de configuración aparece la primera
  vez que el profesional abre el formulario (antes de firmar); permite
  seleccionar qué tomas realizar para cada protocolo. $_mpSkippedSepIds
  oculta las secciones no seleccionadas en render. $_mpMap se reconstruye
  desde los grupos filtrados para que next_firma_id salte tomas omitidas.
- configurar_tomas.php (nuevo): guarda _tomas_config en datos_respuestas
  del consentimiento; valida que cada grupo tenga al menos una toma.
- guardar_toma.php: aplica el filtro _tomas_config al array firmasCampos
  para que el conteo de tomas firmadas/pendientes sea correcto.

Feature 2 — Gestión de tipos de examen (admin):
- lab_tomas_config.php (nuevo): página admin que muestra los exámenes
  actuales con sus tomas y permite añadir nuevos tipos con su esquema
  completo (separador + hora + resultado + firma_profesional por toma).
- api/lab/save_tomas_config.php (nuevo): modifica el esquema JSON del
  formulario id=15; add_exam agrega opción al selector y los campos de
  cada toma; delete_exam elimina la opción y los separadores exclusivos.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 10:19:11 -05:00

152 lines
5.9 KiB
PHP

<?php
/**
* POST /api/lab/save_tomas_config.php
* Gestiona los tipos de examen del formulario de Tomas Prolongadas (lab_formularios.id=15).
*
* Body JSON:
* action string 'add_exam' | 'delete_exam'
* exam_name string Nombre del nuevo tipo de examen
* tomas array [{label, tipo:'minutos'|'hora_fija', valor}] (solo add_exam)
*/
require_once __DIR__ . '/_helpers.php';
requireAdmin();
requireMethod('POST');
$body = inputJson();
$action = trim($body['action'] ?? '');
if (!in_array($action, ['add_exam', 'delete_exam'], true)) jsonError('action inválida.');
$db = Database::getInstance();
$row = $db->fetch("SELECT id, esquema FROM lab_formularios WHERE id = 15 LIMIT 1");
if (!$row) jsonError('Formulario de tomas no encontrado.', 404);
$esquema = json_decode($row['esquema'], true);
if (!is_array($esquema)) jsonError('Esquema del formulario no válido.', 500);
// ── Localizar el campo selector de tipo de examen ────────────
$idxSelector = null;
foreach ($esquema as $i => $c) {
if (($c['id'] ?? '') === '_c8j2g16') { $idxSelector = $i; break; }
}
if ($idxSelector === null) jsonError('Campo selector de examen (_c8j2g16) no encontrado.', 500);
// ── ADD EXAM ─────────────────────────────────────────────────
if ($action === 'add_exam') {
$examName = trim($body['exam_name'] ?? '');
$tomas = $body['tomas'] ?? [];
if (!$examName) jsonError('exam_name requerido.');
if (strlen($examName) > 80) jsonError('exam_name demasiado largo (máx 80 chars).');
if (!is_array($tomas) || empty($tomas)) jsonError('tomas requeridas.');
if (count($tomas) > 20) jsonError('Máximo 20 tomas por examen.');
// Verificar que el examen no exista ya
$currentOptions = $esquema[$idxSelector]['options'] ?? [];
if (in_array($examName, $currentOptions, true)) {
jsonError("El tipo de examen '$examName' ya existe.");
}
// Validar tomas
foreach ($tomas as $i => $t) {
$tipo = $t['tipo'] ?? '';
$valor = $t['valor'] ?? '';
$label = trim($t['label'] ?? '');
if (!in_array($tipo, ['minutos', 'hora_fija'], true)) jsonError("Toma $i: tipo inválido.");
if (!$label) jsonError("Toma $i: label requerido.");
if ($tipo === 'minutos' && (!is_numeric($valor) || (int)$valor < 0))
jsonError("Toma $i: valor de minutos inválido.");
if ($tipo === 'hora_fija' && !preg_match('/^\d{1,2}:\d{2}$/', $valor))
jsonError("Toma $i: hora_fija debe ser HH:MM.");
}
// Prefijo corto para IDs (basado en nombre del examen, sanitizado)
$prefix = '_' . substr(preg_replace('/[^a-z0-9]/i', '', strtolower($examName)), 0, 8) . '_';
$uid = substr(md5($examName . microtime()), 0, 4);
// 1. Agregar opción al campo selector
$esquema[$idxSelector]['options'][] = $examName;
// 2. Agregar campos al final del esquema
$condCampoId = '_c8j2g16';
foreach ($tomas as $idx => $t) {
$label = trim($t['label']);
$tipo = $t['tipo'];
$valor = $t['valor'];
// Construir label del separador
if ($tipo === 'minutos') {
$sepLabel = "$examName · Minuto $valor";
} else {
// hora_fija: convertir HH:MM a "H:MM a.m./p.m."
[$hh, $mm] = explode(':', $valor);
$h = (int)$hh; $ampm = $h >= 12 ? 'p.m.' : 'a.m.';
$h12 = $h > 12 ? $h - 12 : ($h === 0 ? 12 : $h);
$sepLabel = "$examName · {$h12}:{$mm} {$ampm}";
}
$sepId = $prefix . 's' . $idx . $uid;
$horaId = $prefix . 'h' . $idx . $uid;
$resId = $prefix . 'r' . $idx . $uid;
$firmaId = $prefix . 'f' . $idx . $uid;
$esquema[] = [
'id' => $sepId,
'tipo' => 'separador',
'label' => $sepLabel,
'condicion'=> ['campo_id' => $condCampoId, 'valores' => [$examName]],
];
$esquema[] = [
'id' => $horaId,
'tipo' => 'hora',
'label' => 'Hora de toma',
];
$esquema[] = [
'id' => $resId,
'tipo' => 'numero',
'label' => 'Resultado',
];
$esquema[] = [
'id' => $firmaId,
'tipo' => 'firma_profesional',
'label' => 'Firma del profesional',
];
}
$db->getConnection()->prepare(
"UPDATE lab_formularios SET esquema = ? WHERE id = 15"
)->execute([json_encode($esquema, JSON_UNESCAPED_UNICODE)]);
jsonOk([
'exam_name' => $examName,
'tomas_count' => count($tomas),
'options_count'=> count($esquema[$idxSelector]['options']),
], "Examen '$examName' agregado con " . count($tomas) . " tomas.");
}
// ── DELETE EXAM ──────────────────────────────────────────────
if ($action === 'delete_exam') {
$examName = trim($body['exam_name'] ?? '');
if (!$examName) jsonError('exam_name requerido.');
$options = $esquema[$idxSelector]['options'] ?? [];
if (!in_array($examName, $options, true)) jsonError("El examen '$examName' no existe.");
// Eliminar opción del selector
$esquema[$idxSelector]['options'] = array_values(array_filter($options, fn($o) => $o !== $examName));
// Eliminar separadores condicionados únicamente a este examen
$esquema = array_values(array_filter($esquema, function($c) use ($examName) {
$cond = $c['condicion'] ?? null;
if (!$cond) return true;
$vals = $cond['valores'] ?? [];
return !(count($vals) === 1 && $vals[0] === $examName);
}));
$db->getConnection()->prepare(
"UPDATE lab_formularios SET esquema = ? WHERE id = 15"
)->execute([json_encode($esquema, JSON_UNESCAPED_UNICODE)]);
jsonOk(['exam_name' => $examName], "Examen '$examName' eliminado.");
}