238 lines
9.0 KiB
PHP
238 lines
9.0 KiB
PHP
<?php
|
|
/**
|
|
* POST /modules/turnero/api/send_consentimiento.php
|
|
* Genera y/o reenvía consentimientos informados por WhatsApp para un turno.
|
|
*
|
|
* Lógica:
|
|
* 1. Lee los turnero_examen_items del turno.
|
|
* 2. Para cada exam_tipo_id busca en exam_tipo_consentimientos qué formulario_id requiere.
|
|
* 3. Deduplica: varios exámenes que apunten al mismo formulario → 1 solo envío.
|
|
* 4. Por cada formulario distinto:
|
|
* a. Si ya existe un turnero_consentimientos con ese (turno_id, formulario_id) → reutiliza / reenvía.
|
|
* b. Si no existe: genera token UUID, inserta con estado 'pendiente'.
|
|
* 5. Envía mensaje WhatsApp al celular del turno / paciente con enlace de firma.
|
|
* 6. Actualiza estado → 'enviado' y registra enviado_at.
|
|
*
|
|
* Body JSON:
|
|
* turno_id int requerido
|
|
*
|
|
* Requiere login + módulo turnero.
|
|
*/
|
|
|
|
require_once __DIR__ . '/_helpers.php';
|
|
requireMethod('POST');
|
|
requireTurnero();
|
|
|
|
require_once __DIR__ . '/../../../services/WhatsAppService.php';
|
|
|
|
$datos = inputJson();
|
|
$turnoId = isset($datos['turno_id']) ? (int) $datos['turno_id'] : 0;
|
|
|
|
if ($turnoId <= 0) jsonError('turno_id inválido.');
|
|
|
|
$pdo = db();
|
|
|
|
// ── 1. Cargar turno y su solicitud ────────────────────────────
|
|
$stmt = $pdo->prepare(
|
|
"SELECT t.id, t.codigo, t.paciente_nombre, t.paciente_cel,
|
|
t.estado,
|
|
s.id AS solicitud_id,
|
|
s.paciente_id,
|
|
s.lugar_id,
|
|
p.telefono AS pac_telefono,
|
|
p.telefono AS pac_celular,
|
|
p.nombre_completo AS pac_nombre
|
|
FROM turnero_turnos t
|
|
LEFT JOIN turnero_solicitudes s ON s.turno_id = t.id
|
|
LEFT JOIN lab_pacientes p ON p.id = s.paciente_id
|
|
WHERE t.id = ?"
|
|
);
|
|
$stmt->execute([$turnoId]);
|
|
$turno = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$turno) jsonError('Turno no encontrado.', 404);
|
|
if (!$turno['solicitud_id']) jsonError('El turno no tiene solicitud registrada. Guarde la solicitud primero.', 422);
|
|
|
|
// Determinar celular de contacto (preferencia: paciente → kiosko)
|
|
$celular = $turno['pac_celular'] ?? $turno['pac_telefono'] ?? $turno['paciente_cel'] ?? null;
|
|
if (!$celular) {
|
|
jsonError('El paciente no tiene número de celular registrado. Actualice el paciente antes de enviar.', 422);
|
|
}
|
|
|
|
// Normalizar celular (quitar espacios / guiones, agregar +57 si no tiene código)
|
|
$celular = preg_replace('/[\s\-\.]/', '', $celular);
|
|
if (!str_starts_with($celular, '+')) {
|
|
// Asumir Colombia si no tiene prefijo internacional
|
|
$celular = '+57' . ltrim($celular, '0');
|
|
}
|
|
|
|
// ── 2. Obtener exámenes de la solicitud ───────────────────────
|
|
$stmt = $pdo->prepare(
|
|
"SELECT exam_tipo_id FROM turnero_examen_items WHERE solicitud_id = ?"
|
|
);
|
|
$stmt->execute([$turno['solicitud_id']]);
|
|
$examIds = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
|
|
|
if (empty($examIds)) {
|
|
jsonError('La solicitud no tiene exámenes registrados.', 422);
|
|
}
|
|
|
|
// ── 3. Obtener formularios configurados para este turno ───────
|
|
$stmt = $pdo->prepare(
|
|
"SELECT tc.formulario_id, f.nombre AS formulario_nombre
|
|
FROM turnero_consentimientos tc
|
|
JOIN lab_formularios f ON f.id = tc.formulario_id
|
|
WHERE tc.turno_id = ?
|
|
ORDER BY f.nombre ASC"
|
|
);
|
|
$stmt->execute([$turnoId]);
|
|
$formulariosRequeridos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
if (empty($formulariosRequeridos)) {
|
|
jsonOk(['consentimientos' => [], 'mensaje' => 'Este turno no tiene consentimientos requeridos.']);
|
|
}
|
|
|
|
// ── 4. Generar / recuperar tokens UUID ────────────────────────
|
|
function generarUuid(): string
|
|
{
|
|
return 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)
|
|
);
|
|
}
|
|
|
|
$pdo->beginTransaction();
|
|
$consentimientosResultado = [];
|
|
$erroresEnvio = [];
|
|
|
|
try {
|
|
$stmtBuscar = $pdo->prepare(
|
|
"SELECT id, token, estado FROM turnero_consentimientos
|
|
WHERE turno_id = ? AND formulario_id = ?"
|
|
);
|
|
$stmtInsertar = $pdo->prepare(
|
|
"INSERT INTO turnero_consentimientos (turno_id, formulario_id, token, estado)
|
|
VALUES (?, ?, ?, 'pendiente')"
|
|
);
|
|
$stmtActualizar = $pdo->prepare(
|
|
"UPDATE turnero_consentimientos
|
|
SET estado = 'enviado', enviado_at = NOW()
|
|
WHERE id = ?"
|
|
);
|
|
|
|
$wa = new WhatsAppService();
|
|
// URL base del sistema (para generar el enlace de firma)
|
|
$baseUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http')
|
|
. '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost');
|
|
// Si BASE_URL está definida, úsala
|
|
if (defined('BASE_URL')) {
|
|
$baseUrl = rtrim(BASE_URL, '/');
|
|
}
|
|
|
|
foreach ($formulariosRequeridos as $form) {
|
|
$formularioId = (int) $form['formulario_id'];
|
|
$formularioNom = $form['formulario_nombre'];
|
|
|
|
// Buscar si ya existe
|
|
$stmtBuscar->execute([$turnoId, $formularioId]);
|
|
$existente = $stmtBuscar->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($existente) {
|
|
$consentId = (int) $existente['id'];
|
|
$token = $existente['token'];
|
|
// Si ya está firmado/rechazado, no reenviar
|
|
if (in_array($existente['estado'], ['firmado', 'rechazado'], true)) {
|
|
$consentimientosResultado[] = [
|
|
'id' => $consentId,
|
|
'formulario_id' => $formularioId,
|
|
'formulario_nombre'=> $formularioNom,
|
|
'estado' => $existente['estado'],
|
|
'enviado' => false,
|
|
];
|
|
continue;
|
|
}
|
|
} else {
|
|
$token = generarUuid();
|
|
$stmtInsertar->execute([$turnoId, $formularioId, $token]);
|
|
$consentId = (int) $pdo->lastInsertId();
|
|
}
|
|
|
|
// ── Construir enlace de firma ──────────────────────────
|
|
$enlaceFirma = $baseUrl . '/ver_formulario_enviado.php?token=' . urlencode($token);
|
|
|
|
// ── Nombre del paciente para el mensaje ───────────────
|
|
$nombrePac = $turno['pac_nombre'] ?? $turno['paciente_nombre'] ?? 'Paciente';
|
|
|
|
// ── Enviar mensaje WhatsApp ────────────────────────────
|
|
// Intentamos enviar con template "consentimiento_turno".
|
|
// Si el template no existe, enviamos texto plano como fallback.
|
|
$enviado = false;
|
|
try {
|
|
$wa->sendTemplateMessage(
|
|
$celular,
|
|
'consentimiento_turno',
|
|
'es',
|
|
// Parámetros del body: {{1}} = nombre, {{2}} = nombre formulario, {{3}} = código turno
|
|
[
|
|
htmlspecialchars($nombrePac, ENT_QUOTES),
|
|
htmlspecialchars($formularioNom, ENT_QUOTES),
|
|
$turno['codigo'],
|
|
],
|
|
// Parámetro del header o botón URL (URL del enlace)
|
|
[$enlaceFirma]
|
|
);
|
|
$enviado = true;
|
|
} catch (\Throwable $eTemplate) {
|
|
// Fallback: enviar mensaje de texto plano
|
|
try {
|
|
$mensajeTexto = "Hola {$nombrePac}, le informamos que para su turno *{$turno['codigo']}* "
|
|
. "debe firmar el siguiente consentimiento informado:\n\n"
|
|
. "*{$formularioNom}*\n\n"
|
|
. "Puede firmarlo en el siguiente enlace:\n{$enlaceFirma}\n\n"
|
|
. "Si ya firmó este documento presencial, ignore este mensaje.";
|
|
$wa->sendTextMessage($celular, $mensajeTexto);
|
|
$enviado = true;
|
|
} catch (\Throwable $eTexto) {
|
|
$erroresEnvio[] = "Formulario '{$formularioNom}': " . $eTexto->getMessage();
|
|
}
|
|
}
|
|
|
|
if ($enviado) {
|
|
$stmtActualizar->execute([$consentId]);
|
|
$estado = 'enviado';
|
|
} else {
|
|
$estado = 'pendiente';
|
|
}
|
|
|
|
$consentimientosResultado[] = [
|
|
'id' => $consentId,
|
|
'formulario_id' => $formularioId,
|
|
'formulario_nombre' => $formularioNom,
|
|
'token' => $token,
|
|
'estado' => $estado,
|
|
'enviado' => $enviado,
|
|
'enlace_firma' => $enlaceFirma,
|
|
];
|
|
}
|
|
|
|
$pdo->commit();
|
|
|
|
$msgExtra = !empty($erroresEnvio)
|
|
? ' (Advertencias: ' . implode('; ', $erroresEnvio) . ')'
|
|
: '';
|
|
|
|
jsonOk(
|
|
['consentimientos' => $consentimientosResultado],
|
|
count(array_filter($consentimientosResultado, fn($c) => $c['enviado']))
|
|
. ' consentimiento(s) enviado(s) por WhatsApp' . $msgExtra
|
|
);
|
|
|
|
} catch (\Throwable $e) {
|
|
if ($pdo->inTransaction()) $pdo->rollBack();
|
|
jsonError('Error al procesar consentimientos: ' . $e->getMessage(), 500);
|
|
}
|