fetch( "SELECT tc.id, tc.turno_id, tc.formulario_id, tc.token, tc.estado, tc.enviado_at, tc.firmado_at, tc.ip_firma, tc.ua_firma, tc.firma_svg, tc.firma_profesional_svg, tc.firmado_profesional_at, tc.datos_respuestas, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion, f.esquema, 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, t.sesion_id FROM turnero_consentimientos tc JOIN lab_formularios f ON f.id = tc.formulario_id JOIN turnero_turnos t ON t.id = tc.turno_id LEFT JOIN turnero_solicitudes ts ON ts.turno_id = tc.turno_id LEFT JOIN lab_pacientes p ON p.id = COALESCE(ts.paciente_id, t.paciente_id) WHERE tc.token = ?", [$tokenTurnero] ); if (!$tcRow) { http_response_code(404); die('Consentimiento no encontrado'); } // ── POST: guardar firma y marcar como firmado ────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST') { header('Content-Type: application/json; charset=utf-8'); if ($tcRow['estado'] === 'firmado') { echo json_encode(['ok' => false, 'error' => 'Este consentimiento ya fue firmado']); exit; } $input = json_decode(file_get_contents('php://input'), true) ?? []; $firmaSvg = trim($input['firma_svg'] ?? ''); if (strlen($firmaSvg) < 100) { echo json_encode(['ok' => false, 'error' => 'Firma requerida']); exit; } $datosRespuestas = isset($input['datos_respuestas']) && is_array($input['datos_respuestas']) ? json_encode($input['datos_respuestas'], JSON_UNESCAPED_UNICODE) : null; $ip = filter_var( $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '', FILTER_VALIDATE_IP ) ?: ($_SERVER['REMOTE_ADDR'] ?? ''); $ua = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 500); $pdo = $db->getConnection(); $stmt = $pdo->prepare( "UPDATE turnero_consentimientos SET estado='firmado', firmado_at=NOW(), firma_svg=?, ip_firma=?, ua_firma=?, version_formulario=?, datos_respuestas=? WHERE token=?" ); $stmt->execute([$firmaSvg, $ip, $ua, (int)$tcRow['formulario_id'], $datosRespuestas, $tokenTurnero]); require_once __DIR__ . '/modules/turnero/api/_helpers.php'; notificarSSE((int)$tcRow['sesion_id']); echo json_encode(['ok' => true, 'message' => 'Consentimiento firmado correctamente']); exit; } // ── GET: construir $envio compatible con la plantilla ───────────── $envio = [ 'id' => (int)$tcRow['id'], 'estado' => $tcRow['estado'], 'form_nombre' => $tcRow['form_nombre'], 'form_descripcion' => $tcRow['form_descripcion'], 'categoria' => $tcRow['categoria'], 'esquema' => $tcRow['esquema'], 'firma_svg' => $tcRow['firma_svg'], 'doc_color' => $tcRow['doc_color'], 'doc_encabezado' => $tcRow['doc_encabezado'], 'doc_subtitulo' => $tcRow['doc_subtitulo'], 'doc_logo_base64' => $tcRow['doc_logo_base64'], 'doc_pie_pagina' => $tcRow['doc_pie_pagina'], 'paciente_nombre' => $tcRow['paciente_nombre'], 'numero_documento' => $tcRow['numero_documento'], 'tipo_documento' => $tcRow['tipo_documento'], 'fecha_nacimiento' => $tcRow['fecha_nacimiento'], 'paciente_telefono' => $tcRow['paciente_telefono'], 'eps' => $tcRow['eps'], 'enviado_por_nombre'=> $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['username'] ?? 'Turnero', 'enviado_por_email' => $_SESSION['admin_user']['email'] ?? null, 'firma_profesional_svg' => $tcRow['firma_profesional_svg'] ?? null, 'datos_cliente' => $tcRow['datos_respuestas'] ?: '{}', 'datos_prefilled' => json_encode(['__paciente' => [ 'nombre_completo' => $tcRow['paciente_nombre'] ?? '', 'numero_documento' => $tcRow['numero_documento'] ?? '', 'tipo_documento' => $tcRow['tipo_documento'] ?? '', 'telefono' => $tcRow['paciente_telefono'] ?? '', 'eps' => $tcRow['eps'] ?? '', ]]), 'created_at' => $tcRow['enviado_at'] ?? date('Y-m-d H:i:s'), 'completado_en' => $tcRow['firmado_at'], 'ip_cliente' => $tcRow['ip_firma'], 'hash_verificacion' => null, 'permite_firma' => 1, 'requiere_firma' => 1, ]; } elseif ($modoPublico) { // Acceso por token: solo si el formulario ya fue firmado/completado if (!preg_match('/^[a-f0-9]{64}$/i', $tokenPublico)) { http_response_code(400); die('Token inválido'); } $envio = $db->fetch( "SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion, f.esquema, f.permite_firma, f.requiere_firma, 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, u.full_name AS enviado_por_nombre, u.email AS enviado_por_email FROM lab_form_envios e JOIN lab_formularios f ON f.id = e.formulario_id LEFT JOIN lab_pacientes p ON p.id = e.paciente_id LEFT JOIN admin_users u ON u.id = e.enviado_por WHERE e.token = ?", [$tokenPublico] ); if (!$envio) { http_response_code(404); die('Formulario no encontrado'); } if (!in_array($envio['estado'], ['firmado', 'completado'])) { http_response_code(403); die('El formulario aún no ha sido completado.'); } } else { $id = (int)($_GET['id'] ?? 0); if (!$id) { http_response_code(400); die('ID requerido'); } $envio = $db->fetch( "SELECT e.*, f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion, f.esquema, f.permite_firma, f.requiere_firma, 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, u.full_name AS enviado_por_nombre, u.email AS enviado_por_email FROM lab_form_envios e JOIN lab_formularios f ON f.id = e.formulario_id LEFT JOIN lab_pacientes p ON p.id = e.paciente_id LEFT JOIN admin_users u ON u.id = e.enviado_por WHERE e.id = ?", [$id] ); if (!$envio) { http_response_code(404); die('Formulario no encontrado'); } // Enfermero solo puede ver sus propios envíos if (isEnfermero()) { $uid = (int)($_SESSION['admin_user']['id'] ?? 0); if ($envio['enviado_por'] != $uid) { http_response_code(403); die('Sin acceso'); } } } // ── Config global del lab ───────────────────────────────────────────── $cfgRows = $db->fetchAll('SELECT clave, valor FROM lab_config WHERE valor != ""'); $cfg = []; foreach ($cfgRows as $r) { $cfg[$r['clave']] = $r['valor']; } // Merge: per-form override > global config $docColor = $envio['doc_color'] ?: ($cfg['doc_color'] ?? '#1565c0'); $docEncabezado = $envio['doc_encabezado'] ?: ($cfg['empresa_nombre'] ?? ''); $docSubtitulo = $envio['doc_subtitulo'] ?: ($cfg['empresa_subtitulo'] ?? ''); $docLogo = $envio['doc_logo_base64'] ?: ($cfg['doc_logo_base64'] ?? ''); $docPiePagina = $envio['doc_pie_pagina'] ?: ($cfg['doc_pie_pagina'] ?? ''); $docDireccion = $cfg['empresa_direccion'] ?? ''; $docTelefono = $cfg['empresa_telefono'] ?? ''; $docEmail = $cfg['empresa_email'] ?? ''; $docCiudad = $cfg['empresa_ciudad'] ?? ''; $esquema = json_decode($envio['esquema'], true) ?? []; $datosCliente = json_decode($envio['datos_cliente'] ?? '{}', true) ?? []; $datosPrefilled = json_decode($envio['datos_prefilled'] ?? '{}', true) ?? []; $todos = array_merge($datosPrefilled, $datosCliente); $modoEditar = $modoTurnero && $envio['estado'] !== 'firmado'; $embebido = isset($_GET['embed']) && $_GET['embed'] === '1'; // Pre-scan: formulario que solo requiere firma del profesional (sin firma paciente) $_soloFirmaPro = !empty(array_filter($esquema, fn($c) => ($c['tipo'] ?? '') === 'firma_profesional')) && empty(array_filter($esquema, fn($c) => ($c['tipo'] ?? '') === 'firma')); // Mapa id → label $labelMap = []; foreach ($esquema as $c) { if (!empty($c['id'])) $labelMap[$c['id']] = $c['label'] ?? $c['id']; } $completado = ($envio['completado_en'] ?? '') ? date('d/m/Y H:i', strtotime($envio['completado_en'])) : '—'; $creado = ($envio['created_at'] ?? '') ? date('d/m/Y H:i', strtotime($envio['created_at'])) : '—'; function esc2(mixed $v): string { if (is_array($v)) return htmlspecialchars(implode(', ', $v), ENT_QUOTES); return htmlspecialchars((string)($v ?? ''), ENT_QUOTES); } ?>
He leído el documento. Dibuje su firma:
He leído y comprendido el contenido de este documento. Por favor dibuje su firma en el recuadro: