From 0d96fa0029adc7a9f603f3194bfc13945d5c6ec6 Mon Sep 17 00:00:00 2001 From: lizandrogd <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:42:26 -0500 Subject: [PATCH] up --- api/finish_attend.php | 41 +++++++++++++++++++++++++++ conversations.php | 38 +++++++++++++++++++++++++ scripts/insert_activity_test.php | 8 ++++++ scripts/print_operator_activity.php | 7 +++++ scripts/test_attend.php | 26 +++++++++++++++++ scripts/test_finish_attend.php | 25 ++++++++++++++++ services/BotService.php | 44 +++++++++++++++++++++++++++++ 7 files changed, 189 insertions(+) create mode 100644 api/finish_attend.php create mode 100644 scripts/insert_activity_test.php create mode 100644 scripts/print_operator_activity.php create mode 100644 scripts/test_attend.php create mode 100644 scripts/test_finish_attend.php diff --git a/api/finish_attend.php b/api/finish_attend.php new file mode 100644 index 0000000..5412e5a --- /dev/null +++ b/api/finish_attend.php @@ -0,0 +1,41 @@ + false, 'error' => 'user_id required']); + exit; + } + + $db = Database::getInstance(); + $user = $db->fetch('SELECT phone_number FROM users WHERE id = :id', ['id' => $userId]); + if (!$user) { + http_response_code(404); + echo json_encode(['success' => false, 'error' => 'User not found']); + exit; + } + + $operator = $_SESSION['admin_user'] ?? null; + $operatorId = $operator['id'] ?? null; + + try { + require_once __DIR__ . '/../services/BotService.php'; + $bot = new BotService(); + $bot->finishAttendConversation($user['phone_number'], $operatorId); + echo json_encode(['success' => true]); + } catch (Exception $e) { + // Fallback: clear in_service and log activity + $now = date('Y-m-d H:i:s'); + $db->update('users', ['in_service' => 0, 'in_service_by' => null, 'in_service_at' => null, 'advisor_requested' => 0], 'id = :id', ['id' => $userId]); + $db->insert('operator_activity', ['user_id' => $userId, 'operator_id' => $operatorId, 'action' => 'finish', 'details' => 'Finished attending via fallback', 'created_at' => $now]); + echo json_encode(['success' => true, 'warning' => 'BotService failed, fallback applied']); + } +} catch (Exception $e) { + http_response_code(500); + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} diff --git a/conversations.php b/conversations.php index 3bcf613..e83c7ef 100644 --- a/conversations.php +++ b/conversations.php @@ -477,6 +477,7 @@ +1234567890
+
@@ -892,6 +893,7 @@ // Attender (marcar 'en servicio' sin liberar) const attendBtn = document.getElementById('attend-btn'); + const finishBtn = document.getElementById('finish-attend-btn'); if (attendBtn) { attendBtn.style.display = (conv.advisor_requested && !conv.in_service) ? 'inline-block' : 'none'; attendBtn.onclick = async () => { @@ -915,6 +917,8 @@ attendBtn.style.display = 'none'; // keep release available releaseBtn.style.display = 'inline-block'; + // show finish button + if (finishBtn) finishBtn.style.display = 'inline-block'; await this.loadConversations(); } else { alert('Error al marcar como atendida'); @@ -925,6 +929,40 @@ } }; } + + // Finalizar atención: enviar encuesta y limpiar estado + if (finishBtn) { + finishBtn.style.display = conv.in_service ? 'inline-block' : 'none'; + finishBtn.onclick = async () => { + if (!confirm('¿Finalizar atención y enviar encuesta al usuario?')) return; + try { + const resp = await fetch('api/finish_attend.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ user_id: userId }) + }); + if (resp.status === 401) { + alert('Sesión expirada. Por favor inicie sesión de nuevo.'); + return; + } + const json = await resp.json(); + if (json && json.success) { + conv.in_service = false; + conv.advisor_requested = 0; + holdIndicator.style.display = 'none'; + finishBtn.style.display = 'none'; + releaseBtn.style.display = 'none'; + attendBtn.style.display = 'none'; + await this.loadConversations(); + } else { + alert('Error al finalizar la atención'); + } + } catch (e) { + console.error('Error finalizing attend', e); + alert('Error al finalizar la atención'); + } + }; + } } } }; diff --git a/scripts/insert_activity_test.php b/scripts/insert_activity_test.php new file mode 100644 index 0000000..0982a3d --- /dev/null +++ b/scripts/insert_activity_test.php @@ -0,0 +1,8 @@ +insert('operator_activity', ['user_id' => 1, 'operator_id' => 1, 'action' => 'test', 'details' => 'test insert', 'created_at' => $now]); +var_dump($id); +$rows = $db->fetchAll('SELECT * FROM operator_activity ORDER BY created_at DESC LIMIT 5'); +var_dump($rows); diff --git a/scripts/print_operator_activity.php b/scripts/print_operator_activity.php new file mode 100644 index 0000000..79b63a6 --- /dev/null +++ b/scripts/print_operator_activity.php @@ -0,0 +1,7 @@ +fetchAll('SELECT * FROM operator_activity ORDER BY created_at DESC LIMIT 10'); +foreach ($rows as $r) { + echo json_encode($r) . PHP_EOL; +} diff --git a/scripts/test_attend.php b/scripts/test_attend.php new file mode 100644 index 0000000..3170de4 --- /dev/null +++ b/scripts/test_attend.php @@ -0,0 +1,26 @@ +execute('DELETE FROM users WHERE phone_number = :p', ['p' => $phone]); +$id = $db->insert('users', ['phone_number' => $phone, 'status' => 'active', 'created_at' => date('Y-m-d H:i:s')]); +$db->update('users', ['advisor_requested' => 1], 'id = :id', ['id' => $id]); + +$bot = new BotService(); +$bot->attendConversation($phone, 1); + +$user = $db->fetch('SELECT * FROM users WHERE id = :id', ['id' => $id]); +$activity = $db->fetch('SELECT * FROM operator_activity WHERE user_id = :uid ORDER BY created_at DESC LIMIT 1', ['uid' => $id]); + +echo "User in_service: " . ($user['in_service'] ?? 'NULL') . PHP_EOL; +echo "in_service_by: " . ($user['in_service_by'] ?? 'NULL') . PHP_EOL; +echo "in_service_at: " . ($user['in_service_at'] ?? 'NULL') . PHP_EOL; + +if ($activity) { + echo "Activity: action={$activity['action']} operator_id={$activity['operator_id']} details={$activity['details']}\n"; +} else { + echo "No operator activity found\n"; +} diff --git a/scripts/test_finish_attend.php b/scripts/test_finish_attend.php new file mode 100644 index 0000000..c096987 --- /dev/null +++ b/scripts/test_finish_attend.php @@ -0,0 +1,25 @@ +execute('DELETE FROM users WHERE phone_number = :p', ['p' => $phone]); +$id = $db->insert('users', ['phone_number' => $phone, 'status' => 'active', 'created_at' => date('Y-m-d H:i:s')]); +$db->update('users', ['advisor_requested' => 1], 'id = :id', ['id' => $id]); + +$bot = new BotService(); +$bot->attendConversation($phone, 1); +$user = $db->fetch('SELECT * FROM users WHERE id = :id', ['id' => $id]); +echo "After attend: in_service={$user['in_service']} in_service_by={$user['in_service_by']}\n"; + +$bot->finishAttendConversation($phone, 1); +$user2 = $db->fetch('SELECT * FROM users WHERE id = :id', ['id' => $id]); +echo "After finish: in_service={$user2['in_service']} in_service_by={$user2['in_service_by']}\n"; +$activity = $db->fetch('SELECT * FROM operator_activity WHERE user_id = :uid ORDER BY created_at DESC LIMIT 1', ['uid' => $id]); +if ($activity) { + echo "Activity: action={$activity['action']} details={$activity['details']}\n"; +} else { + echo "No activity\n"; +} diff --git a/services/BotService.php b/services/BotService.php index a1ed429..4281998 100644 --- a/services/BotService.php +++ b/services/BotService.php @@ -545,6 +545,50 @@ class BotService { } } + /** + * Finalizar la atención: limpiar estado 'in_service' y enviar plantilla de encuesta + */ + public function finishAttendConversation($phoneNumber, $operatorId = null) { + try { + // Limpiar estado de 'in_service' + $this->db->update('users', ['in_service' => 0, 'in_service_by' => null, 'in_service_at' => null, 'advisor_requested' => 0], 'phone_number = :phone', ['phone' => $phoneNumber]); + + // Enviar plantilla de encuesta (configurable) + $template = getConfigFromDB('survey_template', 'encuesta_satisfaccin'); + $lang = getConfigFromDB('survey_template_language', 'es'); + + try { + $this->whatsappService->sendTemplateMessage($phoneNumber, $template, $lang, []); + } catch (Exception $e) { + // Ignorar errores de envío de plantilla pero loguear + error_log('Failed to send survey template: ' . $e->getMessage()); + if (function_exists('writeLog')) writeLog('WARN', 'Failed to send survey template: ' . $e->getMessage()); + } + + // Registrar actividad del operador + $user = $this->db->fetch('SELECT id FROM users WHERE phone_number = :phone', ['phone' => $phoneNumber]); + $userId = $user['id'] ?? null; + $now = date('Y-m-d H:i:s'); + $activity = [ + 'user_id' => $userId, + 'operator_id' => $operatorId, + 'action' => 'finish', + 'details' => "Finished attend and sent survey: {$template}", + 'created_at' => $now + ]; + try { + $this->db->insert('operator_activity', $activity); + } catch (Exception $e) { + error_log('Failed to insert operator_activity on finish: ' . $e->getMessage()); + } + + if (function_exists('writeLog')) writeLog('INFO', "Operator {$operatorId} finished attending for {$phoneNumber}, survey={$template}"); + } catch (Exception $e) { + error_log('finishAttendConversation failed: ' . $e->getMessage()); + throw $e; + } + } + /** * Actualizar estado del menú del usuario */