From 2b5004031a0555638bbf2822deccab3ecae61dc3 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Fri, 14 May 2021 20:47:16 +0530 Subject: [PATCH 01/11] [EE] Fix Forwarding Department not working with Waiting queue feature --- app/livechat/server/lib/Helper.js | 2 +- app/livechat/server/lib/RoutingManager.js | 4 +- .../server/hooks/onAgentAssignmentFailed.ts | 42 ++++++++++++++----- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index f7a321a25e95..b45a83a26c4d 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -378,7 +378,7 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { // Fake the department to forward the inquiry - Case the forward process does not success // the inquiry will stay in the same original department inquiry.department = departmentId; - const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent); + const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { clientAction: false, forwardRoomToDepartment: oldDepartmentId }); if (!roomTaken) { return false; } diff --git a/app/livechat/server/lib/RoutingManager.js b/app/livechat/server/lib/RoutingManager.js index 9f147539d463..eca7367ca79e 100644 --- a/app/livechat/server/lib/RoutingManager.js +++ b/app/livechat/server/lib/RoutingManager.js @@ -43,7 +43,7 @@ export const RoutingManager = { return this.getMethod().getNextAgent(department, ignoreAgentId); }, - async delegateInquiry(inquiry, agent) { + async delegateInquiry(inquiry, agent, options = {}) { const { department, rid } = inquiry; if (!agent || (agent.username && !Users.findOneOnlineAgentByUsername(agent.username) && !allowAgentSkipQueue(agent))) { agent = await this.getNextAgent(department); @@ -53,7 +53,7 @@ export const RoutingManager = { return LivechatRooms.findOneById(rid); } - return this.takeInquiry(inquiry, agent); + return this.takeInquiry(inquiry, agent, options); }, assignAgent(inquiry, agent) { diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index b8592fff228d..82f807ebbf30 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -1,23 +1,45 @@ import { callbacks } from '../../../../../app/callbacks/server'; import { LivechatInquiry, Subscriptions, LivechatRooms } from '../../../../../app/models/server'; import { queueInquiry } from '../../../../../app/livechat/server/lib/QueueManager'; +import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; -const handleOnAgentAssignmentFailed = async ({ inquiry, room }: { inquiry: any; room: any }): Promise => { - if (!inquiry || !room || !room.onHold) { +const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardRoomToDepartment?: string; clienAction?: boolean} }): Promise => { + if (!inquiry || !room) { return; } - const { _id: roomId, servedBy } = room; + if (room.onHold) { + const { _id: roomId, servedBy } = room; - const { _id: inquiryId } = inquiry; - LivechatInquiry.readyInquiry(inquiryId); - LivechatInquiry.removeDefaultAgentById(inquiryId); - LivechatRooms.removeAgentByRoomId(roomId); - if (servedBy?._id) { - Subscriptions.removeByRoomIdAndUserId(roomId, servedBy._id); + const { _id: inquiryId } = inquiry; + LivechatInquiry.readyInquiry(inquiryId); + LivechatInquiry.removeDefaultAgentById(inquiryId); + LivechatRooms.removeAgentByRoomId(roomId); + if (servedBy?._id) { + Subscriptions.removeByRoomIdAndUserId(roomId, servedBy._id); + } + + const newInquiry = LivechatInquiry.findOneById(inquiryId); + + await queueInquiry(room, newInquiry); + + return; + } + + const { forwardRoomToDepartment: oldDepartmentId } = options; + const { department: newDepartmentId } = inquiry; + + if (!newDepartmentId || !oldDepartmentId || newDepartmentId === oldDepartmentId) { + return; } - const newInquiry = LivechatInquiry.findOneById(inquiryId); + // Undo the FAKE Department we did before RoutingManager.delegateInquiry() + inquiry.department = oldDepartmentId; + RoutingManager.unassignAgent(inquiry, newDepartmentId); + + LivechatInquiry.readyInquiry(inquiry._id); + + const newInquiry = LivechatInquiry.findOneById(inquiry._id); await queueInquiry(room, newInquiry); }; From d9fe3e38a579d3ba589f9b9e1d353d4ffcfc4596 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Fri, 14 May 2021 21:24:22 +0530 Subject: [PATCH 02/11] add waiting queue feature enabled check --- .../server/hooks/onAgentAssignmentFailed.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index 82f807ebbf30..3505445fe6bd 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -2,6 +2,7 @@ import { callbacks } from '../../../../../app/callbacks/server'; import { LivechatInquiry, Subscriptions, LivechatRooms } from '../../../../../app/models/server'; import { queueInquiry } from '../../../../../app/livechat/server/lib/QueueManager'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; +import { settings } from '../../../../../app/settings/server'; const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardRoomToDepartment?: string; clienAction?: boolean} }): Promise => { if (!inquiry || !room) { @@ -26,6 +27,10 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui return; } + if (!settings.get('Livechat_waiting_queue')) { + return; + } + const { forwardRoomToDepartment: oldDepartmentId } = options; const { department: newDepartmentId } = inquiry; From 1b5c9737085fe8dbc21ede1d2b39eefab5585729 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Fri, 14 May 2021 21:56:21 +0530 Subject: [PATCH 03/11] Refactor --- app/livechat/server/lib/Helper.js | 2 +- .../server/hooks/onAgentAssignmentFailed.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index b45a83a26c4d..de8750483f00 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -378,7 +378,7 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { // Fake the department to forward the inquiry - Case the forward process does not success // the inquiry will stay in the same original department inquiry.department = departmentId; - const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { clientAction: false, forwardRoomToDepartment: oldDepartmentId }); + const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { clientAction: false, forwardRoomOldDepartment: oldDepartmentId }); if (!roomTaken) { return false; } diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index 3505445fe6bd..1bfad342ee35 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -4,7 +4,7 @@ import { queueInquiry } from '../../../../../app/livechat/server/lib/QueueManage import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { settings } from '../../../../../app/settings/server'; -const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardRoomToDepartment?: string; clienAction?: boolean} }): Promise => { +const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardRoomOldDepartment?: string; clienAction?: boolean} }): Promise => { if (!inquiry || !room) { return; } @@ -31,7 +31,7 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui return; } - const { forwardRoomToDepartment: oldDepartmentId } = options; + const { forwardRoomOldDepartment: oldDepartmentId } = options; const { department: newDepartmentId } = inquiry; if (!newDepartmentId || !oldDepartmentId || newDepartmentId === oldDepartmentId) { From b4b3c3da9e5affc80a33ee6c70cc1445f2494c35 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Sat, 15 May 2021 22:40:39 +0530 Subject: [PATCH 04/11] Fix forwarding of agents not working --- .../client/views/app/tabbar/visitorForward.js | 1 + app/livechat/server/lib/Helper.js | 12 +++++++----- app/livechat/server/methods/transfer.js | 1 + .../Header/Omnichannel/QuickActions/QuickActions.tsx | 2 ++ .../server/hooks/checkAgentBeforeTakeInquiry.js | 2 +- .../server/hooks/onAgentAssignmentFailed.ts | 11 +++++++++-- 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/livechat/client/views/app/tabbar/visitorForward.js b/app/livechat/client/views/app/tabbar/visitorForward.js index 84860188cf99..871f6448f31a 100644 --- a/app/livechat/client/views/app/tabbar/visitorForward.js +++ b/app/livechat/client/views/app/tabbar/visitorForward.js @@ -111,6 +111,7 @@ Template.visitorForward.events({ const transferData = { roomId: instance.room.get()._id, comment: event.target.comment.value, + clientAction: true, }; const [user] = instance.selectedAgents.get(); diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index de8750483f00..c61c6c9f8eab 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -273,7 +273,7 @@ export const forwardRoomToAgent = async (room, transferData) => { return false; } - const { userId: agentId } = transferData; + const { userId: agentId, clientAction } = transferData; const user = Users.findOneOnlineAgentById(agentId); if (!user) { throw new Meteor.Error('error-user-is-offline', 'User is offline', { function: 'forwardRoomToAgent' }); @@ -291,9 +291,11 @@ export const forwardRoomToAgent = async (room, transferData) => { const { username } = user; const agent = { agentId, username }; - // There are some Enterprise features that may interrupt the fowarding process + // Remove department from inquiry to make sure the routing algorithm treat this as forwarding to agent and not as forwarding to department + inquiry.department = undefined; + // There are some Enterprise features that may interrupt the forwarding process // Due to that we need to check whether the agent has been changed or not - const roomTaken = await RoutingManager.takeInquiry(inquiry, agent); + const roomTaken = await RoutingManager.takeInquiry(inquiry, agent, { ...clientAction && { clientAction } }); if (!roomTaken) { return false; } @@ -356,7 +358,7 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { throw new Meteor.Error('error-forwarding-chat-same-department', 'The selected department and the current room department are the same', { function: 'forwardRoomToDepartment' }); } - const { userId: agentId } = transferData; + const { userId: agentId, clientAction } = transferData; if (agentId) { let user = Users.findOneOnlineAgentById(agentId); if (!user) { @@ -378,7 +380,7 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { // Fake the department to forward the inquiry - Case the forward process does not success // the inquiry will stay in the same original department inquiry.department = departmentId; - const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { clientAction: false, forwardRoomOldDepartment: oldDepartmentId }); + const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { forwardingToDepartment: { oldDepartmentId, transferData }, ...clientAction && { clientAction } }); if (!roomTaken) { return false; } diff --git a/app/livechat/server/methods/transfer.js b/app/livechat/server/methods/transfer.js index 241a031761ae..7f99c8f08875 100644 --- a/app/livechat/server/methods/transfer.js +++ b/app/livechat/server/methods/transfer.js @@ -17,6 +17,7 @@ Meteor.methods({ userId: Match.Optional(String), departmentId: Match.Optional(String), comment: Match.Optional(String), + clientAction: Match.Optional(Boolean), }); const room = LivechatRooms.findOneById(transferData.roomId); diff --git a/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx b/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx index 810c1b78858e..9e08e37f6bfe 100644 --- a/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx +++ b/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx @@ -137,12 +137,14 @@ const QuickActions: FC = ({ room, className }) => { } const transferData: { roomId: string; + clientAction: boolean; comment?: string; departmentId?: string; userId?: string; } = { roomId: rid, comment, + clientAction: true, }; if (departmentId) { diff --git a/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js b/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js index 0f772543cf63..b7fe80a22142 100644 --- a/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js +++ b/ee/app/livechat-enterprise/server/hooks/checkAgentBeforeTakeInquiry.js @@ -35,7 +35,7 @@ callbacks.add('livechat.checkAgentBeforeTakeInquiry', async ({ agent, inquiry, o const { queueInfo: { chats = 0 } = {} } = user; if (maxNumberSimultaneousChat <= chats) { callbacks.run('livechat.onMaxNumberSimultaneousChatsReached', inquiry); - if (options.clientAction) { + if (options.clientAction && !options.forwardingToDepartment) { throw new Meteor.Error('error-max-number-simultaneous-chats-reached', 'Not allowed'); } diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index 1bfad342ee35..090002bdf28b 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -3,8 +3,9 @@ import { LivechatInquiry, Subscriptions, LivechatRooms } from '../../../../../ap import { queueInquiry } from '../../../../../app/livechat/server/lib/QueueManager'; import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { settings } from '../../../../../app/settings/server'; +import { Livechat } from '../../../../../app/livechat/server/lib/Livechat'; -const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardRoomOldDepartment?: string; clienAction?: boolean} }): Promise => { +const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardingToDepartment?: { oldDepartmentId: string; transferData: any }; clienAction?: boolean} }): Promise => { if (!inquiry || !room) { return; } @@ -31,7 +32,11 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui return; } - const { forwardRoomOldDepartment: oldDepartmentId } = options; + const { forwardingToDepartment: { oldDepartmentId, transferData } = {}, forwardingToDepartment } = options; + if (!forwardingToDepartment) { + return; + } + const { department: newDepartmentId } = inquiry; if (!newDepartmentId || !oldDepartmentId || newDepartmentId === oldDepartmentId) { @@ -47,6 +52,8 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui const newInquiry = LivechatInquiry.findOneById(inquiry._id); await queueInquiry(room, newInquiry); + + Livechat.saveTransferHistory(room, transferData); }; callbacks.add('livechat.onAgentAssignmentFailed', handleOnAgentAssignmentFailed, callbacks.priority.HIGH, 'livechat-agent-assignment-failed'); From 0c6f7ec3b73f998c45df24b7b992745e830404d7 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Mon, 17 May 2021 14:15:45 +0530 Subject: [PATCH 05/11] Apply suggestions from code review Co-authored-by: Renato Becker --- .../livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index 090002bdf28b..2f6f4a90ac13 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -5,7 +5,7 @@ import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingMa import { settings } from '../../../../../app/settings/server'; import { Livechat } from '../../../../../app/livechat/server/lib/Livechat'; -const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardingToDepartment?: { oldDepartmentId: string; transferData: any }; clienAction?: boolean} }): Promise => { +const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardingToDepartment?: { oldDepartmentId: string; transferData: any }; clientAction?: boolean} }): Promise => { if (!inquiry || !room) { return; } From d750c5949d2cf1d738dd21289e9396e9aacffa1a Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Mon, 17 May 2021 16:08:51 +0530 Subject: [PATCH 06/11] Handle transfer api response properly on client + refactor --- app/livechat/server/lib/Helper.js | 13 ++++++++++--- app/livechat/server/lib/RoutingManager.js | 6 ++++-- .../Omnichannel/QuickActions/QuickActions.tsx | 7 +++++-- .../server/hooks/onAgentAssignmentFailed.ts | 17 +++-------------- packages/rocketchat-i18n/i18n/en.i18n.json | 4 +++- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index c61c6c9f8eab..8e452c0ca4e0 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -13,6 +13,7 @@ import { Apps, AppEvents } from '../../../apps/server'; import notifications from '../../../notifications/server/lib/Notifications'; import { sendNotification } from '../../../lib/server'; import { sendMessage } from '../../../lib/server/functions/sendMessage'; +import { queueInquiry } from './QueueManager'; export const allowAgentSkipQueue = (agent) => { check(agent, Match.ObjectIncluding({ @@ -385,8 +386,8 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { return false; } - const { servedBy } = roomTaken; - if (oldServedBy && servedBy && oldServedBy._id === servedBy._id) { + const { servedBy, chatQueued } = roomTaken; + if (!chatQueued && oldServedBy && servedBy && oldServedBy._id === servedBy._id) { return false; } @@ -394,12 +395,18 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { if (oldServedBy) { removeAgentFromSubscription(rid, oldServedBy); } - if (servedBy) { + if (!chatQueued && servedBy) { Messages.createUserJoinWithRoomIdAndUser(rid, servedBy); } updateChatDepartment({ rid, newDepartmentId: departmentId, oldDepartmentId }); + if (chatQueued) { + LivechatInquiry.readyInquiry(inquiry._id); + const newInquiry = LivechatInquiry.findOneById(inquiry._id); + await queueInquiry(room, newInquiry); + } + const { token } = guest; Livechat.setDepartmentForGuest({ token, department: departmentId }); diff --git a/app/livechat/server/lib/RoutingManager.js b/app/livechat/server/lib/RoutingManager.js index eca7367ca79e..224fa6dbc4ea 100644 --- a/app/livechat/server/lib/RoutingManager.js +++ b/app/livechat/server/lib/RoutingManager.js @@ -47,6 +47,9 @@ export const RoutingManager = { const { department, rid } = inquiry; if (!agent || (agent.username && !Users.findOneOnlineAgentByUsername(agent.username) && !allowAgentSkipQueue(agent))) { agent = await this.getNextAgent(department); + if (!agent && options.forwardingToDepartment) { + throw new Meteor.Error('error-no-agents-online-in-department', 'No agents online in the department', { function: 'forwardRoomToDepartment' }); + } } if (!agent) { @@ -134,8 +137,7 @@ export const RoutingManager = { agent = await callbacks.run('livechat.checkAgentBeforeTakeInquiry', { agent, inquiry, options }); if (!agent) { - await callbacks.run('livechat.onAgentAssignmentFailed', { inquiry, room, options }); - return null; + return callbacks.run('livechat.onAgentAssignmentFailed', { inquiry, room, options }); } if (room.onHold) { diff --git a/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx b/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx index b1562498fb32..f7f5f0e9e331 100644 --- a/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx +++ b/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx @@ -155,10 +155,13 @@ const QuickActions: FC = ({ room, className }) => { } try { - await forwardChat(transferData); - closeModal(); + const result = await forwardChat(transferData); + if (!result) { + throw new Error(t('error-forwarding-chat')); + } toastr.success(t('Transferred')); FlowRouter.go('/'); + closeModal(); } catch (error) { handleError(error); } diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index 2f6f4a90ac13..2ad504e40b3d 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -1,9 +1,7 @@ import { callbacks } from '../../../../../app/callbacks/server'; import { LivechatInquiry, Subscriptions, LivechatRooms } from '../../../../../app/models/server'; import { queueInquiry } from '../../../../../app/livechat/server/lib/QueueManager'; -import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { settings } from '../../../../../app/settings/server'; -import { Livechat } from '../../../../../app/livechat/server/lib/Livechat'; const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inquiry: any; room: any; options: { forwardingToDepartment?: { oldDepartmentId: string; transferData: any }; clientAction?: boolean} }): Promise => { if (!inquiry || !room) { @@ -32,7 +30,7 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui return; } - const { forwardingToDepartment: { oldDepartmentId, transferData } = {}, forwardingToDepartment } = options; + const { forwardingToDepartment: { oldDepartmentId } = {}, forwardingToDepartment } = options; if (!forwardingToDepartment) { return; } @@ -43,17 +41,8 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui return; } - // Undo the FAKE Department we did before RoutingManager.delegateInquiry() - inquiry.department = oldDepartmentId; - RoutingManager.unassignAgent(inquiry, newDepartmentId); - - LivechatInquiry.readyInquiry(inquiry._id); - - const newInquiry = LivechatInquiry.findOneById(inquiry._id); - - await queueInquiry(room, newInquiry); - - Livechat.saveTransferHistory(room, transferData); + room.chatQueued = true; + return room; }; callbacks.add('livechat.onAgentAssignmentFailed', handleOnAgentAssignmentFailed, callbacks.priority.HIGH, 'livechat-agent-assignment-failed'); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index b4d179a68e2e..ff6289cb56b4 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1612,6 +1612,7 @@ "error-essential-app-disabled": "Error: a Rocket.Chat App that is essential for this is disabled. Please contact your administrator", "error-field-unavailable": "__field__ is already in use :(", "error-file-too-large": "File is too large", + "error-forwarding-chat": "Something went wrong while forwarding the chat, Please try again later.", "error-forwarding-chat-same-department": "The selected department and the current room department are the same", "error-forwarding-department-target-not-allowed": "The forwarding to the target department is not allowed.", "error-guests-cant-have-other-roles": "Guest users can't have any other role.", @@ -1672,6 +1673,7 @@ "error-message-size-exceeded": "Message size exceeds Message_MaxAllowedSize", "error-missing-unsubscribe-link": "You must provide the [unsubscribe] link.", "error-no-tokens-for-this-user": "There are no tokens for this user", + "error-no-agents-online-in-department": "No agents online in the department", "error-no-message-for-unread": "There are no messages to mark unread", "error-not-allowed": "Not allowed", "error-not-authorized": "Not authorized", @@ -4501,4 +4503,4 @@ "Your_temporary_password_is_password": "Your temporary password is [password].", "Your_TOTP_has_been_reset": "Your Two Factor TOTP has been reset.", "Your_workspace_is_ready": "Your workspace is ready to use 🎉" -} \ No newline at end of file +} From 53eec95407fdbc67608b5c3887db3765c3abca72 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Mon, 17 May 2021 16:10:04 +0530 Subject: [PATCH 07/11] Avoid passing unnecessary params --- app/livechat/server/lib/Helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index 8e452c0ca4e0..9341a3acb732 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -381,7 +381,7 @@ export const forwardRoomToDepartment = async (room, guest, transferData) => { // Fake the department to forward the inquiry - Case the forward process does not success // the inquiry will stay in the same original department inquiry.department = departmentId; - const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { forwardingToDepartment: { oldDepartmentId, transferData }, ...clientAction && { clientAction } }); + const roomTaken = await RoutingManager.delegateInquiry(inquiry, agent, { forwardingToDepartment: { oldDepartmentId }, ...clientAction && { clientAction } }); if (!roomTaken) { return false; } From deccab97333eec553e84dff52bc7527804c9fd34 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Mon, 17 May 2021 17:42:59 -0300 Subject: [PATCH 08/11] Remove throw error. --- app/livechat/server/lib/RoutingManager.js | 3 --- packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/livechat/server/lib/RoutingManager.js b/app/livechat/server/lib/RoutingManager.js index 224fa6dbc4ea..7de0a4ce0a74 100644 --- a/app/livechat/server/lib/RoutingManager.js +++ b/app/livechat/server/lib/RoutingManager.js @@ -47,9 +47,6 @@ export const RoutingManager = { const { department, rid } = inquiry; if (!agent || (agent.username && !Users.findOneOnlineAgentByUsername(agent.username) && !allowAgentSkipQueue(agent))) { agent = await this.getNextAgent(department); - if (!agent && options.forwardingToDepartment) { - throw new Meteor.Error('error-no-agents-online-in-department', 'No agents online in the department', { function: 'forwardRoomToDepartment' }); - } } if (!agent) { diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index 6c5b220357b4..342cfb55b26b 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -1424,6 +1424,7 @@ "error-message-editing-blocked": "Edição de mensagens está bloqueada", "error-message-size-exceeded": "O tamanho da mensagem excede Message_MaxAllowedSize", "error-missing-unsubscribe-link": "Você deve fornecer o link para desinscrever-se: [unsubscribe].", + "error-no-agents-online-in-department": "Nenhum agente online no departamento", "error-no-tokens-for-this-user": "Não existem tokens para este usuário", "error-no-message-for-unread": "Não há mensagens para serem marcadas como não lidas", "error-not-allowed": "Não permitido", @@ -3661,4 +3662,4 @@ "Your_question": "A sua pergunta", "Your_server_link": "O link do seu servidor", "Your_workspace_is_ready": "O seu espaço de trabalho está pronto a usar 🎉" -} \ No newline at end of file +} From 85b015db474068fc9b3bbfb96713bace939a5c5f Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Mon, 17 May 2021 17:52:07 -0300 Subject: [PATCH 09/11] Improve throw message logic. --- .../room/Header/Omnichannel/QuickActions/QuickActions.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx b/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx index f7f5f0e9e331..9cea78ed6a08 100644 --- a/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx +++ b/client/views/room/Header/Omnichannel/QuickActions/QuickActions.tsx @@ -157,7 +157,9 @@ const QuickActions: FC = ({ room, className }) => { try { const result = await forwardChat(transferData); if (!result) { - throw new Error(t('error-forwarding-chat')); + throw new Error( + departmentId ? t('error-no-agents-online-in-department') : t('error-forwarding-chat'), + ); } toastr.success(t('Transferred')); FlowRouter.go('/'); From bf90764a96326b58cb4d660dc4354f099a917278 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Mon, 17 May 2021 19:16:38 -0300 Subject: [PATCH 10/11] Fix on-hold queue. Methods have been removed in another PR. --- ee/app/livechat-enterprise/server/lib/LivechatEnterprise.js | 4 +++- ee/app/livechat-enterprise/server/methods/resumeOnHold.ts | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.js b/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.js index 8c11c466011a..11d276937226 100644 --- a/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.js +++ b/ee/app/livechat-enterprise/server/lib/LivechatEnterprise.js @@ -5,7 +5,7 @@ import { Users } from '../../../../../app/models'; import { LivechatInquiry, OmnichannelQueue } from '../../../../../app/models/server/raw'; import LivechatUnit from '../../../models/server/models/LivechatUnit'; import LivechatTag from '../../../models/server/models/LivechatTag'; -import { LivechatRooms, Messages } from '../../../../../app/models/server'; +import { LivechatRooms, Subscriptions, Messages } from '../../../../../app/models/server'; import LivechatPriority from '../../../models/server/models/LivechatPriority'; import { addUserRoles, removeUserFromRoles } from '../../../../../app/authorization/server'; import { processWaitingQueue, removePriorityFromRooms, updateInquiryQueuePriority, updatePriorityInquiries, updateRoomPriorityHistory } from './Helper'; @@ -173,6 +173,7 @@ export const LivechatEnterprise = { return false; } LivechatRooms.setOnHold(roomId); + Subscriptions.setOnHold(roomId); Messages.createOnHoldHistoryWithRoomIdMessageAndUser(roomId, comment, onHoldBy); Meteor.defer(() => { @@ -190,6 +191,7 @@ export const LivechatEnterprise = { await AutoCloseOnHoldScheduler.unscheduleRoom(roomId); LivechatRooms.unsetAllOnHoldFieldsByRoomId(roomId); + Subscriptions.unsetOnHold(roomId); }, }; diff --git a/ee/app/livechat-enterprise/server/methods/resumeOnHold.ts b/ee/app/livechat-enterprise/server/methods/resumeOnHold.ts index 5caae4ae074c..f0ed7c7271e0 100644 --- a/ee/app/livechat-enterprise/server/methods/resumeOnHold.ts +++ b/ee/app/livechat-enterprise/server/methods/resumeOnHold.ts @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; import { LivechatRooms, LivechatInquiry, Messages, Users, LivechatVisitors } from '../../../../../app/models/server'; -import { LivechatEnterprise } from '../lib/LivechatEnterprise'; +import { RoutingManager } from '../../../../../app/livechat/server/lib/RoutingManager'; import { callbacks } from '../../../../../app/callbacks/server'; const resolveOnHoldCommentInfo = (options: { clientAction: boolean }, room: any, onHoldChatResumedBy: any): string => { @@ -38,7 +38,8 @@ Meteor.methods({ throw new Meteor.Error('inquiry-not-found', 'Error! No inquiry found for this room', { method: 'livechat:resumeOnHold' }); } - LivechatEnterprise.releaseOnHoldChat(room); + const { servedBy: { _id: agentId, username } } = room; + await RoutingManager.takeInquiry(inquiry, { agentId, username }, options); const onHoldChatResumedBy = options.clientAction ? Meteor.user() : Users.findOneById('rocket.cat'); From d49c8fe47802587441d40f57a8db8c8ac162cb71 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Mon, 17 May 2021 19:31:47 -0300 Subject: [PATCH 11/11] Remove all subscription from a chat placed on-hold. --- .../server/hooks/onAgentAssignmentFailed.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts index 2ad504e40b3d..f2a3e9c44d88 100644 --- a/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts +++ b/ee/app/livechat-enterprise/server/hooks/onAgentAssignmentFailed.ts @@ -9,16 +9,13 @@ const handleOnAgentAssignmentFailed = async ({ inquiry, room, options }: { inqui } if (room.onHold) { - const { _id: roomId, servedBy } = room; + const { _id: roomId } = room; const { _id: inquiryId } = inquiry; LivechatInquiry.readyInquiry(inquiryId); LivechatInquiry.removeDefaultAgentById(inquiryId); LivechatRooms.removeAgentByRoomId(roomId); - if (servedBy?._id) { - Subscriptions.removeByRoomIdAndUserId(roomId, servedBy._id); - } - + Subscriptions.removeByRoomId(roomId); const newInquiry = LivechatInquiry.findOneById(inquiryId); await queueInquiry(room, newInquiry);