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
*/