From 66eb7a8fc40d6668daf71a61ff0ef131871ad1cb Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 13 May 2020 18:52:36 -0300 Subject: [PATCH 01/10] Add new setting to get the last agent chatted. --- app/livechat/server/lib/Livechat.js | 9 +++++-- .../hooks/checkDefaultAgentOnNewRoom.js | 25 +++++++++++++++++++ ee/app/livechat-enterprise/server/index.js | 1 + ee/app/livechat-enterprise/server/settings.js | 8 ++++++ ee/i18n/en.i18n.json | 2 ++ ee/i18n/pt-BR.i18n.json | 2 ++ 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js diff --git a/app/livechat/server/lib/Livechat.js b/app/livechat/server/lib/Livechat.js index 33a77296e75c..395dd181388a 100644 --- a/app/livechat/server/lib/Livechat.js +++ b/app/livechat/server/lib/Livechat.js @@ -118,8 +118,13 @@ export const Livechat = { } if (room == null) { + console.log('agent'); + console.log(agent); + const defaultAgent = callbacks.run('livechat.checkDefaultAgentOnNewRoom', agent, guest); + console.log('defaultAgent'); + console.log(defaultAgent); // if no department selected verify if there is at least one active and pick the first - if (!agent && !guest.department) { + if (!defaultAgent && !guest.department) { const department = this.getRequiredDepartment(); if (department) { @@ -128,7 +133,7 @@ export const Livechat = { } // delegate room creation to QueueManager - room = await QueueManager.requestRoom({ guest, message, roomInfo, agent, extraData }); + room = await QueueManager.requestRoom({ guest, message, roomInfo, agent: defaultAgent, extraData }); newRoom = true; } diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js new file mode 100644 index 000000000000..ea77e4b41db7 --- /dev/null +++ b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js @@ -0,0 +1,25 @@ +// import { Meteor } from 'meteor/meteor'; + +import { callbacks } from '../../../../../app/callbacks'; +// import LivechatPriority from '../../../models/server/models/Li'; + +callbacks.add('livechat.checkDefaultAgentOnNewRoom', (agent, guest) => { + if (agent) { + return agent; + } + + /* + const { priority: searchTerm } = extraData; + if (!searchTerm) { + return roomInfo; + } + + const priority = LivechatPriority.findOneByIdOrName(searchTerm); + if (!priority) { + throw new Meteor.Error('error-invalid-priority', 'Invalid priority', { function: 'livechat.beforeRoom' }); + } + + const { _id: priorityId } = priority; + return Object.assign({ ...roomInfo }, { priorityId }); + */ +}, callbacks.priority.MEDIUM, 'livechat-check-default-agent-new-room'); diff --git a/ee/app/livechat-enterprise/server/index.js b/ee/app/livechat-enterprise/server/index.js index 63f36630a18c..91e576a2ce83 100644 --- a/ee/app/livechat-enterprise/server/index.js +++ b/ee/app/livechat-enterprise/server/index.js @@ -27,6 +27,7 @@ import './hooks/beforeNewInquiry'; import './hooks/beforeNewRoom'; import './hooks/beforeRoutingChat'; import './hooks/checkAgentBeforeTakeInquiry'; +import './hooks/checkDefaultAgentOnNewRoom'; import './hooks/onCheckRoomParamsApi'; import './hooks/onLoadConfigApi'; import './hooks/onSetUserStatusLivechat'; diff --git a/ee/app/livechat-enterprise/server/settings.js b/ee/app/livechat-enterprise/server/settings.js index 8d91cb92f6c2..24932b5b1dac 100644 --- a/ee/app/livechat-enterprise/server/settings.js +++ b/ee/app/livechat-enterprise/server/settings.js @@ -51,5 +51,13 @@ export const createSettings = () => { enableQuery: { _id: 'Livechat_auto_close_abandoned_rooms', value: true }, }); + settings.add('Livechat_last_chatted_agent_routing', false, { + type: 'boolean', + group: 'Omnichannel', + section: 'Routing', + i18nLabel: 'Livechat_last_chatted_agent_preferred', + enableQuery: { _id: 'Livechat_Routing_Method', value: { $ne: 'Manual_Selection' } }, + }); + Settings.addOptionValueById('Livechat_Routing_Method', { key: 'Load_Balancing', i18nLabel: 'Load_Balancing' }); }; diff --git a/ee/i18n/en.i18n.json b/ee/i18n/en.i18n.json index 09f587ee2297..d178767a7eac 100644 --- a/ee/i18n/en.i18n.json +++ b/ee/i18n/en.i18n.json @@ -34,6 +34,8 @@ "List_of_departments_for_forward": "List of departments allowed for forwarding (Optional)", "List_of_departments_for_forward_description": "Allow to set a restricted list of departments that can receive chats from this department", "Livechat_abandoned_rooms_closed_custom_message": "Custom message when room is automatically closed by visitor inactivity", + "Livechat_last_chatted_agent_preferred": "Last-Chatted Agent Preferred", + "Livechat_last_chatted_agent_preferred_Description": "The Last-Chatted Agent setting allocates chats to the agent who previously interacted with the same visitor if the agent is available when the chat starts.", "Livechat_Monitors": "Monitors", "Livechat_monitors": "Livechat monitors", "Max_number_of_chats_per_agent": "Max. number of simultaneous chats", diff --git a/ee/i18n/pt-BR.i18n.json b/ee/i18n/pt-BR.i18n.json index 892daf29eed0..83e9fe52d0be 100644 --- a/ee/i18n/pt-BR.i18n.json +++ b/ee/i18n/pt-BR.i18n.json @@ -26,6 +26,8 @@ "List_of_departments_for_forward": "Lista de departamentos permitidos para o encaminhamento(Opcional).", "List_of_departments_for_forward_description": "Permite definir uma lista restrita de departamentos que podem receber conversas desse departamento.", "Livechat_abandoned_rooms_closed_custom_message": "Mensagem customizada para usar quando a sala for automaticamente fechada por abandono do visitante", + "Livechat_last_chatted_agent_preferred": "Agente preferido pela última conversa", + "Livechat_last_chatted_agent_preferred_Description": "Agente preferido pela última conversa aloca bate-papos para o agente que interagiu anteriormente com o mesmo visitante, caso o agente esteja disponível quando o bate-papo for iniciado.", "Livechat_Monitors": "Monitores", "Livechat_monitors": "Monitores de Livechat", "Max_number_of_chats_per_agent": "Número máximo de atendimentos simultâneos", From a447b90187f604a07dd89e288bbcf96750d8d30b Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Thu, 14 May 2020 14:56:34 -0300 Subject: [PATCH 02/10] Store Visitor last agent info. --- app/livechat/server/lib/Livechat.js | 4 --- app/livechat/server/lib/RoutingManager.js | 2 +- app/models/server/models/LivechatRooms.js | 12 +++++++ app/models/server/models/LivechatVisitors.js | 14 ++++++++ app/models/server/models/Users.js | 4 +-- .../hooks/checkDefaultAgentOnNewRoom.js | 32 +++++++++++-------- .../hooks/saveDefaultAgentAfterTakeInquiry.js | 28 ++++++++++++++++ ee/app/livechat-enterprise/server/index.js | 1 + 8 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js diff --git a/app/livechat/server/lib/Livechat.js b/app/livechat/server/lib/Livechat.js index 395dd181388a..24ebd22c849d 100644 --- a/app/livechat/server/lib/Livechat.js +++ b/app/livechat/server/lib/Livechat.js @@ -118,11 +118,7 @@ export const Livechat = { } if (room == null) { - console.log('agent'); - console.log(agent); const defaultAgent = callbacks.run('livechat.checkDefaultAgentOnNewRoom', agent, guest); - console.log('defaultAgent'); - console.log(defaultAgent); // if no department selected verify if there is at least one active and pick the first if (!defaultAgent && !guest.department) { const department = this.getRequiredDepartment(); diff --git a/app/livechat/server/lib/RoutingManager.js b/app/livechat/server/lib/RoutingManager.js index 2f4579f29b7b..277ef9e5f0ca 100644 --- a/app/livechat/server/lib/RoutingManager.js +++ b/app/livechat/server/lib/RoutingManager.js @@ -146,7 +146,7 @@ export const RoutingManager = { LivechatInquiry.takeInquiry(_id); const inq = this.assignAgent(inquiry, agent); - callbacks.run('livechat.afterTakeInquiry', inq); + callbacks.runAsync('livechat.afterTakeInquiry', inq, agent); return LivechatRooms.findOneById(rid); }, diff --git a/app/models/server/models/LivechatRooms.js b/app/models/server/models/LivechatRooms.js index 25e2e51c6be2..0284e64cafac 100644 --- a/app/models/server/models/LivechatRooms.js +++ b/app/models/server/models/LivechatRooms.js @@ -164,6 +164,18 @@ export class LivechatRooms extends Base { return this.findOne(query, options); } + findLastServedAndClosedByVisitorToken(visitorToken, options = {}) { + const query = { + t: 'l', + 'v.token': visitorToken, + closedAt: { $exists: true }, + servedBy: { $exists: true }, + }; + + options.sort = { closedAt: -1 }; + return this.findOne(query, options); + } + findOneByVisitorToken(visitorToken, fields) { const options = {}; diff --git a/app/models/server/models/LivechatVisitors.js b/app/models/server/models/LivechatVisitors.js index 803ecf2dc56f..571d950b0fee 100644 --- a/app/models/server/models/LivechatVisitors.js +++ b/app/models/server/models/LivechatVisitors.js @@ -78,6 +78,20 @@ export class LivechatVisitors extends Base { return this.update(query, update); } + updateLastAgentByToken(token, lastAgent) { + const query = { + token, + }; + + const update = { + $set: { + lastAgent, + }, + }; + + return this.update(query, update); + } + /** * Find a visitor by their phone number * @return {object} User from db diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index 6b388bfa3402..b278b552e6e8 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -124,10 +124,10 @@ export class Users extends Base { return this.findOne(query); } - findOneOnlineAgentByUsername(username) { + findOneOnlineAgentByUsername(username, options) { const query = queryStatusAgentOnline({ username }); - return this.findOne(query); + return this.findOne(query, options); } findOneOnlineAgentById(_id) { diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js index ea77e4b41db7..869068dbeb79 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js +++ b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js @@ -1,25 +1,29 @@ -// import { Meteor } from 'meteor/meteor'; - import { callbacks } from '../../../../../app/callbacks'; -// import LivechatPriority from '../../../models/server/models/Li'; +import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; +import { settings } from '../../../../../app/settings'; +import { LivechatRooms, Users } from '../../../../../app/models/server'; callbacks.add('livechat.checkDefaultAgentOnNewRoom', (agent, guest) => { - if (agent) { + if (agent || !guest) { return agent; } - /* - const { priority: searchTerm } = extraData; - if (!searchTerm) { - return roomInfo; + if (!RoutingManager.getConfig().autoAssignAgent) { + return agent; + } + + if (!settings.get('Livechat_last_chatted_agent_routing')) { + return agent; } - const priority = LivechatPriority.findOneByIdOrName(searchTerm); - if (!priority) { - throw new Meteor.Error('error-invalid-priority', 'Invalid priority', { function: 'livechat.beforeRoom' }); + const { lastAgent: { username: usernameByVisitor } = {}, token } = guest; + const lastGuestAgent = usernameByVisitor && Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } }); + if (lastGuestAgent) { + return lastGuestAgent; } - const { _id: priorityId } = priority; - return Object.assign({ ...roomInfo }, { priorityId }); - */ + const room = LivechatRooms.findLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); + const { servedBy: { username: usernameByRoom } } = room; + const lastRoomAgent = usernameByRoom && Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); + return lastRoomAgent || agent; }, callbacks.priority.MEDIUM, 'livechat-check-default-agent-new-room'); diff --git a/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js b/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js new file mode 100644 index 000000000000..7b3592fb7437 --- /dev/null +++ b/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js @@ -0,0 +1,28 @@ +import { callbacks } from '../../../../../app/callbacks'; +import { settings } from '../../../../../app/settings'; +import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; +import { LivechatVisitors } from '../../../../../app/models/server'; + +callbacks.add('livechat.afterTakeInquiry', (inquiry, agent) => { + if (!inquiry || !agent) { + return inquiry; + } + + if (!RoutingManager.getConfig().autoAssignAgent) { + return inquiry; + } + + if (!settings.get('Livechat_last_chatted_agent_routing')) { + return inquiry; + } + + const { v: { token } = {} } = inquiry; + if (!token) { + return inquiry; + } + + const { agentId: _id, username } = agent; + LivechatVisitors.updateLastAgentByToken(token, { _id, username, ts: new Date() }); + + return inquiry; +}, callbacks.priority.MEDIUM, 'livechat-save-default-agent-after-take-inquiry'); diff --git a/ee/app/livechat-enterprise/server/index.js b/ee/app/livechat-enterprise/server/index.js index 91e576a2ce83..910f1c1301c0 100644 --- a/ee/app/livechat-enterprise/server/index.js +++ b/ee/app/livechat-enterprise/server/index.js @@ -33,6 +33,7 @@ import './hooks/onLoadConfigApi'; import './hooks/onSetUserStatusLivechat'; import './hooks/onCloseLivechat'; import './hooks/onSaveVisitorInfo'; +import './hooks/saveDefaultAgentAfterTakeInquiry'; import './lib/routing/LoadBalancing'; import { onLicense } from '../../license/server'; From 8b2f018ae34eea3e635c763e0b998b9b046838b4 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Thu, 14 May 2020 16:16:40 -0300 Subject: [PATCH 03/10] Check room object before get the servedBy property. --- .../server/hooks/checkDefaultAgentOnNewRoom.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js index 869068dbeb79..eb30bc55940f 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js +++ b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js @@ -23,7 +23,11 @@ callbacks.add('livechat.checkDefaultAgentOnNewRoom', (agent, guest) => { } const room = LivechatRooms.findLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); + if (!room || !room.servedBy) { + return agent; + } + const { servedBy: { username: usernameByRoom } } = room; - const lastRoomAgent = usernameByRoom && Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); + const lastRoomAgent = Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); return lastRoomAgent || agent; }, callbacks.priority.MEDIUM, 'livechat-check-default-agent-new-room'); From 28a2172a04fcf8beaa397465c10827c353346194 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Sat, 16 May 2020 14:39:39 -0300 Subject: [PATCH 04/10] Route the conversation to another agent when the last agent is not available. --- app/models/server/models/LivechatInquiry.js | 16 ++++++++-- .../server/hooks/beforeRoutingChat.js | 4 +-- .../hooks/checkAgentBeforeTakeInquiry.js | 3 ++ .../hooks/checkDefaultAgentOnNewRoom.js | 19 ++++++----- .../onMaxNumberSimultaneousChatsReached.js | 32 +++++++++++++++++++ ee/app/livechat-enterprise/server/index.js | 1 + .../livechat-enterprise/server/lib/Helper.js | 12 ++++++- 7 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js diff --git a/app/models/server/models/LivechatInquiry.js b/app/models/server/models/LivechatInquiry.js index 954c7083ab6a..bce6723f2c3e 100644 --- a/app/models/server/models/LivechatInquiry.js +++ b/app/models/server/models/LivechatInquiry.js @@ -45,6 +45,7 @@ export class LivechatInquiry extends Base { _id: inquiryId, }, { $set: { status: 'taken' }, + $unset: { defaultAgent: 1 }, }); } @@ -62,11 +63,14 @@ export class LivechatInquiry extends Base { /* * mark inquiry as queued */ - queueInquiry(inquiryId) { + queueInquiry(inquiryId, defaultAgent) { return this.update({ _id: inquiryId, }, { - $set: { status: 'queued' }, + $set: { + status: 'queued', + ...defaultAgent && { defaultAgent }, + }, }); } @@ -180,6 +184,14 @@ export class LivechatInquiry extends Base { return collectionObj.aggregate(aggregate).toArray(); } + removeDefaultAgentById(inquiryId) { + this.update({ + _id: inquiryId, + }, { + $unset: { defaultAgent: 1 }, + }); + } + /* * remove the inquiry by roomId */ diff --git a/ee/app/livechat-enterprise/server/hooks/beforeRoutingChat.js b/ee/app/livechat-enterprise/server/hooks/beforeRoutingChat.js index aec059e67649..cae961b5798b 100644 --- a/ee/app/livechat-enterprise/server/hooks/beforeRoutingChat.js +++ b/ee/app/livechat-enterprise/server/hooks/beforeRoutingChat.js @@ -3,7 +3,7 @@ import { settings } from '../../../../../app/settings'; import { LivechatInquiry } from '../../../../../app/models/server'; import { dispatchInquiryPosition, checkWaitingQueue } from '../lib/Helper'; -callbacks.add('livechat.beforeRouteChat', async (inquiry) => { +callbacks.add('livechat.beforeRouteChat', async (inquiry, agent) => { if (!settings.get('Livechat_waiting_queue')) { return inquiry; } @@ -18,7 +18,7 @@ callbacks.add('livechat.beforeRouteChat', async (inquiry) => { return inquiry; } - LivechatInquiry.queueInquiry(_id); + LivechatInquiry.queueInquiry(_id, agent); const [inq] = await LivechatInquiry.getCurrentSortedQueueAsync({ _id }); if (inq) { diff --git a/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js b/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js index 4cbdd304f043..513f07d8a3e9 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js +++ b/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js @@ -34,9 +34,12 @@ callbacks.add('livechat.checkAgentBeforeTakeInquiry', async (agent, inquiry) => const { queueInfo: { chats = 0 } = {} } = user; if (maxNumberSimultaneousChat <= chats) { + callbacks.run('livechat.onMaxNumberSimultaneousChatsReached', inquiry, agent); + if (!RoutingManager.getConfig().autoAssignAgent) { throw new Meteor.Error('error-max-number-simultaneous-chats-reached', 'Not allowed'); } + return null; } return agent; diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js index eb30bc55940f..ffe7c3546f2d 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js +++ b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js @@ -1,22 +1,25 @@ import { callbacks } from '../../../../../app/callbacks'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { settings } from '../../../../../app/settings'; -import { LivechatRooms, Users } from '../../../../../app/models/server'; +import { LivechatRooms, LivechatVisitors, Users } from '../../../../../app/models/server'; -callbacks.add('livechat.checkDefaultAgentOnNewRoom', (agent, guest) => { - if (agent || !guest) { - return agent; +callbacks.add('livechat.checkDefaultAgentOnNewRoom', (defaultAgent, defaultGuest) => { + if (defaultAgent || !defaultGuest) { + return defaultAgent; } if (!RoutingManager.getConfig().autoAssignAgent) { - return agent; + return defaultAgent; } if (!settings.get('Livechat_last_chatted_agent_routing')) { - return agent; + return defaultAgent; } + const { _id: guestId } = defaultGuest; + const guest = LivechatVisitors.findOneById(guestId, { fields: { lastAgent: 1 } }); const { lastAgent: { username: usernameByVisitor } = {}, token } = guest; + const lastGuestAgent = usernameByVisitor && Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } }); if (lastGuestAgent) { return lastGuestAgent; @@ -24,10 +27,10 @@ callbacks.add('livechat.checkDefaultAgentOnNewRoom', (agent, guest) => { const room = LivechatRooms.findLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); if (!room || !room.servedBy) { - return agent; + return defaultAgent; } const { servedBy: { username: usernameByRoom } } = room; const lastRoomAgent = Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); - return lastRoomAgent || agent; + return lastRoomAgent || defaultAgent; }, callbacks.priority.MEDIUM, 'livechat-check-default-agent-new-room'); diff --git a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js new file mode 100644 index 000000000000..4374a0a23158 --- /dev/null +++ b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js @@ -0,0 +1,32 @@ +import { callbacks } from '../../../../../app/callbacks'; +import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; +import { settings } from '../../../../../app/settings'; +import { LivechatInquiry } from '../../../../../app/models/server'; +import { processWaitingQueue } from '../lib/Helper'; + +callbacks.add('livechat.onMaxNumberSimultaneousChatsReached', (inquiry, agent) => { + if (!inquiry || !inquiry.defaultAgent) { + return inquiry; + } + + if (!RoutingManager.getConfig().autoAssignAgent) { + return inquiry; + } + + if (!settings.get('Livechat_last_chatted_agent_routing')) { + return inquiry; + } + + const { _id, defaultAgent, department } = inquiry; + + LivechatInquiry.removeDefaultAgentById(_id); + + const { _id: defaultAgentId } = defaultAgent; + const { agentId } = agent; + + if (defaultAgentId === agentId) { + processWaitingQueue(department); + } + + return LivechatInquiry.findOneById(_id); +}, callbacks.priority.MEDIUM, 'livechat-on-max-number-simultaneous-chats-reached'); diff --git a/ee/app/livechat-enterprise/server/index.js b/ee/app/livechat-enterprise/server/index.js index 910f1c1301c0..ba2b34e73b92 100644 --- a/ee/app/livechat-enterprise/server/index.js +++ b/ee/app/livechat-enterprise/server/index.js @@ -30,6 +30,7 @@ import './hooks/checkAgentBeforeTakeInquiry'; import './hooks/checkDefaultAgentOnNewRoom'; import './hooks/onCheckRoomParamsApi'; import './hooks/onLoadConfigApi'; +import './hooks/onMaxNumberSimultaneousChatsReached'; import './hooks/onSetUserStatusLivechat'; import './hooks/onCloseLivechat'; import './hooks/onSaveVisitorInfo'; diff --git a/ee/app/livechat-enterprise/server/lib/Helper.js b/ee/app/livechat-enterprise/server/lib/Helper.js index 072e98ac7d7f..4fa2a8c462ed 100644 --- a/ee/app/livechat-enterprise/server/lib/Helper.js +++ b/ee/app/livechat-enterprise/server/lib/Helper.js @@ -94,13 +94,23 @@ export const dispatchWaitingQueueStatus = async (department) => { }); }; +const normalizeDefaultAgent = (agent) => { + if (!agent) { + return; + } + + const { _id: agentId, username } = agent; + return { agentId, username }; +}; + const processWaitingQueue = async (department) => { const inquiry = LivechatInquiry.getNextInquiryQueued(department); if (!inquiry) { return; } - const room = await RoutingManager.delegateInquiry(inquiry); + const { defaultAgent } = inquiry; + const room = await RoutingManager.delegateInquiry(inquiry, normalizeDefaultAgent(defaultAgent)); const propagateAgentDelegated = Meteor.bindEnvironment((rid, agentId) => { dispatchAgentDelegated(rid, agentId); From 197fb4e37549865202bbd504e5ccb7c21726175d Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Mon, 18 May 2020 13:45:15 -0300 Subject: [PATCH 05/10] Call checkWaitingQueue when the max. number of chats per agent is reached. --- .../server/hooks/onMaxNumberSimultaneousChatsReached.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js index 4374a0a23158..46b6f5900eb7 100644 --- a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js +++ b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js @@ -2,7 +2,7 @@ import { callbacks } from '../../../../../app/callbacks'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { settings } from '../../../../../app/settings'; import { LivechatInquiry } from '../../../../../app/models/server'; -import { processWaitingQueue } from '../lib/Helper'; +import { checkWaitingQueue } from '../lib/Helper'; callbacks.add('livechat.onMaxNumberSimultaneousChatsReached', (inquiry, agent) => { if (!inquiry || !inquiry.defaultAgent) { @@ -25,7 +25,7 @@ callbacks.add('livechat.onMaxNumberSimultaneousChatsReached', (inquiry, agent) = const { agentId } = agent; if (defaultAgentId === agentId) { - processWaitingQueue(department); + checkWaitingQueue(department); } return LivechatInquiry.findOneById(_id); From 82afdb97be6437f7ed99144effec6a4818e7c6a4 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 20 May 2020 17:36:23 -0300 Subject: [PATCH 06/10] Unified setting name and translations. --- ee/app/livechat-enterprise/server/settings.js | 1 - ee/i18n/en.i18n.json | 4 ++-- ee/i18n/pt-BR.i18n.json | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ee/app/livechat-enterprise/server/settings.js b/ee/app/livechat-enterprise/server/settings.js index 24932b5b1dac..118fe5967a54 100644 --- a/ee/app/livechat-enterprise/server/settings.js +++ b/ee/app/livechat-enterprise/server/settings.js @@ -55,7 +55,6 @@ export const createSettings = () => { type: 'boolean', group: 'Omnichannel', section: 'Routing', - i18nLabel: 'Livechat_last_chatted_agent_preferred', enableQuery: { _id: 'Livechat_Routing_Method', value: { $ne: 'Manual_Selection' } }, }); diff --git a/ee/i18n/en.i18n.json b/ee/i18n/en.i18n.json index d178767a7eac..0c44d3332954 100644 --- a/ee/i18n/en.i18n.json +++ b/ee/i18n/en.i18n.json @@ -34,8 +34,8 @@ "List_of_departments_for_forward": "List of departments allowed for forwarding (Optional)", "List_of_departments_for_forward_description": "Allow to set a restricted list of departments that can receive chats from this department", "Livechat_abandoned_rooms_closed_custom_message": "Custom message when room is automatically closed by visitor inactivity", - "Livechat_last_chatted_agent_preferred": "Last-Chatted Agent Preferred", - "Livechat_last_chatted_agent_preferred_Description": "The Last-Chatted Agent setting allocates chats to the agent who previously interacted with the same visitor if the agent is available when the chat starts.", + "Livechat_last_chatted_agent_routing": "Last-Chatted Agent Preferred", + "Livechat_last_chatted_agent_routing_Description": "The Last-Chatted Agent setting allocates chats to the agent who previously interacted with the same visitor if the agent is available when the chat starts.", "Livechat_Monitors": "Monitors", "Livechat_monitors": "Livechat monitors", "Max_number_of_chats_per_agent": "Max. number of simultaneous chats", diff --git a/ee/i18n/pt-BR.i18n.json b/ee/i18n/pt-BR.i18n.json index 83e9fe52d0be..e7ebff498eae 100644 --- a/ee/i18n/pt-BR.i18n.json +++ b/ee/i18n/pt-BR.i18n.json @@ -26,8 +26,8 @@ "List_of_departments_for_forward": "Lista de departamentos permitidos para o encaminhamento(Opcional).", "List_of_departments_for_forward_description": "Permite definir uma lista restrita de departamentos que podem receber conversas desse departamento.", "Livechat_abandoned_rooms_closed_custom_message": "Mensagem customizada para usar quando a sala for automaticamente fechada por abandono do visitante", - "Livechat_last_chatted_agent_preferred": "Agente preferido pela última conversa", - "Livechat_last_chatted_agent_preferred_Description": "Agente preferido pela última conversa aloca bate-papos para o agente que interagiu anteriormente com o mesmo visitante, caso o agente esteja disponível quando o bate-papo for iniciado.", + "Livechat_last_chatted_agent_routing": "Agente preferido pela última conversa", + "Livechat_last_chatted_agent_routing_Description": "Agente preferido pela última conversa aloca bate-papos para o agente que interagiu anteriormente com o mesmo visitante, caso o agente esteja disponível quando o bate-papo for iniciado.", "Livechat_Monitors": "Monitores", "Livechat_monitors": "Monitores de Livechat", "Max_number_of_chats_per_agent": "Número máximo de atendimentos simultâneos", From 4c3a1a23bf988d49468a4f448e4b92f3adbecef1 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 20 May 2020 19:11:22 -0300 Subject: [PATCH 07/10] Fix file imports. --- .../server/hooks/checkDefaultAgentOnNewRoom.js | 4 ++-- .../server/hooks/onMaxNumberSimultaneousChatsReached.js | 4 ++-- .../server/hooks/saveDefaultAgentAfterTakeInquiry.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js index ffe7c3546f2d..eec6430d140c 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js +++ b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js @@ -1,6 +1,6 @@ -import { callbacks } from '../../../../../app/callbacks'; +import { callbacks } from '../../../../../app/callbacks/server'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; -import { settings } from '../../../../../app/settings'; +import { settings } from '../../../../../app/settings/server'; import { LivechatRooms, LivechatVisitors, Users } from '../../../../../app/models/server'; callbacks.add('livechat.checkDefaultAgentOnNewRoom', (defaultAgent, defaultGuest) => { diff --git a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js index 46b6f5900eb7..2dc7750e847f 100644 --- a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js +++ b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js @@ -1,6 +1,6 @@ -import { callbacks } from '../../../../../app/callbacks'; +import { callbacks } from '../../../../../app/callbacks/server'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; -import { settings } from '../../../../../app/settings'; +import { settings } from '../../../../../app/settings/server'; import { LivechatInquiry } from '../../../../../app/models/server'; import { checkWaitingQueue } from '../lib/Helper'; diff --git a/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js b/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js index 7b3592fb7437..cfadb39ac3f3 100644 --- a/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js +++ b/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js @@ -1,5 +1,5 @@ -import { callbacks } from '../../../../../app/callbacks'; -import { settings } from '../../../../../app/settings'; +import { callbacks } from '../../../../../app/callbacks/server'; +import { settings } from '../../../../../app/settings/server'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { LivechatVisitors } from '../../../../../app/models/server'; From 31cc1f6d7e9aa9c1e767b477c9574ae4e72e81e4 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 20 May 2020 19:50:52 -0300 Subject: [PATCH 08/10] Fix review requests. --- app/models/server/models/LivechatInquiry.js | 2 +- app/models/server/models/LivechatRooms.js | 4 +++- app/models/server/models/Rooms.js | 3 --- .../server/hooks/checkDefaultAgentOnNewRoom.js | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/models/server/models/LivechatInquiry.js b/app/models/server/models/LivechatInquiry.js index bce6723f2c3e..9dc6251a17cb 100644 --- a/app/models/server/models/LivechatInquiry.js +++ b/app/models/server/models/LivechatInquiry.js @@ -185,7 +185,7 @@ export class LivechatInquiry extends Base { } removeDefaultAgentById(inquiryId) { - this.update({ + return this.update({ _id: inquiryId, }, { $unset: { defaultAgent: 1 }, diff --git a/app/models/server/models/LivechatRooms.js b/app/models/server/models/LivechatRooms.js index 0284e64cafac..49823c11f896 100644 --- a/app/models/server/models/LivechatRooms.js +++ b/app/models/server/models/LivechatRooms.js @@ -16,6 +16,8 @@ export class LivechatRooms extends Base { this.tryEnsureIndex({ 'metrics.serviceTimeDuration': 1 }, { sparse: true }); this.tryEnsureIndex({ 'metrics.visitorInactivity': 1 }, { sparse: true }); this.tryEnsureIndex({ 'omnichannel.predictedVisitorAbandonmentAt': 1 }, { sparse: true }); + this.tryEnsureIndex({ closedAt: 1 }, { sparse: true }); + this.tryEnsureIndex({ servedBy: 1 }, { sparse: true }); } findLivechat(filter = {}, offset = 0, limit = 20) { @@ -164,7 +166,7 @@ export class LivechatRooms extends Base { return this.findOne(query, options); } - findLastServedAndClosedByVisitorToken(visitorToken, options = {}) { + findOneLastServedAndClosedByVisitorToken(visitorToken, options = {}) { const query = { t: 'l', 'v.token': visitorToken, diff --git a/app/models/server/models/Rooms.js b/app/models/server/models/Rooms.js index 0f038458b700..6e5007cabf90 100644 --- a/app/models/server/models/Rooms.js +++ b/app/models/server/models/Rooms.js @@ -20,9 +20,6 @@ export class Rooms extends Base { // discussions this.tryEnsureIndex({ prid: 1 }, { sparse: true }); this.tryEnsureIndex({ fname: 1 }, { sparse: true }); - // Livechat - statistics - this.tryEnsureIndex({ closedAt: 1 }, { sparse: true }); - // field used for DMs only this.tryEnsureIndex({ uids: 1 }, { sparse: true }); } diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js index eec6430d140c..3181870549e9 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js +++ b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js @@ -17,7 +17,7 @@ callbacks.add('livechat.checkDefaultAgentOnNewRoom', (defaultAgent, defaultGuest } const { _id: guestId } = defaultGuest; - const guest = LivechatVisitors.findOneById(guestId, { fields: { lastAgent: 1 } }); + const guest = LivechatVisitors.findOneById(guestId, { fields: { lastAgent: 1, token: 1 } }); const { lastAgent: { username: usernameByVisitor } = {}, token } = guest; const lastGuestAgent = usernameByVisitor && Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } }); @@ -25,7 +25,7 @@ callbacks.add('livechat.checkDefaultAgentOnNewRoom', (defaultAgent, defaultGuest return lastGuestAgent; } - const room = LivechatRooms.findLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); + const room = LivechatRooms.findOneLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); if (!room || !room.servedBy) { return defaultAgent; } From 03bef150413904b4ef1e1e1b8d1e4e3358aeaa26 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 20 May 2020 21:46:37 -0300 Subject: [PATCH 09/10] Add/Removed callback event handlers based on the setting. --- .../hooks/checkDefaultAgentOnNewRoom.js | 36 -------- .../handleLastChattedAgentPreferredEvents.js | 88 +++++++++++++++++++ .../onMaxNumberSimultaneousChatsReached.js | 32 ------- .../hooks/saveDefaultAgentAfterTakeInquiry.js | 28 ------ ee/app/livechat-enterprise/server/index.js | 4 +- 5 files changed, 89 insertions(+), 99 deletions(-) delete mode 100644 ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js create mode 100644 ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js delete mode 100644 ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js delete mode 100644 ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js diff --git a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js b/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js deleted file mode 100644 index 3181870549e9..000000000000 --- a/ee/app/livechat-enterprise/server/hooks/checkDefaultAgentOnNewRoom.js +++ /dev/null @@ -1,36 +0,0 @@ -import { callbacks } from '../../../../../app/callbacks/server'; -import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; -import { settings } from '../../../../../app/settings/server'; -import { LivechatRooms, LivechatVisitors, Users } from '../../../../../app/models/server'; - -callbacks.add('livechat.checkDefaultAgentOnNewRoom', (defaultAgent, defaultGuest) => { - if (defaultAgent || !defaultGuest) { - return defaultAgent; - } - - if (!RoutingManager.getConfig().autoAssignAgent) { - return defaultAgent; - } - - if (!settings.get('Livechat_last_chatted_agent_routing')) { - return defaultAgent; - } - - const { _id: guestId } = defaultGuest; - const guest = LivechatVisitors.findOneById(guestId, { fields: { lastAgent: 1, token: 1 } }); - const { lastAgent: { username: usernameByVisitor } = {}, token } = guest; - - const lastGuestAgent = usernameByVisitor && Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } }); - if (lastGuestAgent) { - return lastGuestAgent; - } - - const room = LivechatRooms.findOneLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); - if (!room || !room.servedBy) { - return defaultAgent; - } - - const { servedBy: { username: usernameByRoom } } = room; - const lastRoomAgent = Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); - return lastRoomAgent || defaultAgent; -}, callbacks.priority.MEDIUM, 'livechat-check-default-agent-new-room'); diff --git a/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js b/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js new file mode 100644 index 000000000000..87aa2850ec2a --- /dev/null +++ b/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js @@ -0,0 +1,88 @@ +import { callbacks } from '../../../../../app/callbacks/server'; +import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; +import { settings } from '../../../../../app/settings/server'; +import { LivechatRooms, LivechatInquiry, LivechatVisitors, Users } from '../../../../../app/models/server'; +import { checkWaitingQueue } from '../lib/Helper'; + +const checkDefaultAgentOnNewRoom = (defaultAgent, defaultGuest) => { + if (defaultAgent || !defaultGuest) { + return defaultAgent; + } + + if (!RoutingManager.getConfig().autoAssignAgent) { + return defaultAgent; + } + + const { _id: guestId } = defaultGuest; + const guest = LivechatVisitors.findOneById(guestId, { fields: { lastAgent: 1, token: 1 } }); + const { lastAgent: { username: usernameByVisitor } = {}, token } = guest; + + const lastGuestAgent = usernameByVisitor && Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } }); + if (lastGuestAgent) { + return lastGuestAgent; + } + + const room = LivechatRooms.findOneLastServedAndClosedByVisitorToken(token, { fields: { servedBy: 1 } }); + if (!room || !room.servedBy) { + return defaultAgent; + } + + const { servedBy: { username: usernameByRoom } } = room; + const lastRoomAgent = Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); + return lastRoomAgent || defaultAgent; +}; + +const onMaxNumberSimultaneousChatsReached = (inquiry, agent) => { + if (!inquiry || !inquiry.defaultAgent) { + return inquiry; + } + + if (!RoutingManager.getConfig().autoAssignAgent) { + return inquiry; + } + + const { _id, defaultAgent, department } = inquiry; + + LivechatInquiry.removeDefaultAgentById(_id); + + const { _id: defaultAgentId } = defaultAgent; + const { agentId } = agent; + + if (defaultAgentId === agentId) { + checkWaitingQueue(department); + } + + return LivechatInquiry.findOneById(_id); +}; + +const afterTakeInquiry = (inquiry, agent) => { + if (!inquiry || !agent) { + return inquiry; + } + + if (!RoutingManager.getConfig().autoAssignAgent) { + return inquiry; + } + + const { v: { token } = {} } = inquiry; + if (!token) { + return inquiry; + } + + const { agentId: _id, username } = agent; + LivechatVisitors.updateLastAgentByToken(token, { _id, username, ts: new Date() }); + + return inquiry; +}; +settings.get('Livechat_last_chatted_agent_routing', function(key, value) { + if (!value) { + callbacks.remove('livechat.checkDefaultAgentOnNewRoom', 'livechat-check-default-agent-new-room'); + callbacks.remove('livechat.onMaxNumberSimultaneousChatsReached', 'livechat-on-max-number-simultaneous-chats-reached'); + callbacks.remove('livechat.afterTakeInquiry', 'livechat-save-default-agent-after-take-inquiry'); + return; + } + + callbacks.add('livechat.checkDefaultAgentOnNewRoom', checkDefaultAgentOnNewRoom, callbacks.priority.MEDIUM, 'livechat-check-default-agent-new-room'); + callbacks.add('livechat.onMaxNumberSimultaneousChatsReached', onMaxNumberSimultaneousChatsReached, callbacks.priority.MEDIUM, 'livechat-on-max-number-simultaneous-chats-reached'); + callbacks.add('livechat.afterTakeInquiry', afterTakeInquiry, callbacks.priority.MEDIUM, 'livechat-save-default-agent-after-take-inquiry'); +}); diff --git a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js b/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js deleted file mode 100644 index 2dc7750e847f..000000000000 --- a/ee/app/livechat-enterprise/server/hooks/onMaxNumberSimultaneousChatsReached.js +++ /dev/null @@ -1,32 +0,0 @@ -import { callbacks } from '../../../../../app/callbacks/server'; -import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; -import { settings } from '../../../../../app/settings/server'; -import { LivechatInquiry } from '../../../../../app/models/server'; -import { checkWaitingQueue } from '../lib/Helper'; - -callbacks.add('livechat.onMaxNumberSimultaneousChatsReached', (inquiry, agent) => { - if (!inquiry || !inquiry.defaultAgent) { - return inquiry; - } - - if (!RoutingManager.getConfig().autoAssignAgent) { - return inquiry; - } - - if (!settings.get('Livechat_last_chatted_agent_routing')) { - return inquiry; - } - - const { _id, defaultAgent, department } = inquiry; - - LivechatInquiry.removeDefaultAgentById(_id); - - const { _id: defaultAgentId } = defaultAgent; - const { agentId } = agent; - - if (defaultAgentId === agentId) { - checkWaitingQueue(department); - } - - return LivechatInquiry.findOneById(_id); -}, callbacks.priority.MEDIUM, 'livechat-on-max-number-simultaneous-chats-reached'); diff --git a/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js b/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js deleted file mode 100644 index cfadb39ac3f3..000000000000 --- a/ee/app/livechat-enterprise/server/hooks/saveDefaultAgentAfterTakeInquiry.js +++ /dev/null @@ -1,28 +0,0 @@ -import { callbacks } from '../../../../../app/callbacks/server'; -import { settings } from '../../../../../app/settings/server'; -import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; -import { LivechatVisitors } from '../../../../../app/models/server'; - -callbacks.add('livechat.afterTakeInquiry', (inquiry, agent) => { - if (!inquiry || !agent) { - return inquiry; - } - - if (!RoutingManager.getConfig().autoAssignAgent) { - return inquiry; - } - - if (!settings.get('Livechat_last_chatted_agent_routing')) { - return inquiry; - } - - const { v: { token } = {} } = inquiry; - if (!token) { - return inquiry; - } - - const { agentId: _id, username } = agent; - LivechatVisitors.updateLastAgentByToken(token, { _id, username, ts: new Date() }); - - return inquiry; -}, callbacks.priority.MEDIUM, 'livechat-save-default-agent-after-take-inquiry'); diff --git a/ee/app/livechat-enterprise/server/index.js b/ee/app/livechat-enterprise/server/index.js index ba2b34e73b92..f18d76223f40 100644 --- a/ee/app/livechat-enterprise/server/index.js +++ b/ee/app/livechat-enterprise/server/index.js @@ -27,14 +27,12 @@ import './hooks/beforeNewInquiry'; import './hooks/beforeNewRoom'; import './hooks/beforeRoutingChat'; import './hooks/checkAgentBeforeTakeInquiry'; -import './hooks/checkDefaultAgentOnNewRoom'; +import './hooks/handleLastChattedAgentPreferredEvents'; import './hooks/onCheckRoomParamsApi'; import './hooks/onLoadConfigApi'; -import './hooks/onMaxNumberSimultaneousChatsReached'; import './hooks/onSetUserStatusLivechat'; import './hooks/onCloseLivechat'; import './hooks/onSaveVisitorInfo'; -import './hooks/saveDefaultAgentAfterTakeInquiry'; import './lib/routing/LoadBalancing'; import { onLicense } from '../../license/server'; From 51d0e87d985af1c03dc43fff6199bade70a89d48 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 20 May 2020 23:36:54 -0300 Subject: [PATCH 10/10] Normalize agent payload before saving. --- .../handleLastChattedAgentPreferredEvents.js | 16 ++++++++++++---- ee/app/livechat-enterprise/server/lib/Helper.js | 11 +---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js b/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js index 87aa2850ec2a..9bdc2bc8de66 100644 --- a/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js +++ b/ee/app/livechat-enterprise/server/hooks/handleLastChattedAgentPreferredEvents.js @@ -4,6 +4,15 @@ import { settings } from '../../../../../app/settings/server'; import { LivechatRooms, LivechatInquiry, LivechatVisitors, Users } from '../../../../../app/models/server'; import { checkWaitingQueue } from '../lib/Helper'; +const normalizeDefaultAgent = (agent) => { + if (!agent) { + return; + } + + const { _id: agentId, username } = agent; + return { agentId, username }; +}; + const checkDefaultAgentOnNewRoom = (defaultAgent, defaultGuest) => { if (defaultAgent || !defaultGuest) { return defaultAgent; @@ -17,7 +26,7 @@ const checkDefaultAgentOnNewRoom = (defaultAgent, defaultGuest) => { const guest = LivechatVisitors.findOneById(guestId, { fields: { lastAgent: 1, token: 1 } }); const { lastAgent: { username: usernameByVisitor } = {}, token } = guest; - const lastGuestAgent = usernameByVisitor && Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } }); + const lastGuestAgent = usernameByVisitor && normalizeDefaultAgent(Users.findOneOnlineAgentByUsername(usernameByVisitor, { fields: { _id: 1, username: 1 } })); if (lastGuestAgent) { return lastGuestAgent; } @@ -28,7 +37,7 @@ const checkDefaultAgentOnNewRoom = (defaultAgent, defaultGuest) => { } const { servedBy: { username: usernameByRoom } } = room; - const lastRoomAgent = Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } }); + const lastRoomAgent = normalizeDefaultAgent(Users.findOneOnlineAgentByUsername(usernameByRoom, { fields: { _id: 1, username: 1 } })); return lastRoomAgent || defaultAgent; }; @@ -69,8 +78,7 @@ const afterTakeInquiry = (inquiry, agent) => { return inquiry; } - const { agentId: _id, username } = agent; - LivechatVisitors.updateLastAgentByToken(token, { _id, username, ts: new Date() }); + LivechatVisitors.updateLastAgentByToken(token, { ...agent, ts: new Date() }); return inquiry; }; diff --git a/ee/app/livechat-enterprise/server/lib/Helper.js b/ee/app/livechat-enterprise/server/lib/Helper.js index 02df14fd4199..dd3318c8e678 100644 --- a/ee/app/livechat-enterprise/server/lib/Helper.js +++ b/ee/app/livechat-enterprise/server/lib/Helper.js @@ -94,15 +94,6 @@ export const dispatchWaitingQueueStatus = async (department) => { }); }; -const normalizeDefaultAgent = (agent) => { - if (!agent) { - return; - } - - const { _id: agentId, username } = agent; - return { agentId, username }; -}; - const processWaitingQueue = async (department) => { const inquiry = LivechatInquiry.getNextInquiryQueued(department); if (!inquiry) { @@ -110,7 +101,7 @@ const processWaitingQueue = async (department) => { } const { defaultAgent } = inquiry; - const room = await RoutingManager.delegateInquiry(inquiry, normalizeDefaultAgent(defaultAgent)); + const room = await RoutingManager.delegateInquiry(inquiry, defaultAgent); const propagateAgentDelegated = Meteor.bindEnvironment((rid, agentId) => { dispatchAgentDelegated(rid, agentId);