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');