From a481a20e9a19d621964846ccaa34d50a71172101 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Sat, 24 Jan 2026 02:15:54 -0500 Subject: [PATCH] up --- logs/system.log | 2 + scripts/test_menu_backflow.php | 102 ++++++++++++++++++++++++++ services/BotService.php | 17 +++++ services/ConversationStateService.php | 8 +- 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 scripts/test_menu_backflow.php diff --git a/logs/system.log b/logs/system.log index aeefcba..e5835f0 100644 --- a/logs/system.log +++ b/logs/system.log @@ -63,3 +63,5 @@ Stack trace: [2026-01-21 23:14:51] [INFO] Survey response saved {"id":"10","phone":"573111111111","parsed":{"\u00bfFue f\u00e1cil interactuar con el chat autom\u00e1tico?":"S\u00ed","\u00bfEl asesor humano resolvi\u00f3 tu solicitud?":"No","Calificaci\u00f3n":"5","Comentario":"excelente servicio"}} [2026-01-21 23:49:55] [INFO] delete_template.php start {"raw_input":{"id":"1"},"query":{"debug":"true"}} [2026-01-21 23:49:55] [INFO] delete_template.php parsed ids {"ids":[1]} +[2026-01-24 02:11:00] [INFO] Bot paused for 3 minutes for 573022548060 +[2026-01-24 02:14:23] [INFO] Bot paused for 3 minutes for 573022548060 diff --git a/scripts/test_menu_backflow.php b/scripts/test_menu_backflow.php new file mode 100644 index 0000000..0e1f64a --- /dev/null +++ b/scripts/test_menu_backflow.php @@ -0,0 +1,102 @@ + opción que abre "informacion_examenes" -> seleccionar "pruebas de embarazo" (end) -> enviar ATRÁS + +require_once __DIR__ . '/../config/config.php'; +require __DIR__ . '/../services/BotService.php'; +require __DIR__ . '/../services/ConversationStateService.php'; + +// Ajusta este teléfono al usuario de prueba +$phone = '573022548060'; + +$db = Database::getInstance(); + +// Obtener usuario +$user = $db->fetch("SELECT * FROM users WHERE phone_number = :phone", ['phone' => $phone]); +if (!$user) { + echo "Usuario con teléfono {$phone} no encontrado. Creando usuario de prueba...\n"; + $db->insert('users', ['phone_number' => $phone, 'name' => 'Test User', 'created_at' => date('Y-m-d H:i:s')]); + $user = $db->fetch("SELECT * FROM users WHERE phone_number = :phone", ['phone' => $phone]); + if (!$user) { + echo "No se pudo crear el usuario de prueba. Abortando.\n"; + exit(1); + } +} + +// Stub de WhatsApp que imprime en stdout en lugar de hacer llamadas HTTP +class TestWhatsAppService { + public function sendTextMessage($phone, $text) { + echo "[TestWhatsApp] sendTextMessage to {$phone}: " . trim(preg_replace('/\s+/', ' ', $text)) . "\n"; + } + public function sendTemplateMessage($phone, $template, $lang, $params) { + echo "[TestWhatsApp] sendTemplateMessage to {$phone}: template={$template} lang={$lang}\n"; + } +} + +$bot = new BotService(); +// Injectar stub +$rp = new ReflectionProperty($bot, 'whatsappService'); +$rp->setAccessible(true); +$rp->setValue($bot, new TestWhatsAppService()); + +$stateSvc = new ConversationStateService(); + +// Limpieza inicial: borrar estados y setear users.current_menu_id = NULL +$db->update('users', ['current_menu_id' => null, 'current_step' => 0, 'session_data' => null, 'welcome_sent_at' => date('Y-m-d H:i:s')], 'phone_number = :phone', ['phone' => $phone]); +$stateSvc->clearState($phone); + +echo "== Estado inicial ==\n"; +print_r($db->fetch("SELECT id, phone_number, current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phone])); +print_r($stateSvc->getState($phone)); + +// 1) Enviar MENU +echo "\n1) Enviar 'MENU'\n"; +$bot->processMessage($user, 'MENU'); +print_r($stateSvc->getState($phone)); +echo "menu_history: " . json_encode($stateSvc->getStateData($phone, 'menu_history')) . "\n"; +print_r($db->fetch("SELECT current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phone])); + +// 2) Seleccionar opción que abre informacion_examenes +// Encontramos qué opción en main_menu abre el menu 'informacion_examenes' +$options = $db->fetchAll("SELECT mo.* FROM menu_options mo JOIN menus m ON mo.menu_id = m.id WHERE m.is_root = 1 AND mo.is_active = 1"); +$targetOption = null; +foreach ($options as $opt) { + if ($opt['action_type'] === 'menu') { + $targetMenu = $db->fetch("SELECT * FROM menus WHERE id = :id", ['id' => $opt['action_value']]); + // action_value may be name not id; check by name + $menuByName = $db->fetch("SELECT * FROM menus WHERE name = :name", ['name' => $opt['action_value']]); + if ($menuByName && $menuByName['name'] === 'informacion_examenes') { + $targetOption = $opt; + break; + } + } +} + +if (!$targetOption) { + // Fallback: just try option 4 like user described + $optNumber = 4; + echo "No se encontró opción por nombre, usando opción {$optNumber} en main menu\n"; + $bot->processMessage($user, (string)$optNumber); +} else { + echo "Seleccionando opción número {$targetOption['option_number']} que abre informacion_examenes\n"; + $bot->processMessage($user, (string)$targetOption['option_number']); +} + +print_r($stateSvc->getState($phone)); +echo "menu_history: " . json_encode($stateSvc->getStateData($phone, 'menu_history')) . "\n"; +print_r($db->fetch("SELECT current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phone])); + +// 3) En menu informacion_examenes, seleccionar 'Pruebas de embarazo' (usualmente opción 1) +echo "\n3) En menu informacion_examenes, seleccionar opción 1 (pruebas de embarazo)\n"; +$bot->processMessage($user, '1'); +print_r($stateSvc->getState($phone)); +echo "menu_history: " . json_encode($stateSvc->getStateData($phone, 'menu_history')) . "\n"; +print_r($db->fetch("SELECT current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phone])); + +// 4) Enviar ATRAS +echo "\n4) Enviar 'ATRAS'\n"; +$bot->processMessage($user, 'ATRAS'); +print_r($stateSvc->getState($phone)); +print_r($db->fetch("SELECT current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phone])); + +echo "\nTest script finished.\n"; diff --git a/services/BotService.php b/services/BotService.php index 4ddf3e6..e7876d7 100644 --- a/services/BotService.php +++ b/services/BotService.php @@ -780,6 +780,8 @@ class BotService { $previousMenu = null; } + try { error_log("[BotService] updateUserMenuState - phone={$phoneNumber} previousMenu=" . json_encode($previousMenu) . " newMenu=" . json_encode($menuId)); } catch (Throwable $t) {} + // Si hay un menú previo diferente al nuevo, empujarlo al historial if (!empty($previousMenu) && $previousMenu != $menuId) { try { @@ -813,6 +815,21 @@ class BotService { private function pushMenuToHistory(string $phoneNumber, $menuId) { try { $stateSvc = new ConversationStateService(); + $currentState = $stateSvc->getState($phoneNumber); + + // Si no existe una fila de estado, crearla con el historial inicial + if (!$currentState) { + try { + error_log("[BotService] pushMenuToHistory - no existing state, creating initial state with menu_history for phone={$phoneNumber} menuId={$menuId}"); + $res = $stateSvc->setState($phoneNumber, ConversationStateService::STATE_INITIAL, ['menu_history' => [$menuId]]); + error_log('[BotService] pushMenuToHistory - setState result: ' . json_encode($res)); + return $res; + } catch (Exception $e) { + error_log('[BotService] pushMenuToHistory create initial state failed: ' . $e->getMessage()); + return false; + } + } + $history = (array)$stateSvc->getStateData($phoneNumber, 'menu_history'); if (!is_array($history)) $history = []; diff --git a/services/ConversationStateService.php b/services/ConversationStateService.php index 8b51b83..5ca8799 100644 --- a/services/ConversationStateService.php +++ b/services/ConversationStateService.php @@ -119,7 +119,13 @@ class ConversationStateService */ public function clearState(string $phoneNumber): bool { - return $this->db->delete('user_states', 'phone_number = :phone', ['phone' => $phoneNumber]); + try { + $this->db->delete('user_states', 'phone_number = :phone', ['phone' => $phoneNumber]); + return true; + } catch (Exception $e) { + error_log('[ConversationStateService] clearState failed: ' . $e->getMessage()); + return false; + } } /**