This commit is contained in:
Lizandro Guarnizo
2026-01-24 02:40:33 -05:00
parent 3033f022d7
commit 09b50a2a99
2 changed files with 142 additions and 14 deletions
+26
View File
@@ -93,6 +93,32 @@ 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]));
// 3b) En menu informacion_examenes, enviar '6' para volver al menú principal (según la config)
echo "\n3b) En menu informacion_examenes, enviar '6' para volver al menú principal\n";
$bot->processMessage($user, '6');
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' (para comparar comportamiento)
echo "\n4) Enviar 'ATRAS'\n";
$bot->processMessage($user, 'ATRAS');
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]));
// 5) Probar si reconoce otros comandos/números: enviar '1' y una palabra cualquiera y 'ASESOR' y 'MENU'
echo "\n5) Probar entradas posteriores: enviar '1', 'hola', 'ASESOR', 'MENU'\n";
$bot->processMessage($user, '1');
$bot->processMessage($user, 'hola');
$bot->processMessage($user, 'ASESOR');
$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]));
echo "\nTest script finished.\n";
// 4) Enviar ATRAS
echo "\n4) Enviar 'ATRAS'\n";
$bot->processMessage($user, 'ATRAS');
+116 -14
View File
@@ -126,13 +126,94 @@ class BotService {
$now = time();
$until = !empty($user['bot_paused_until']) ? strtotime($user['bot_paused_until']) : null;
if ($until && $until > $now) {
// Permitir *navegación explícita* durante la espera: MENU, ATRÁS, números (opciones)
$normalized = mb_strtolower(trim($messageText));
$isNav = in_array($normalized, ['menu','menú','inicio','atras','atrás','volver','back'], true) || is_numeric($messageText);
try {
$this->whatsappService->sendTextMessage($phoneNumber, "🔔 Su solicitud de asesor está pendiente. Un miembro del equipo le atenderá en breve. Si no hay respuesta, podrá usar *MENU* después de " . date('g:i a', $until) . ".");
} catch (Exception $e) {
// ignore
}
error_log("[BotService] processMessage - returning early because advisor_requested active for user {$user['id']}");
return;
if ($isNav) {
try { error_log("[BotService] processMessage - advisor_requested active but navigation input allowed for user {$user['id']} message='{$messageText}'"); } catch (Throwable $t) {}
// Manejar la navegación inmediatamente (no esperar al flujo normal)
$normalized = mb_strtolower(trim($messageText));
// MENU
if (in_array($normalized, ['menu','menú','inicio'], true)) {
$this->showMainMenu($phoneNumber);
return;
}
// ATRÁS
if (in_array($normalized, ['atras','atrás','volver','back'], true)) {
// Si hay menú actual, intentar ir al padre, si no, usar historial
try {
$cur = $this->db->fetch("SELECT current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phoneNumber]);
$currentMenuId = $cur ? $cur['current_menu_id'] : null;
} catch (Exception $e) {
$currentMenuId = null;
}
if (!empty($currentMenuId)) {
$this->goToParentMenu($phoneNumber, $currentMenuId);
} else {
$this->goToPreviousMenu($phoneNumber);
}
return;
}
// Si es número, intentar procesarlo contra current_menu_id o historial
if (is_numeric(trim($messageText))) {
try {
$stateSvc2 = new ConversationStateService();
$resolvedMenuId2 = $stateSvc2->getCurrentMenuId($phoneNumber);
} catch (Exception $e) {
$resolvedMenuId2 = null;
}
if (empty($resolvedMenuId2)) {
try {
$cur = $this->db->fetch("SELECT current_menu_id FROM users WHERE phone_number = :phone", ['phone' => $phoneNumber]);
$resolvedMenuId2 = $cur ? $cur['current_menu_id'] : null;
} catch (Exception $e) {
$resolvedMenuId2 = null;
}
}
// Si no hay menú activo, intentar con historial
if (empty($resolvedMenuId2)) {
try {
$hist = (array)$stateSvc2->getStateData($phoneNumber, 'menu_history');
if (!empty($hist)) $resolvedMenuId2 = end($hist);
} catch (Exception $e) {
$resolvedMenuId2 = null;
}
}
if (!empty($resolvedMenuId2)) {
// Asegurar que la BD refleje el menu activo para que processMenuSelection lo resuelva correctamente
try {
$this->db->update('users', ['current_menu_id' => $resolvedMenuId2, 'current_step' => 1], 'phone_number = :phone', ['phone' => $phoneNumber]);
try {
$stateSvc2->setCurrentMenu($phoneNumber, (int)$resolvedMenuId2);
} catch (Exception $e) {
// ignore
}
} catch (Exception $e) {
error_log('[BotService] failed to set current_menu_id before processing numeric selection: ' . $e->getMessage());
}
$user['current_menu_id'] = $resolvedMenuId2;
$this->processMenuSelection($user, $messageText);
return;
}
}
// Si llegamos aquí no pudimos resolver navegación; permitir que el flujo normal lo trate
} else {
error_log("[BotService] processMessage - returning early because advisor_requested active for user {$user['id']}");
return;
}
} else {
// expiró la espera: limpiar flag
try {
@@ -191,19 +272,40 @@ class BotService {
// Verificar si el usuario está en un menú
if (!empty($resolvedMenuId)) {
$this->processMenuSelection($user, $messageText);
} else {
// No usar las "respuestas rápidas" (autoresponses) automáticamente desde el bot.
// Estas respuestas solo se mostrarán en la UI del chat como "respuestas rápidas".
// Si un asesor ya respondió recientemente, no enviar respuestas automáticas.
if (empty($advisorReplied)) {
$this->sendDefaultNoMatch($phoneNumber);
} else {
// Opcional: informar que el asesor ya respondió y no podemos enviar automáticas
try {
//$this->whatsappService->sendTextMessage($phoneNumber, "🔕 Un asesor ya ha intervenido en la conversación, por favor espera su respuesta o utiliza *MENU* para ver opciones.");
} catch (Exception $e) {
// ignore
return;
}
// Si no hay menú actual pero el usuario envía un número, intentar interpretar el número
// contra el último menú en el historial (por ejemplo: user vio opciones, eligió end y luego envía '6' para volver)
if (is_numeric(trim($messageText))) {
try {
$stateSvc = new ConversationStateService();
$history = (array)$stateSvc->getStateData($phoneNumber, 'menu_history');
if (!empty($history)) {
$lastMenu = end($history);
try { error_log("[BotService] interpreting numeric input '{$messageText}' against lastMenu={$lastMenu} for phone={$phoneNumber}"); } catch (Throwable $t) {}
// simular que estamos en ese menú para procesar la selección
$user['current_menu_id'] = $lastMenu;
$this->processMenuSelection($user, $messageText);
return;
}
} catch (Exception $e) {
// ignore and fallthrough to default
error_log('[BotService] failed to check menu_history: ' . $e->getMessage());
}
}
// No usar las "respuestas rápidas" (autoresponses) automáticamente desde el bot.
// Estas respuestas solo se mostrarán en la UI del chat como "respuestas rápidas".
// Si un asesor ya respondió recientemente, no enviar respuestas automáticas.
if (empty($advisorReplied)) {
$this->sendDefaultNoMatch($phoneNumber);
} else {
// Opcional: informar que el asesor ya respondió y no podemos enviar automáticas
try {
//$this->whatsappService->sendTextMessage($phoneNumber, "🔕 Un asesor ya ha intervenido en la conversación, por favor espera su respuesta o utiliza *MENU* para ver opciones.");
} catch (Exception $e) {
// ignore
}
}
}