shuttlepro-shared 1.3.13 → 1.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/constants/index.js +0 -15
- package/index.js +0 -8
- package/models/UserRole.js +119 -1
- package/models/Website.js +1 -0
- package/models.js +1 -62
- package/package.json +2 -13
- package/common/repositories/chatMember.repository.js +0 -9
- package/common/repositories/customerProfile.repository.js +0 -147
- package/common/repositories/descriptionTemplates.repository.js +0 -229
- package/common/repositories/index.js +0 -32
- package/common/repositories/integration.repository.js +0 -210
- package/common/repositories/label.repository.js +0 -95
- package/common/repositories/notificationSettings.repository.js +0 -95
- package/common/repositories/role.repository.js +0 -333
- package/common/repositories/settings.repository.js +0 -32
- package/common/repositories/shipper.repository.js +0 -77
- package/common/repositories/socialMediaSetting.repository.js +0 -33
- package/common/repositories/user.repository.js +0 -150
- package/common/repositories/userPermission.repository.js +0 -228
- package/common/repositories/userRepository.js +0 -31
- package/common/repositories/userRole.repository.js +0 -235
- package/common/repositories/userRolePermission.repository.js +0 -59
- package/common/repositories/workspace.repository.js +0 -147
- package/config/bull.js +0 -78
- package/config/config.js +0 -14
- package/config/database.js +0 -4
- package/config/index.js +0 -13
- package/config/redis.js +0 -196
- package/config/socket.js +0 -172
- package/models/AgentActivity.js +0 -192
- package/models/Assignment.js +0 -23
- package/models/BusinessDistribution.js +0 -23
- package/models/Card.js +0 -144
- package/models/CardComments.js +0 -33
- package/models/ChatMember.js +0 -17
- package/models/Chatbot.js +0 -20
- package/models/Checkpoint.js +0 -50
- package/models/City.js +0 -17
- package/models/Column.js +0 -28
- package/models/Conversation.js +0 -87
- package/models/Customer.js +0 -36
- package/models/CustomerProfile.js +0 -27
- package/models/DefaultRolePermission.js +0 -34
- package/models/DescriptionTemplate.js +0 -22
- package/models/Integration.js +0 -51
- package/models/Label.js +0 -42
- package/models/Message.js +0 -47
- package/models/NewProduct.js +0 -71
- package/models/NotificationSettings.js +0 -130
- package/models/Order.js +0 -236
- package/models/OrderProduct.js +0 -37
- package/models/Profile.js +0 -127
- package/models/Report.js +0 -27
- package/models/Setting.js +0 -18
- package/models/Shipper.js +0 -62
- package/models/SocialMediaSetting.js +0 -28
- package/models/Status.js +0 -58
- package/models/StatusType.js +0 -10
- package/models/Step.js +0 -50
- package/models/Type.js +0 -25
- package/models/UserWorkflow.js +0 -46
- package/models/Workspace.js +0 -308
- package/utils/decorator-factory.js +0 -264
- package/utils/logger.js +0 -41
package/config/bull.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
const Queue = require("bull");
|
|
2
|
-
const config = require("./config");
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create a new queue.
|
|
6
|
-
* @param {string} queueName - The name of the queue.
|
|
7
|
-
* @param {Object} [redisConfig=config.redis] - Redis configuration.
|
|
8
|
-
* @returns {Object} - A collection of queue-related functions.
|
|
9
|
-
*/
|
|
10
|
-
const createQueue = (queueName, redisConfig = config.redis) => {
|
|
11
|
-
const queue = new Queue(queueName, { redis: redisConfig });
|
|
12
|
-
|
|
13
|
-
// Attach event listeners for logging
|
|
14
|
-
queue.on("completed", (job) => console.log(`Job ${job.id} completed.`));
|
|
15
|
-
queue.on("failed", (job, err) => console.error(`Job ${job.id} failed:`, err));
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Add a job to the queue.
|
|
19
|
-
* @param {Object} data - Data to be processed by the job.
|
|
20
|
-
* @param {Object} [options] - Bull job options (e.g., delay, attempts).
|
|
21
|
-
* @returns {Promise<Job>} - The created job.
|
|
22
|
-
*/
|
|
23
|
-
const addJob = async (
|
|
24
|
-
data,
|
|
25
|
-
options = {
|
|
26
|
-
attempts: 3,
|
|
27
|
-
removeOnComplete: true,
|
|
28
|
-
}
|
|
29
|
-
) => {
|
|
30
|
-
return await queue.add(data, options);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Process jobs in the queue.
|
|
35
|
-
* @param {Function} processor - The function to process each job.
|
|
36
|
-
*/
|
|
37
|
-
const processJobs = (processor) => {
|
|
38
|
-
queue.process(processor);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Close the queue connection.
|
|
43
|
-
* @returns {Promise<void>}
|
|
44
|
-
*/
|
|
45
|
-
const closeConnection = async () => {
|
|
46
|
-
await queue.close();
|
|
47
|
-
console.log(`Queue "${queue.name}" connection closed.`);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Pause the queue.
|
|
52
|
-
* @returns {Promise<void>}
|
|
53
|
-
*/
|
|
54
|
-
const pauseQueue = async () => {
|
|
55
|
-
await queue.pause();
|
|
56
|
-
console.log(`Queue "${queue.name}" paused.`);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Resume the queue.
|
|
61
|
-
* @returns {Promise<void>}
|
|
62
|
-
*/
|
|
63
|
-
const resumeQueue = async () => {
|
|
64
|
-
await queue.resume();
|
|
65
|
-
console.log(`Queue "${queue.name}" resumed.`);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// Return the functional interface
|
|
69
|
-
return {
|
|
70
|
-
addJob,
|
|
71
|
-
processJobs,
|
|
72
|
-
closeConnection,
|
|
73
|
-
pauseQueue,
|
|
74
|
-
resumeQueue,
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
module.exports = { createQueue };
|
package/config/config.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const ALLOWED_URLS = process.env.ALLOWED_ORIGIN.split(",");
|
|
2
|
-
const WEBHOOK_API_KEY = process.env.API_KEY || process.env.WEBHOOK_API_KEY;
|
|
3
|
-
const mode = process.env.MODE || "production";
|
|
4
|
-
|
|
5
|
-
const redis = {
|
|
6
|
-
url: process.env.REDIS_URI,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
module.exports = {
|
|
10
|
-
WEBHOOK_API_KEY,
|
|
11
|
-
ALLOWED_URLS,
|
|
12
|
-
mode,
|
|
13
|
-
redis,
|
|
14
|
-
};
|
package/config/database.js
DELETED
package/config/index.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const bullConfig = require("./bull");
|
|
2
|
-
const redisConfig = require("./redis");
|
|
3
|
-
const config = require("./config");
|
|
4
|
-
const databaseConfig = require("./database");
|
|
5
|
-
const socketConfig = require("./socket");
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
bullConfig,
|
|
9
|
-
redisConfig,
|
|
10
|
-
config,
|
|
11
|
-
databaseConfig,
|
|
12
|
-
socketConfig,
|
|
13
|
-
};
|
package/config/redis.js
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
const { createClient } = require("redis");
|
|
2
|
-
require("dotenv").config();
|
|
3
|
-
|
|
4
|
-
const REDIS_URL = process.env.REDIS_URL || "redis://localhost:6379";
|
|
5
|
-
|
|
6
|
-
// ✅ Create main Redis client
|
|
7
|
-
const client = createClient({
|
|
8
|
-
url: REDIS_URL,
|
|
9
|
-
socket: { reconnectStrategy: (retries) => Math.min(retries * 50, 1000) }, // Exponential backoff
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
// ✅ Create separate Pub/Sub clients
|
|
13
|
-
const publisher = client.duplicate();
|
|
14
|
-
const subscriber = client.duplicate();
|
|
15
|
-
|
|
16
|
-
// ✅ Handle Redis Connection Events
|
|
17
|
-
client.on("error", (err) => console.error("❌ Redis Error:", err));
|
|
18
|
-
client.on("connect", () => console.log("✅ Redis Connected"));
|
|
19
|
-
client.on("ready", () => console.log("🚀 Redis Ready to use"));
|
|
20
|
-
client.on("end", () => console.log("❗ Redis Connection Closed"));
|
|
21
|
-
|
|
22
|
-
// ✅ Ensure Redis is connected before performing operations
|
|
23
|
-
const connectRedis = async () => {
|
|
24
|
-
if (!client.isOpen) {
|
|
25
|
-
try {
|
|
26
|
-
await client.connect();
|
|
27
|
-
await publisher.connect();
|
|
28
|
-
await subscriber.connect();
|
|
29
|
-
} catch (err) {
|
|
30
|
-
console.error("❌ Failed to connect to Redis:", err);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
await client.configSet("notify-keyspace-events", "Ex");
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* ✅ Publish Data to a Channel
|
|
38
|
-
* @param {string} channel - The Redis Pub/Sub channel
|
|
39
|
-
* @param {any} message - The message to send
|
|
40
|
-
*/
|
|
41
|
-
const publishToChannel = async (channel, message) => {
|
|
42
|
-
try {
|
|
43
|
-
await connectRedis();
|
|
44
|
-
await publisher.publish(channel, JSON.stringify(message));
|
|
45
|
-
} catch (err) {
|
|
46
|
-
console.error("❌ Error publishing message:", err);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* ✅ Subscribe & Listen for Messages
|
|
52
|
-
* @param {string} channel - The Redis Pub/Sub channel
|
|
53
|
-
* @param {function} callback - Callback function to handle messages
|
|
54
|
-
*/
|
|
55
|
-
const subscribeToChannel = async (channel, callback, expiry = false) => {
|
|
56
|
-
try {
|
|
57
|
-
await connectRedis();
|
|
58
|
-
await subscriber.subscribe(channel, (message) => {
|
|
59
|
-
if (expiry) callback(message);
|
|
60
|
-
else callback(JSON.parse(message));
|
|
61
|
-
});
|
|
62
|
-
} catch (err) {
|
|
63
|
-
console.error("❌ Error subscribing to channel:", err);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* ✅ Set Data in Redis (Supports String & Hash)
|
|
69
|
-
* @param {string} key - The Redis key
|
|
70
|
-
* @param {any} value - The value to store
|
|
71
|
-
* @param {string|null} field - Optional field for Hash storage
|
|
72
|
-
* @param {number} expiryInSeconds - Expiry time in seconds (default: 3600)
|
|
73
|
-
*/
|
|
74
|
-
const setRedisData = async (
|
|
75
|
-
key,
|
|
76
|
-
value,
|
|
77
|
-
field = null,
|
|
78
|
-
expiryInSeconds = 3600
|
|
79
|
-
) => {
|
|
80
|
-
try {
|
|
81
|
-
await connectRedis();
|
|
82
|
-
const stringifiedValue = JSON.stringify(value);
|
|
83
|
-
let result;
|
|
84
|
-
|
|
85
|
-
if (field) {
|
|
86
|
-
result = await client.hSet(key, field, stringifiedValue);
|
|
87
|
-
if (expiryInSeconds) {
|
|
88
|
-
await client.expire(key, expiryInSeconds);
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
result = expiryInSeconds
|
|
92
|
-
? await client.set(key, stringifiedValue, { EX: expiryInSeconds })
|
|
93
|
-
: await client.set(key, stringifiedValue);
|
|
94
|
-
}
|
|
95
|
-
return result;
|
|
96
|
-
} catch (err) {
|
|
97
|
-
console.error("❌ Error setting Redis data:", err);
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const addDataToRedisSet = async (key, value) => {
|
|
103
|
-
try {
|
|
104
|
-
await connectRedis();
|
|
105
|
-
await client.sAdd(key, value);
|
|
106
|
-
return true;
|
|
107
|
-
} catch (err) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const removeDataFromRedisSet = async (key, value) => {
|
|
113
|
-
try {
|
|
114
|
-
await connectRedis();
|
|
115
|
-
await client.sRem(key, value);
|
|
116
|
-
return true;
|
|
117
|
-
} catch (err) {
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
const isMemberOfRedisSet = async (key, value) => {
|
|
122
|
-
try {
|
|
123
|
-
await connectRedis();
|
|
124
|
-
return await client.sIsMember(key, value);
|
|
125
|
-
} catch (err) {
|
|
126
|
-
console.log(err, "err");
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
/**
|
|
131
|
-
* ✅ Get Data from Redis (Supports String & Hash)
|
|
132
|
-
* @param {string} key - The Redis key
|
|
133
|
-
* @param {string|null} field - Optional field for Hash retrieval
|
|
134
|
-
*/
|
|
135
|
-
const getRedisData = async (key, field = null) => {
|
|
136
|
-
try {
|
|
137
|
-
await connectRedis();
|
|
138
|
-
let result = field ? await client.hGet(key, field) : await client.get(key);
|
|
139
|
-
return result ? JSON.parse(result) : null;
|
|
140
|
-
} catch (err) {
|
|
141
|
-
console.error("❌ Error getting Redis data:", err);
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* ✅ Delete Data from Redis (Supports String & Hash)
|
|
148
|
-
* @param {string} key - The Redis key
|
|
149
|
-
* @param {string|null} field - Optional field for Hash deletion
|
|
150
|
-
*/
|
|
151
|
-
const deleteRedisData = async (key, field = null) => {
|
|
152
|
-
try {
|
|
153
|
-
await connectRedis();
|
|
154
|
-
return field ? await client.hDel(key, field) : await client.del(key);
|
|
155
|
-
} catch (err) {
|
|
156
|
-
console.error("❌ Error deleting Redis data:", err);
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* ✅ Graceful Shutdown Handling
|
|
163
|
-
*/
|
|
164
|
-
const closeClients = async () => {
|
|
165
|
-
if (client.isOpen) await client.quit();
|
|
166
|
-
if (publisher.isOpen) await publisher.quit();
|
|
167
|
-
if (subscriber.isOpen) await subscriber.quit();
|
|
168
|
-
console.log("❗ Redis Clients Disconnected Gracefully");
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
// ✅ Ensure Redis disconnects properly on process exit
|
|
172
|
-
process.on("exit", closeClients);
|
|
173
|
-
process.on("SIGINT", async () => {
|
|
174
|
-
await closeClients();
|
|
175
|
-
process.exit();
|
|
176
|
-
});
|
|
177
|
-
process.on("SIGTERM", async () => {
|
|
178
|
-
await closeClients();
|
|
179
|
-
process.exit();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// ✅ Export Functions
|
|
183
|
-
module.exports = {
|
|
184
|
-
client,
|
|
185
|
-
publisher,
|
|
186
|
-
subscriber,
|
|
187
|
-
setRedisData,
|
|
188
|
-
getRedisData,
|
|
189
|
-
deleteRedisData,
|
|
190
|
-
publishToChannel,
|
|
191
|
-
subscribeToChannel,
|
|
192
|
-
connectRedis,
|
|
193
|
-
addDataToRedisSet,
|
|
194
|
-
removeDataFromRedisSet,
|
|
195
|
-
isMemberOfRedisSet,
|
|
196
|
-
};
|
package/config/socket.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
const { Server } = require("socket.io");
|
|
2
|
-
const { publisher, subscriber, connectRedis } = require("./redis");
|
|
3
|
-
require("dotenv").config();
|
|
4
|
-
|
|
5
|
-
let io;
|
|
6
|
-
const namespaceSockets = {}; // Store different namespace sockets
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Initialize Socket.IO server with namespaces
|
|
10
|
-
* @param {http.Server} server - HTTP server instance
|
|
11
|
-
* @param {string} namespaceParam - Socket namespace name (default: "conversation")
|
|
12
|
-
* @param {string} redisChannel - Redis channel for this namespace (default: "socket_events")
|
|
13
|
-
* @returns {SocketIO.Namespace} - The initialized namespace
|
|
14
|
-
*/
|
|
15
|
-
const initializeSocket = async (
|
|
16
|
-
server,
|
|
17
|
-
namespaceParam = "conversation",
|
|
18
|
-
redisChannel = "socket_events"
|
|
19
|
-
) => {
|
|
20
|
-
// Initialize Socket.IO server if not already done
|
|
21
|
-
if (!io) {
|
|
22
|
-
io = new Server(server, {
|
|
23
|
-
cors: {
|
|
24
|
-
origin: "*",
|
|
25
|
-
methods: ["GET", "POST"],
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
console.log("✅ Socket.IO server initialized");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Return existing namespace if already initialized
|
|
32
|
-
if (namespaceSockets[namespaceParam]) {
|
|
33
|
-
console.log(`📢 Using existing namespace: /${namespaceParam}`);
|
|
34
|
-
return namespaceSockets[namespaceParam];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Create and store new namespace
|
|
38
|
-
const namespace = io.of(`/${namespaceParam}`);
|
|
39
|
-
namespaceSockets[namespaceParam] = namespace;
|
|
40
|
-
console.log(`🚀 Created new namespace: /${namespaceParam}`);
|
|
41
|
-
|
|
42
|
-
// Ensure Redis is connected
|
|
43
|
-
await connectRedis();
|
|
44
|
-
|
|
45
|
-
// Create a unique Redis channel for this namespace
|
|
46
|
-
const nsRedisChannel = `${redisChannel}_${namespaceParam}`;
|
|
47
|
-
|
|
48
|
-
// Subscribe to Redis events for this namespace
|
|
49
|
-
await subscriber.subscribe(nsRedisChannel, (messageStr) => {
|
|
50
|
-
try {
|
|
51
|
-
const message = JSON.parse(messageStr);
|
|
52
|
-
const { workspaceId, event, data } = message;
|
|
53
|
-
|
|
54
|
-
console.log(`📥 Redis message received on ${nsRedisChannel}:`, {
|
|
55
|
-
workspaceId,
|
|
56
|
-
event,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Emit to specific workspace room in this namespace
|
|
60
|
-
if (workspaceId) {
|
|
61
|
-
namespace.to(workspaceId).emit(event, data);
|
|
62
|
-
console.log(
|
|
63
|
-
`📢 Event ${event} emitted to workspace ${workspaceId} in /${namespaceParam}`
|
|
64
|
-
);
|
|
65
|
-
} else {
|
|
66
|
-
// Broadcast to all clients in this namespace if no workspaceId specified
|
|
67
|
-
namespace.emit(event, data);
|
|
68
|
-
console.log(
|
|
69
|
-
`📢 Event ${event} broadcasted to all clients in /${namespaceParam}`
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
} catch (err) {
|
|
73
|
-
console.error(
|
|
74
|
-
`❌ Error handling Redis message on ${nsRedisChannel}:`,
|
|
75
|
-
err
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Handle new socket connections to this namespace
|
|
81
|
-
namespace.on("connection", (socket) => {
|
|
82
|
-
const { workspaceId } = socket.handshake.query;
|
|
83
|
-
|
|
84
|
-
if (!workspaceId) {
|
|
85
|
-
console.warn(`⚠️ Connection rejected: No workspaceId provided`);
|
|
86
|
-
socket.disconnect(true);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
console.log(
|
|
91
|
-
`✅ Client connected: ${socket.id} (Workspace: ${workspaceId}) in /${namespaceParam}`
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
// Join workspace room
|
|
95
|
-
socket.join(workspaceId);
|
|
96
|
-
|
|
97
|
-
// Send connection confirmation to client
|
|
98
|
-
socket.emit("connected", {
|
|
99
|
-
status: "connected",
|
|
100
|
-
socketId: socket.id,
|
|
101
|
-
namespace: namespaceParam,
|
|
102
|
-
workspaceId,
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// Handle custom events from clients
|
|
106
|
-
socket.on("client_event", (data) => {
|
|
107
|
-
console.log(`📥 Client event from ${socket.id}:`, data);
|
|
108
|
-
// You can process client events here
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Handle disconnect
|
|
112
|
-
socket.on("disconnect", (reason) => {
|
|
113
|
-
console.log(
|
|
114
|
-
`❌ Client disconnected: ${socket.id} (Workspace: ${workspaceId}, Reason: ${reason})`
|
|
115
|
-
);
|
|
116
|
-
socket.leave(workspaceId);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// Handle errors
|
|
120
|
-
socket.on("error", (error) => {
|
|
121
|
-
console.error(`❌ Socket error for ${socket.id}:`, error);
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
console.log(
|
|
126
|
-
`✅ Namespace /${namespaceParam} initialized and listening on Redis channel: ${nsRedisChannel}`
|
|
127
|
-
);
|
|
128
|
-
return namespace;
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Send event to clients via Redis pub/sub
|
|
133
|
-
* @param {object} params - Event parameters
|
|
134
|
-
* @param {string} params.workspaceId - Target workspace ID
|
|
135
|
-
* @param {string} params.event - Event name
|
|
136
|
-
* @param {any} params.data - Event data payload
|
|
137
|
-
* @param {string} [params.namespace="conversation"] - Target namespace
|
|
138
|
-
* @param {string} [params.redisChannel="socket_events"] - Base Redis channel
|
|
139
|
-
* @returns {Promise<void>}
|
|
140
|
-
*/
|
|
141
|
-
const sendEventToServer = async ({
|
|
142
|
-
workspaceId,
|
|
143
|
-
event,
|
|
144
|
-
data,
|
|
145
|
-
namespace = "conversation",
|
|
146
|
-
redisChannel = "socket_events",
|
|
147
|
-
}) => {
|
|
148
|
-
try {
|
|
149
|
-
// Create namespace-specific Redis channel
|
|
150
|
-
const nsRedisChannel = `${redisChannel}_${namespace}`;
|
|
151
|
-
|
|
152
|
-
// Ensure Redis is connected
|
|
153
|
-
await connectRedis();
|
|
154
|
-
|
|
155
|
-
// Create message payload
|
|
156
|
-
const message = JSON.stringify({ workspaceId, event, data });
|
|
157
|
-
|
|
158
|
-
// Publish to Redis
|
|
159
|
-
await publisher.publish(nsRedisChannel, message);
|
|
160
|
-
|
|
161
|
-
console.log(
|
|
162
|
-
`📢 Event published to Redis channel ${nsRedisChannel}: ${event} (Workspace: ${workspaceId})`
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
return true;
|
|
166
|
-
} catch (err) {
|
|
167
|
-
console.error("❌ Error publishing to Redis:", err);
|
|
168
|
-
throw err;
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
module.exports = { initializeSocket, sendEventToServer };
|
package/models/AgentActivity.js
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
const mongoose = require("mongoose");
|
|
2
|
-
const { Schema } = mongoose;
|
|
3
|
-
|
|
4
|
-
const breakSchema = new mongoose.Schema({
|
|
5
|
-
refId: { type: String, required: true },
|
|
6
|
-
breakId: { type: String, required: false },
|
|
7
|
-
startTime: { type: Date, required: true },
|
|
8
|
-
endTime: { type: Date, required: false },
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
const responseSchema = new mongoose.Schema({
|
|
12
|
-
queryMessageId: { type: [String], default: [] },
|
|
13
|
-
responseMessageId: { type: [String], default: [] },
|
|
14
|
-
responseTime: { type: Number, required: false },
|
|
15
|
-
accuracy: { type: Number, required: false, default: 10 },
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const activitySchema = new mongoose.Schema({
|
|
19
|
-
refId: { type: String, required: true },
|
|
20
|
-
type: {
|
|
21
|
-
type: String,
|
|
22
|
-
required: true,
|
|
23
|
-
default: "other",
|
|
24
|
-
enum: ["conversation", "ticket", "order", "other"],
|
|
25
|
-
},
|
|
26
|
-
platformName: { type: String, required: false },
|
|
27
|
-
platformType: { type: String, required: false },
|
|
28
|
-
customerName: { type: String, default: "", required: false },
|
|
29
|
-
conversationId: { type: String, default: "", required: false },
|
|
30
|
-
profileId: { type: String, required: false },
|
|
31
|
-
conversationType: {
|
|
32
|
-
type: String,
|
|
33
|
-
enum: ["email", "comment", "message", ""],
|
|
34
|
-
default: "",
|
|
35
|
-
required: false,
|
|
36
|
-
},
|
|
37
|
-
status: { type: String, required: false, default: "unassigned" },
|
|
38
|
-
sourceType: { type: String, required: false, default: "normal" },
|
|
39
|
-
labels: [{ type: Schema.Types.ObjectId, ref: "Label" }],
|
|
40
|
-
platformId: { type: String, required: false },
|
|
41
|
-
assignTime: { type: Date, required: false },
|
|
42
|
-
qaScore: { type: Number, required: false, default: 10 },
|
|
43
|
-
startTime: { type: String, required: false },
|
|
44
|
-
endTime: { type: String, required: false },
|
|
45
|
-
resolutionTime: { type: String, required: false },
|
|
46
|
-
responses: { type: [responseSchema], default: [] },
|
|
47
|
-
remarks: { type: String, required: false },
|
|
48
|
-
avgAccuracy: { type: Number, required: false, default: 10 },
|
|
49
|
-
sender: { type: String, required: "" },
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const totalActivitySchema = new mongoose.Schema({
|
|
53
|
-
type: { type: String, required: true },
|
|
54
|
-
platformType: { type: String, required: false },
|
|
55
|
-
count: { type: Number, required: true },
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const agentActivitySchema = new mongoose.Schema(
|
|
59
|
-
{
|
|
60
|
-
_id: {
|
|
61
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
62
|
-
default: () => new mongoose.Types.ObjectId(),
|
|
63
|
-
},
|
|
64
|
-
agentId: { type: String, required: true },
|
|
65
|
-
agentRole: { type: String, default: "" },
|
|
66
|
-
agentName: { type: String, required: false },
|
|
67
|
-
agentShift: { type: Object, default: {}, required: false },
|
|
68
|
-
workspaceId: {
|
|
69
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
70
|
-
required: true,
|
|
71
|
-
ref: "Workspace",
|
|
72
|
-
},
|
|
73
|
-
date: { type: String, required: true },
|
|
74
|
-
lateMinutes: {
|
|
75
|
-
type: Number,
|
|
76
|
-
default: 0,
|
|
77
|
-
},
|
|
78
|
-
earlyLeaveMinutes: {
|
|
79
|
-
type: Number,
|
|
80
|
-
default: 0,
|
|
81
|
-
},
|
|
82
|
-
shiftStartTime: { type: [Date], default: [] },
|
|
83
|
-
shiftEndTime: { type: [Date], default: [] },
|
|
84
|
-
shifts: [
|
|
85
|
-
{
|
|
86
|
-
shiftStartTime: { type: Date, required: true, default: null },
|
|
87
|
-
shiftEndTime: { type: Date, required: false, default: null },
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
isLate: { type: Boolean, required: true, default: false },
|
|
91
|
-
isEarlyLeave: { type: Boolean, required: true, default: false },
|
|
92
|
-
breaks: { type: [breakSchema], default: [] },
|
|
93
|
-
activities: { type: [activitySchema], default: [] },
|
|
94
|
-
totalPsc: { type: Number, required: false, default: 0 },
|
|
95
|
-
totalQa: { type: Number, required: false, default: 0 },
|
|
96
|
-
weightedQa: { type: Number, required: false, default: 0 },
|
|
97
|
-
weightedPsc: { type: Number, required: false, default: 0 },
|
|
98
|
-
kpiScore: { type: Number, required: false, default: 0 },
|
|
99
|
-
totalActivities: { type: [totalActivitySchema], default: [] },
|
|
100
|
-
totalWorkTime: { type: Number, required: false, default: 0 },
|
|
101
|
-
totalBreakTime: { type: Number, required: false, default: 0 },
|
|
102
|
-
totalIdleTime: { type: Number, required: false, default: 0 },
|
|
103
|
-
},
|
|
104
|
-
{ timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } }
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
agentActivitySchema.index({ workspaceId: 1 });
|
|
108
|
-
agentActivitySchema.index({ date: 1 });
|
|
109
|
-
agentActivitySchema.index({ agentId: 1 });
|
|
110
|
-
agentActivitySchema.index({ "activities.platformId": 1 });
|
|
111
|
-
agentActivitySchema.index({ "activities.labels": 1 });
|
|
112
|
-
agentActivitySchema.index({ workspaceId: 1, date: 1, agentId: 1 });
|
|
113
|
-
agentActivitySchema.index({
|
|
114
|
-
workspaceId: 1,
|
|
115
|
-
date: 1,
|
|
116
|
-
agentId: 1,
|
|
117
|
-
"activities.platformId": 1,
|
|
118
|
-
"activities.labels": 1,
|
|
119
|
-
});
|
|
120
|
-
agentActivitySchema.index({
|
|
121
|
-
workspaceId: 1,
|
|
122
|
-
date: 1,
|
|
123
|
-
agentId: 1,
|
|
124
|
-
"activities.platformId": 1,
|
|
125
|
-
});
|
|
126
|
-
agentActivitySchema.index({
|
|
127
|
-
workspaceId: 1,
|
|
128
|
-
date: 1,
|
|
129
|
-
agentId: 1,
|
|
130
|
-
"activities.labels": 1,
|
|
131
|
-
});
|
|
132
|
-
agentActivitySchema.index(
|
|
133
|
-
{ "activities.platformId": 1, "activities.labels": 1 },
|
|
134
|
-
{
|
|
135
|
-
partialFilterExpression: {
|
|
136
|
-
"activities.platformId": { $exists: true },
|
|
137
|
-
"activities.labels": { $exists: true },
|
|
138
|
-
},
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
const AgentActivity = mongoose.model("AgentActivity", agentActivitySchema);
|
|
142
|
-
|
|
143
|
-
const findOneAndUpdateAgentActivity = async (
|
|
144
|
-
findQuery = {},
|
|
145
|
-
updateQuery = null
|
|
146
|
-
) => {
|
|
147
|
-
try {
|
|
148
|
-
if (!findQuery || Object.values(findQuery).length === 0) {
|
|
149
|
-
console.log("Find Query is required.");
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const agentActivityForActivitiesUpdated = await AgentActivity.findOne(
|
|
154
|
-
findQuery
|
|
155
|
-
).sort({ createdAt: -1 });
|
|
156
|
-
|
|
157
|
-
if (!agentActivityForActivitiesUpdated) {
|
|
158
|
-
console.log("No matching record found.");
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const bsonSize = require("bson").calculateObjectSize(
|
|
163
|
-
agentActivityForActivitiesUpdated
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
if (bsonSize <= 1000000) {
|
|
167
|
-
return await AgentActivity.findOneAndUpdate(findQuery, updateQuery);
|
|
168
|
-
} else {
|
|
169
|
-
const { breaks, activities, totalActivities, ...restData } =
|
|
170
|
-
agentActivityForActivitiesUpdated.toObject();
|
|
171
|
-
|
|
172
|
-
const newAgentActivity = await AgentActivity.create({
|
|
173
|
-
...restData,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
const agentActivityRecord = await AgentActivity.findOneAndUpdate(
|
|
177
|
-
{ ...findQuery, _id: newAgentActivity._id },
|
|
178
|
-
updateQuery
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
return agentActivityRecord;
|
|
182
|
-
}
|
|
183
|
-
} catch (err) {
|
|
184
|
-
console.error("Error:", err);
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
module.exports = {
|
|
190
|
-
AgentActivity,
|
|
191
|
-
findOneAndUpdateAgentActivity,
|
|
192
|
-
};
|
package/models/Assignment.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const mongoose = require("mongoose");
|
|
2
|
-
|
|
3
|
-
const assignmentSchema = new mongoose.Schema({
|
|
4
|
-
cardId: {
|
|
5
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
6
|
-
ref: "Card",
|
|
7
|
-
required: true,
|
|
8
|
-
},
|
|
9
|
-
id: {
|
|
10
|
-
type: String,
|
|
11
|
-
required: true,
|
|
12
|
-
},
|
|
13
|
-
name: {
|
|
14
|
-
type: String,
|
|
15
|
-
},
|
|
16
|
-
email: {
|
|
17
|
-
type: String,
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const Assignment = mongoose.model("Assignment", assignmentSchema);
|
|
22
|
-
|
|
23
|
-
module.exports = Assignment;
|