From ac179cec9882988b4d80ad3adf7f9970c47fad69 Mon Sep 17 00:00:00 2001
From: lizandrogd <77708265+lizandrogd@users.noreply.github.com>
Date: Wed, 21 Jan 2026 16:32:40 -0500
Subject: [PATCH] up
---
api/attend.php | 41 +++++++++++++++++++++
api/get_conversations.php | 10 +++++-
conversations.php | 41 ++++++++++++++++++++-
scripts/add_user_in_service_column.php | 50 ++++++++++++++++++++++++++
services/BotService.php | 43 +++++++++++++++++++++-
5 files changed, 182 insertions(+), 3 deletions(-)
create mode 100644 api/attend.php
create mode 100644 scripts/add_user_in_service_column.php
diff --git a/api/attend.php b/api/attend.php
new file mode 100644
index 0000000..59c5354
--- /dev/null
+++ b/api/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->attendConversation($user['phone_number'], $operatorId);
+ echo json_encode(['success' => true]);
+ } catch (Exception $e) {
+ // Fallback: apply updates directly and log activity
+ $now = date('Y-m-d H:i:s');
+ $db->update('users', ['in_service' => 1, 'in_service_by' => $operatorId, 'in_service_at' => $now, 'advisor_requested' => 0], 'id = :id', ['id' => $userId]);
+ $db->insert('operator_activity', ['user_id' => $userId, 'operator_id' => $operatorId, 'action' => 'attend', 'details' => 'Marked in_service 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/api/get_conversations.php b/api/get_conversations.php
index fd8365f..d811d9b 100644
--- a/api/get_conversations.php
+++ b/api/get_conversations.php
@@ -23,6 +23,10 @@ try {
u.avatar_url,
u.bot_enabled,
u.on_hold,
+ u.advisor_requested,
+ u.in_service,
+ u.in_service_by,
+ u.in_service_at,
lm.message_id AS last_message_id,
lm.content AS last_message,
lm.direction AS direction,
@@ -60,7 +64,11 @@ try {
'message_type' => $conv['message_type'] ?? 'text',
'unread_count' => intval($conv['unread_count'] ?? 0),
'bot_enabled' => isset($conv['bot_enabled']) ? (bool)$conv['bot_enabled'] : true,
- 'on_hold' => isset($conv['on_hold']) ? (bool)$conv['on_hold'] : false
+ 'on_hold' => isset($conv['on_hold']) ? (bool)$conv['on_hold'] : false,
+ 'advisor_requested' => isset($conv['advisor_requested']) ? (bool)$conv['advisor_requested'] : false,
+ 'in_service' => isset($conv['in_service']) ? (bool)$conv['in_service'] : false,
+ 'in_service_by' => isset($conv['in_service_by']) ? intval($conv['in_service_by']) : null,
+ 'in_service_at' => $conv['in_service_at'] ?? null
];
}, $conversations);
diff --git a/conversations.php b/conversations.php
index 4db4910..3bcf613 100644
--- a/conversations.php
+++ b/conversations.php
@@ -475,7 +475,10 @@
EN ESPERA
+1234567890
-
+
+
+
+
@@ -886,6 +889,42 @@
alert('Error liberando espera');
}
};
+
+ // Attender (marcar 'en servicio' sin liberar)
+ const attendBtn = document.getElementById('attend-btn');
+ if (attendBtn) {
+ attendBtn.style.display = (conv.advisor_requested && !conv.in_service) ? 'inline-block' : 'none';
+ attendBtn.onclick = async () => {
+ try {
+ const resp = await fetch('api/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 = true;
+ conv.advisor_requested = 0;
+ holdIndicator.textContent = 'EN SERVICIO';
+ holdIndicator.style.color = '#28a745';
+ holdIndicator.style.display = 'inline';
+ attendBtn.style.display = 'none';
+ // keep release available
+ releaseBtn.style.display = 'inline-block';
+ await this.loadConversations();
+ } else {
+ alert('Error al marcar como atendida');
+ }
+ } catch (e) {
+ console.error('Error attending', e);
+ alert('Error al atender');
+ }
+ };
+ }
}
}
};
diff --git a/scripts/add_user_in_service_column.php b/scripts/add_user_in_service_column.php
new file mode 100644
index 0000000..efb1732
--- /dev/null
+++ b/scripts/add_user_in_service_column.php
@@ -0,0 +1,50 @@
+fetch("SHOW COLUMNS FROM users LIKE 'in_service'");
+ if ($col) {
+ echo "Column in_service already exists\n";
+ } else {
+ $db->query("ALTER TABLE users ADD COLUMN in_service TINYINT(1) DEFAULT 0 AFTER advisor_requested");
+ echo "Added in_service column\n";
+ }
+
+ $col = $db->fetch("SHOW COLUMNS FROM users LIKE 'in_service_by'");
+ if ($col) {
+ echo "Column in_service_by already exists\n";
+ } else {
+ $db->query("ALTER TABLE users ADD COLUMN in_service_by INT NULL AFTER in_service");
+ echo "Added in_service_by column\n";
+ }
+
+ $col = $db->fetch("SHOW COLUMNS FROM users LIKE 'in_service_at'");
+ if ($col) {
+ echo "Column in_service_at already exists\n";
+ } else {
+ $db->query("ALTER TABLE users ADD COLUMN in_service_at DATETIME NULL AFTER in_service_by");
+ echo "Added in_service_at column\n";
+ }
+
+ // Crear tabla operator_activity si no existe
+ $check = $db->fetch("SHOW TABLES LIKE 'operator_activity'");
+ if ($check) {
+ echo "Table operator_activity already exists\n";
+ } else {
+ $sql = "CREATE TABLE operator_activity (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ user_id INT NULL,
+ operator_id INT NULL,
+ action VARCHAR(50) NOT NULL,
+ details TEXT NULL,
+ created_at DATETIME NOT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
+ $db->query($sql);
+ echo "Created table operator_activity\n";
+ }
+
+ echo "Done.\n";
+} catch (Exception $e) {
+ echo "Migration failed: " . $e->getMessage() . "\n";
+}
diff --git a/services/BotService.php b/services/BotService.php
index 0c1bac4..a1ed429 100644
--- a/services/BotService.php
+++ b/services/BotService.php
@@ -138,7 +138,7 @@ class BotService {
} 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.");
+ //$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
}
@@ -504,6 +504,47 @@ class BotService {
}
}
+ /**
+ * Marcar la conversaci贸n como "en servicio" por un operador (Atender)
+ */
+ public function attendConversation($phoneNumber, $operatorId = null) {
+ try {
+ $now = date('Y-m-d H:i:s');
+ $update = ['in_service' => 1, 'in_service_at' => $now, 'advisor_requested' => 0];
+ if ($operatorId) $update['in_service_by'] = $operatorId;
+ $this->db->update('users', $update, 'phone_number = :phone', ['phone' => $phoneNumber]);
+
+ // Notificar al usuario
+ try {
+ $this->whatsappService->sendTextMessage($phoneNumber, "馃敂 Un asesor est谩 atendiendo tu conversaci贸n. Por favor, espera su respuesta.");
+ } catch (Exception $e) {
+ // ignore send errors
+ }
+
+ // Registrar actividad del operador si hay informaci贸n disponible
+ $user = $this->db->fetch('SELECT id FROM users WHERE phone_number = :phone', ['phone' => $phoneNumber]);
+ $userId = $user['id'] ?? null;
+ $activity = [
+ 'user_id' => $userId,
+ 'operator_id' => $operatorId,
+ 'action' => 'attend',
+ 'details' => 'Operator started attending the conversation',
+ 'created_at' => $now
+ ];
+ try {
+ $this->db->insert('operator_activity', $activity);
+ } catch (Exception $e) {
+ if (function_exists('writeLog')) writeLog('WARN', 'Failed to insert operator_activity: ' . $e->getMessage());
+ error_log('Failed to insert operator_activity: ' . $e->getMessage());
+ }
+
+ if (function_exists('writeLog')) writeLog('INFO', "Operator {$operatorId} attending conversation for {$phoneNumber}");
+ } catch (Exception $e) {
+ error_log('attendConversation failed: ' . $e->getMessage());
+ throw $e;
+ }
+ }
+
/**
* Actualizar estado del men煤 del usuario
*/