Files
whatsapp/modules/turnero/api/send_consentimiento.php
T
Lizandro GuarnizoandClaude Sonnet 4.6 7a08e63e44 send_consentimiento: read wa template from lab_config instead of hardcoding
Was sending 'consentimiento_turno' (plain text fallback) while the
configured template is 'consentimiento_turno_v2'. Now reads
turnero_wa_template and turnero_wa_lang from lab_config, matching
the same logic used in create_turno.php (kiosk).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 17:18:24 -05:00

213 lines
7.9 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 (con fallback de paciente desde kiosko) ──
$stmt = $pdo->prepare(
"SELECT t.id, t.codigo, t.paciente_nombre, t.paciente_cel, t.paciente_id,
t.estado,
COALESCE(p_sol.telefono, p_tur.telefono) AS pac_celular,
COALESCE(p_sol.nombre_completo, p_tur.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_sol ON p_sol.id = s.paciente_id
LEFT JOIN lab_pacientes p_tur ON p_tur.id = t.paciente_id
WHERE t.id = ?"
);
$stmt->execute([$turnoId]);
$turno = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$turno) jsonError('Turno no encontrado.', 404);
// Celular: preferencia paciente BD → kiosko
$celular = $turno['pac_celular'] ?: $turno['paciente_cel'] ?: null;
if (!$celular) {
jsonError('El paciente no tiene número de celular registrado.', 422);
}
$celular = preg_replace('/[^0-9]/', '', $celular);
// ── 2. 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)
);
}
// ── Leer config de WhatsApp (igual que create_turno.php) ─────
$stmtCfg = $pdo->prepare(
"SELECT clave, valor FROM lab_config WHERE clave IN ('turnero_wa_template','turnero_wa_lang')"
);
$stmtCfg->execute();
$cfgWA = $stmtCfg->fetchAll(PDO::FETCH_KEY_PAIR);
$waTemplateName = $cfgWA['turnero_wa_template'] ?? 'consentimiento_turno';
$waLangFallback = $cfgWA['turnero_wa_lang'] ?? 'es';
$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('turnero');
$waMeta = ['canal' => 'turnero'];
$waTemplate = $waTemplateName;
$stmtLang = $pdo->prepare("SELECT language_code FROM message_templates WHERE template_name = ? LIMIT 1");
$stmtLang->execute([$waTemplate]);
$waLang = $stmtLang->fetchColumn() ?: $waLangFallback;
$baseUrl = defined('BASE_URL') ? rtrim(BASE_URL, '/') : (
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http')
. '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost')
);
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();
}
$enlaceFirma = $baseUrl . '/ver_formulario_enviado.php?token=' . urlencode($token);
$nombrePac = $turno['pac_nombre'] ?: ($turno['paciente_nombre'] ?? 'Paciente');
// ── Enviar con template (mismo formato que create_turno.php) ──
$enviado = false;
try {
$rawComps = [
['type' => 'body', 'parameters' => [['type' => 'text', 'text' => $turno['codigo']]]],
['type' => 'button', 'sub_type' => 'url', 'index' => '0',
'parameters' => [['type' => 'text', 'text' => $token]]],
];
$wa->sendTemplateMessage($celular, $waTemplate, $waLang, [], [], $rawComps, $waMeta);
$enviado = true;
} catch (\Throwable $eTemplate) {
// Fallback texto plano
try {
$mensajeTexto = "Hola {$nombrePac}, su turno *{$turno['codigo']}* requiere firma de consentimiento:\n{$enlaceFirma}";
$wa->sendTextMessage($celular, $mensajeTexto, $waMeta);
$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);
}