up
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* POST /modules/turnero/api/create_consent_token.php
|
||||||
|
* Crea un token de consentimiento para un turno + formulario
|
||||||
|
* y retorna la URL para firmar.
|
||||||
|
*
|
||||||
|
* Body JSON:
|
||||||
|
* turno_id int requerido
|
||||||
|
* formulario_id int requerido
|
||||||
|
*/
|
||||||
|
require_once __DIR__ . '/_helpers.php';
|
||||||
|
requireMethod('POST');
|
||||||
|
requireTurnero();
|
||||||
|
|
||||||
|
$datos = inputJson();
|
||||||
|
$turnoId = (int)($datos['turno_id'] ?? 0);
|
||||||
|
$formularioId = (int)($datos['formulario_id'] ?? 0);
|
||||||
|
|
||||||
|
if (!$turnoId) jsonError('turno_id requerido.');
|
||||||
|
if (!$formularioId) jsonError('formulario_id requerido.');
|
||||||
|
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Verificar que el turno existe
|
||||||
|
$stmt = $pdo->prepare("SELECT id, sesion_id, paciente_id FROM turnero_turnos WHERE id = ?");
|
||||||
|
$stmt->execute([$turnoId]);
|
||||||
|
$turno = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if (!$turno) jsonError('Turno no encontrado.', 404);
|
||||||
|
|
||||||
|
$pacienteId = $turno['paciente_id'];
|
||||||
|
if (!$pacienteId) jsonError('El turno no tiene paciente vinculado.');
|
||||||
|
|
||||||
|
// Verificar que el formulario existe
|
||||||
|
$stmt = $pdo->prepare("SELECT id, nombre FROM lab_formularios WHERE id = ? AND is_active = 1");
|
||||||
|
$stmt->execute([$formularioId]);
|
||||||
|
$formulario = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if (!$formulario) jsonError('Formulario no encontrado o inactivo.', 404);
|
||||||
|
|
||||||
|
// Buscar si ya existe un token
|
||||||
|
$stmt = $pdo->prepare(
|
||||||
|
"SELECT token, estado FROM turnero_consentimientos WHERE turno_id = ? AND formulario_id = ?"
|
||||||
|
);
|
||||||
|
$stmt->execute([$turnoId, $formularioId]);
|
||||||
|
$existente = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if ($existente) {
|
||||||
|
if (in_array($existente['estado'], ['firmado', 'rechazado'], true)) {
|
||||||
|
jsonError('Este consentimiento ya fue ' . $existente['estado'] . '.', 422);
|
||||||
|
}
|
||||||
|
$token = $existente['token'];
|
||||||
|
} else {
|
||||||
|
// Generar nuevo token
|
||||||
|
$token = sprintf(
|
||||||
|
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||||
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||||
|
mt_rand(0, 0xffff),
|
||||||
|
mt_rand(0, 0x0fff) | 0x4000,
|
||||||
|
mt_rand(0, 0x3fff) | 0x8000,
|
||||||
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||||
|
);
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare(
|
||||||
|
"INSERT INTO turnero_consentimientos (turno_id, formulario_id, token, estado, creado_at)
|
||||||
|
VALUES (?, ?, ?, 'pendiente', NOW())"
|
||||||
|
);
|
||||||
|
$stmt->execute([$turnoId, $formularioId, $token]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = BASE_URL . 'ver_formulario_enviado.php?token=' . urlencode($token);
|
||||||
|
|
||||||
|
jsonOk([
|
||||||
|
'token' => $token,
|
||||||
|
'url' => $url,
|
||||||
|
'nombre'=> $formulario['nombre'],
|
||||||
|
]);
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* GET /modules/turnero/api/get_lugar_formularios.php
|
||||||
|
* Retorna los formularios de consentimiento configurados para un lugar.
|
||||||
|
* Sin autenticación (acceso interno).
|
||||||
|
*
|
||||||
|
* Query params:
|
||||||
|
* lugar_id int requerido
|
||||||
|
*/
|
||||||
|
require_once __DIR__ . '/_helpers.php';
|
||||||
|
requireMethod('GET');
|
||||||
|
|
||||||
|
$lugarId = isset($_GET['lugar_id']) ? (int) $_GET['lugar_id'] : 0;
|
||||||
|
if (!$lugarId) jsonError('lugar_id requerido.');
|
||||||
|
|
||||||
|
$stmt = db()->prepare(
|
||||||
|
"SELECT f.id, f.nombre
|
||||||
|
FROM turnero_lugar_consentimientos tlc
|
||||||
|
JOIN lab_formularios f ON f.id = tlc.formulario_id
|
||||||
|
WHERE tlc.lugar_id = ?
|
||||||
|
AND f.is_active = 1
|
||||||
|
ORDER BY f.nombre ASC"
|
||||||
|
);
|
||||||
|
$stmt->execute([$lugarId]);
|
||||||
|
$formularios = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
jsonOk(['formularios' => $formularios]);
|
||||||
@@ -389,7 +389,7 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Sección 5: Consentimientos ── -->
|
<!-- ── Sección 5: Consentimientos ── -->
|
||||||
<div class="ficha-section" id="sec-consentimientos" style="display:none!important">
|
<div class="ficha-section" id="sec-consentimientos" style="display:none">
|
||||||
<div class="d-flex align-items-center justify-content-between mb-2">
|
<div class="d-flex align-items-center justify-content-between mb-2">
|
||||||
<h6 class="mb-0"><i class="fas fa-file-signature me-1"></i>Consentimientos informados</h6>
|
<h6 class="mb-0"><i class="fas fa-file-signature me-1"></i>Consentimientos informados</h6>
|
||||||
<button class="btn btn-sm btn-outline-primary py-0 px-2"
|
<button class="btn btn-sm btn-outline-primary py-0 px-2"
|
||||||
@@ -448,11 +448,63 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
pollingColaId = setInterval(cargarCola, 3000);
|
pollingColaId = setInterval(cargarCola, 3000);
|
||||||
document.getElementById('inp-buscar-pac')
|
document.getElementById('inp-buscar-pac')
|
||||||
.addEventListener('keydown', e => { if (e.key === 'Enter') buscarPaciente(); });
|
.addEventListener('keydown', e => { if (e.key === 'Enter') buscarPaciente(); });
|
||||||
|
document.getElementById('sel-lugar')
|
||||||
|
.addEventListener('change', onLugarChange);
|
||||||
// Refrescar consentimientos al volver a la pestaña (firma en otra pestaña)
|
// Refrescar consentimientos al volver a la pestaña (firma en otra pestaña)
|
||||||
document.addEventListener('visibilitychange', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
if (!document.hidden && turnoActivo) refrescarConsentimientos(turnoActivo.id);
|
if (!document.hidden && turnoActivo) refrescarConsentimientos(turnoActivo.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// ── Formularios del lugar ────────────────────────────────────
|
||||||
|
async function onLugarChange() {
|
||||||
|
const sec = document.getElementById('sec-consentimientos');
|
||||||
|
const lista = document.getElementById('lista-consentimientos');
|
||||||
|
const lugarId = parseInt(document.getElementById('sel-lugar').value);
|
||||||
|
if (!lugarId || !pacienteActivo) { sec.style.display = 'none'; return; }
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API}get_lugar_formularios.php?lugar_id=${lugarId}`);
|
||||||
|
const json = await res.json();
|
||||||
|
if (!json.ok || !json.data?.formularios?.length) { sec.style.display = 'none'; return; }
|
||||||
|
|
||||||
|
lista.innerHTML = json.data.formularios.map(f => {
|
||||||
|
const nom = escHtml(f.nombre);
|
||||||
|
return `<div class="consent-item pendiente">
|
||||||
|
<i class="fas fa-file-signature"></i>
|
||||||
|
<span class="c-nom">${nom}</span>
|
||||||
|
<div class="consent-acciones">
|
||||||
|
<button class="btn btn-outline-primary"
|
||||||
|
onclick="abrirFormularioLugar(${f.id}, '${nom.replace(/'/g, "\\'")}')"
|
||||||
|
title="Abrir formulario en nueva pestaña">
|
||||||
|
<i class="fas fa-external-link-alt"></i> Firmar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
}).join('');
|
||||||
|
sec.style.display = '';
|
||||||
|
} catch (_) {
|
||||||
|
sec.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function abrirFormularioLugar(formularioId, nombre) {
|
||||||
|
if (!turnoActivo) return;
|
||||||
|
// Si ya hay solicitud guardada, usa el consent token
|
||||||
|
try {
|
||||||
|
const res = await fetch(API + 'create_consent_token.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ turno_id: turnoActivo.id, formulario_id: formularioId }),
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
if (json.ok && json.data?.url) {
|
||||||
|
window.open(json.data.url, '_blank');
|
||||||
|
} else {
|
||||||
|
window.open('<?= BASE_URL ?>lab_formularios.php', '_blank');
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
window.open('<?= BASE_URL ?>lab_formularios.php', '_blank');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Cola ──────────────────────────────────────────────────────
|
// ── Cola ──────────────────────────────────────────────────────
|
||||||
async function cargarCola() {
|
async function cargarCola() {
|
||||||
@@ -769,11 +821,11 @@ function renderConsentimientos(lista) {
|
|||||||
const ya = ['firmado','rechazado'].includes(c.estado);
|
const ya = ['firmado','rechazado'].includes(c.estado);
|
||||||
const token = escHtml(c.token || '');
|
const token = escHtml(c.token || '');
|
||||||
const nom = escHtml(c.formulario_nombre || 'Consentimiento');
|
const nom = escHtml(c.formulario_nombre || 'Consentimiento');
|
||||||
const nomJs = JSON.stringify(c.formulario_nombre || 'Consentimiento');
|
const fId = c.formulario_id;
|
||||||
|
|
||||||
// Botón de firma (solo si no está firmado/rechazado)
|
// Botón de firma (solo si no está firmado/rechazado)
|
||||||
const btnFirmar = (!ya && c.token)
|
const btnFirmar = (!ya)
|
||||||
? `<button class="btn btn-outline-primary" onclick="abrirFirmaPresencialRec('${token}')"
|
? `<button class="btn btn-outline-primary" onclick="firmarConsentimiento(${fId}, '${nom.replace(/'/g, "\\'")}')"
|
||||||
title="Abrir firma en nueva pestaña">
|
title="Abrir firma en nueva pestaña">
|
||||||
<i class="fas fa-external-link-alt"></i> Firmar
|
<i class="fas fa-external-link-alt"></i> Firmar
|
||||||
</button>` : '';
|
</button>` : '';
|
||||||
@@ -798,11 +850,23 @@ function renderConsentimientos(lista) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Firmar en nueva pestaña ──────────────────────────────────
|
// ── Firmar en nueva pestaña ──────────────────────────────────
|
||||||
function abrirFirmaPresencialRec(token) {
|
async function firmarConsentimiento(formularioId, nombre) {
|
||||||
window.open(
|
if (!turnoActivo) { mostrarError('No hay turno activo.'); return; }
|
||||||
BASE_WA + 'ver_formulario_enviado.php?token=' + encodeURIComponent(token) + '&firmar=1',
|
try {
|
||||||
'_blank'
|
const res = await fetch(API + 'create_consent_token.php', {
|
||||||
);
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ turno_id: turnoActivo.id, formulario_id: formularioId }),
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
if (json.ok && json.data?.url) {
|
||||||
|
window.open(json.data.url, '_blank');
|
||||||
|
} else {
|
||||||
|
mostrarError(json.error || 'No se pudo crear el token de firma');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
mostrarError('Error al abrir firma: ' + err.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function verFirmado(token) {
|
function verFirmado(token) {
|
||||||
window.open(BASE_WA + 'ver_formulario_enviado.php?token=' + encodeURIComponent(token), '_blank');
|
window.open(BASE_WA + 'ver_formulario_enviado.php?token=' + encodeURIComponent(token), '_blank');
|
||||||
|
|||||||
@@ -32,14 +32,15 @@ if ($modoTurnero) {
|
|||||||
tc.enviado_at, tc.firmado_at, tc.ip_firma, tc.ua_firma, tc.firma_svg,
|
tc.enviado_at, tc.firmado_at, tc.ip_firma, tc.ua_firma, tc.firma_svg,
|
||||||
f.nombre AS form_nombre, f.categoria, f.descripcion AS form_descripcion,
|
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,
|
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.nombre_completo AS paciente_nombre,
|
||||||
|
p.numero_documento, p.tipo_documento,
|
||||||
p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps,
|
p.fecha_nacimiento, p.telefono AS paciente_telefono, p.eps,
|
||||||
t.sesion_id
|
t.sesion_id
|
||||||
FROM turnero_consentimientos tc
|
FROM turnero_consentimientos tc
|
||||||
JOIN lab_formularios f ON f.id = tc.formulario_id
|
JOIN lab_formularios f ON f.id = tc.formulario_id
|
||||||
JOIN turnero_turnos t ON t.id = tc.turno_id
|
JOIN turnero_turnos t ON t.id = tc.turno_id
|
||||||
JOIN turnero_solicitudes ts ON ts.turno_id = tc.turno_id
|
LEFT JOIN turnero_solicitudes ts ON ts.turno_id = tc.turno_id
|
||||||
LEFT JOIN lab_pacientes p ON p.id = ts.paciente_id
|
LEFT JOIN lab_pacientes p ON p.id = COALESCE(ts.paciente_id, t.paciente_id)
|
||||||
WHERE tc.token = ?",
|
WHERE tc.token = ?",
|
||||||
[$tokenTurnero]
|
[$tokenTurnero]
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user