up
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
// Script de test: scripts/test_menu_backflow.php
|
||||
// Simula flujo: MENÚ principal -> 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";
|
||||
@@ -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 = [];
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user