From 5dc2b0efa863d7237dd7833bf8d9350b31d97486 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 3 Jul 2026 11:59:33 -0500 Subject: [PATCH] =?UTF-8?q?fix(turnero):=20corregir=20env=C3=ADo=20WA=20de?= =?UTF-8?q?sde=20recepcion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - recepcion.php: quitar guard !solicitudActiva en enviarConsentimientosTodos (bloqueaba silenciosamente antes de guardar solicitud) - send_consentimiento.php: eliminar requisito de solicitud y exámenes para poder reenviar; usar WhatsAppService('turnero') con rawComponents correctos (1 body param=codigo, button param=token); JOIN lab_pacientes también via t.paciente_id como fallback de teléfono Co-Authored-By: Claude Sonnet 4.6 --- modules/turnero/api/send_consentimiento.php | 97 +++++++-------------- modules/turnero/views/recepcion.php | 2 +- 2 files changed, 32 insertions(+), 67 deletions(-) diff --git a/modules/turnero/api/send_consentimiento.php b/modules/turnero/api/send_consentimiento.php index 56bc329..c0ac5d0 100644 --- a/modules/turnero/api/send_consentimiento.php +++ b/modules/turnero/api/send_consentimiento.php @@ -32,52 +32,31 @@ if ($turnoId <= 0) jsonError('turno_id inválido.'); $pdo = db(); -// ── 1. Cargar turno y su solicitud ──────────────────────────── +// ── 1. Cargar turno (con fallback de paciente desde kiosko) ── $stmt = $pdo->prepare( - "SELECT t.id, t.codigo, t.paciente_nombre, t.paciente_cel, + "SELECT t.id, t.codigo, t.paciente_nombre, t.paciente_cel, t.paciente_id, 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 + 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 ON p.id = s.paciente_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); -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; +// 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. Actualice el paciente antes de enviar.', 422); + jsonError('El paciente no tiene número de celular registrado.', 422); } +$celular = preg_replace('/[^0-9]/', '', $celular); -// 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 ─────── +// ── 2. Obtener formularios configurados para este turno ─────── $stmt = $pdo->prepare( "SELECT tc.formulario_id, f.nombre AS formulario_nombre FROM turnero_consentimientos tc @@ -124,14 +103,16 @@ try { 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, '/'); - } + $wa = new WhatsAppService('turnero'); + $waTemplate = 'consentimiento_turno'; + $stmtLang = $pdo->prepare("SELECT language_code FROM message_templates WHERE template_name = ? LIMIT 1"); + $stmtLang->execute([$waTemplate]); + $waLang = $stmtLang->fetchColumn() ?: 'es'; + + $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']; @@ -161,39 +142,23 @@ try { $consentId = (int) $pdo->lastInsertId(); } - // ── Construir enlace de firma ────────────────────────── $enlaceFirma = $baseUrl . '/ver_formulario_enviado.php?token=' . urlencode($token); + $nombrePac = $turno['pac_nombre'] ?: ($turno['paciente_nombre'] ?? 'Paciente'); - // ── 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. + // ── Enviar con template (mismo formato que create_turno.php) ── $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] - ); + $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); $enviado = true; } catch (\Throwable $eTemplate) { - // Fallback: enviar mensaje de texto plano + // Fallback 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."; + $mensajeTexto = "Hola {$nombrePac}, su turno *{$turno['codigo']}* requiere firma de consentimiento:\n{$enlaceFirma}"; $wa->sendTextMessage($celular, $mensajeTexto); $enviado = true; } catch (\Throwable $eTexto) { diff --git a/modules/turnero/views/recepcion.php b/modules/turnero/views/recepcion.php index f033426..c2d8285 100644 --- a/modules/turnero/views/recepcion.php +++ b/modules/turnero/views/recepcion.php @@ -1581,7 +1581,7 @@ async function refrescarConsentimientos(turnoId) { // ── Enviar consentimientos (todos) ─────────────────────────── async function enviarConsentimientosTodos() { - if (!turnoActivo || !solicitudActiva) return; + if (!turnoActivo) return; const btn = document.getElementById('btn-reenviar-consent'); btn.disabled = true; btn.innerHTML = 'Enviando…';