Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fluffy-cougars-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixes a behavior when transferring a room to another department that was not considering the `waiting queue` setting and attempted to route the chat to an agent instead of leaving it on the department's queue
19 changes: 17 additions & 2 deletions apps/meteor/app/livechat/server/lib/Helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,12 +635,27 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi
},
});

// Cases:
// 1. Routing is manual
// 2. Server is out of macs
// 3. Department allows to forward when offline and department is offline
// 4. Department is online && waiting queue is enabled
const onlineAgents = await checkOnlineAgents(departmentId);
const isWaitingQueueEnabled = settings.get('Livechat_waiting_queue');
if (
!RoutingManager.getConfig()?.autoAssignAgent ||
!(await Omnichannel.isWithinMACLimit(room)) ||
(department?.allowReceiveForwardOffline && !(await checkOnlineAgents(departmentId)))
(department?.allowReceiveForwardOffline && !onlineAgents) ||
(isWaitingQueueEnabled && onlineAgents)
) {
logger.debug(`Room ${room._id} will be on department queue`);
logger.debug({
msg: 'Room will be on department queue',
roomId: room._id,
departmentId,
departmentAllowOffline: department?.allowReceiveForwardOffline,
areAgentsOnline: onlineAgents,
isWaitingQueueEnabled,
});
await saveTransferHistory(room, transferData);
return RoutingManager.unassignAgent(inquiry, departmentId, true);
}
Expand Down
211 changes: 211 additions & 0 deletions apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,178 @@ describe('LIVECHAT - rooms', () => {
},
);

(IS_EE ? it : it.skip)(
'when manager forwards a chat that hasnt been assigned to a user to another department with no online agents, chat should end ready in department (not queued)',
async () => {
await updateSetting('Livechat_accept_chats_with_no_agents', true);
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
const { department: initialDepartment } = await createDepartmentWithAnOfflineAgent({});
const { department: forwardToOfflineDepartment } = await createDepartmentWithAnOfflineAgent({});

const newVisitor = await createVisitor(initialDepartment._id);
const newRoom = await createLivechatRoom(newVisitor.token);

const manager = await createUser();
const managerCredentials = await login(manager.username, password);
await createManager(manager.username);

await request.post(api('livechat/room.forward')).set(managerCredentials).send({
roomId: newRoom._id,
departmentId: forwardToOfflineDepartment._id,
clientAction: true,
comment: 'test comment',
});

const inquiry = await fetchInquiry(newRoom._id);

// Inquiry status doesn't change, it was ready when created, it keeps ready after forwarding as no assignment was done
expect(inquiry.status).to.equal('ready');
expect(inquiry.department).to.equal(forwardToOfflineDepartment._id);

await Promise.all([deleteDepartment(initialDepartment._id), deleteDepartment(forwardToOfflineDepartment._id)]);
},
);

(IS_EE ? it : it.skip)(
'when manager forwards a chat that hasnt been assigned to a user to another department with no online agents when waiting queue is active, chat should end queued in department',
async () => {
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
await updateSetting('Livechat_waiting_queue', true);
const { department: initialDepartment } = await createDepartmentWithAnOfflineAgent({});
const { department: forwardToOfflineDepartment } = await createDepartmentWithAnOfflineAgent({});

const newVisitor = await createVisitor(initialDepartment._id);
const newRoom = await createLivechatRoom(newVisitor.token);

const manager = await createUser();
const managerCredentials = await login(manager.username, password);
await createManager(manager.username);

expect(newRoom.servedBy).to.be.undefined;
await request.post(api('livechat/room.forward')).set(managerCredentials).send({
roomId: newRoom._id,
departmentId: forwardToOfflineDepartment._id,
clientAction: true,
comment: 'test comment',
});

const inquiry = await fetchInquiry(newRoom._id);

expect(inquiry.status).to.equal('queued');
expect(inquiry.department).to.equal(forwardToOfflineDepartment._id);

await Promise.all([
deleteDepartment(initialDepartment._id),
deleteDepartment(forwardToOfflineDepartment._id),
updateSetting('Livechat_waiting_queue', true),
updateSetting('Livechat_accept_chats_with_no_agents', false),
]);
},
);

(IS_EE ? it : it.skip)(
'when manager forward to a department while waiting_queue is active and allowReceiveForwardOffline is true, chat should end in departments queue',
async () => {
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
const { department: initialDepartment } = await createDepartmentWithAnOnlineAgent();
const { department: forwardToOfflineDepartment } = await createDepartmentWithAnAwayAgent({ allowReceiveForwardOffline: true });

const newVisitor = await createVisitor(initialDepartment._id);
const newRoom = await createLivechatRoom(newVisitor.token);

const manager = await createUser();
const managerCredentials = await login(manager.username, password);
await createManager(manager.username);

// Waiting queue enabled after assignement but before transfer, otherwise, chat will fall on previous test case
await updateSetting('Livechat_waiting_queue', true);
await request.post(api('livechat/room.forward')).set(managerCredentials).send({
roomId: newRoom._id,
departmentId: forwardToOfflineDepartment._id,
clientAction: true,
comment: 'test comment',
});

const inquiry = await fetchInquiry(newRoom._id);

expect(inquiry.status).to.equal('queued');
expect(inquiry.department).to.equal(forwardToOfflineDepartment._id);

await Promise.all([
deleteDepartment(initialDepartment._id),
deleteDepartment(forwardToOfflineDepartment._id),
updateSetting('Livechat_waiting_queue', false),
]);
},
);

(IS_EE ? it : it.skip)(
'when manager forward to a department while waiting_queue is active and allowReceiveForwardOffline is false, transfer should fail',
async () => {
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
const { department: initialDepartment } = await createDepartmentWithAnOnlineAgent();
const { department: forwardToOfflineDepartment } = await createDepartmentWithAnAwayAgent({ allowReceiveForwardOffline: false });

const newVisitor = await createVisitor(initialDepartment._id);
const newRoom = await createLivechatRoom(newVisitor.token);

const manager = await createUser();
const managerCredentials = await login(manager.username, password);
await createManager(manager.username);

// Waiting queue enabled after assignement but before transfer, otherwise, chat will fall on previous test case
await updateSetting('Livechat_waiting_queue', true);
const res = await request.post(api('livechat/room.forward')).set(managerCredentials).send({
roomId: newRoom._id,
departmentId: forwardToOfflineDepartment._id,
clientAction: true,
comment: 'test comment',
});

expect(res.status).to.equal(400);
expect(res.body).to.have.property('error', 'error-no-agents-online-in-department');

await Promise.all([
deleteDepartment(initialDepartment._id),
deleteDepartment(forwardToOfflineDepartment._id),
updateSetting('Livechat_waiting_queue', false),
]);
},
);

(IS_EE ? it : it.skip)(
'when manager forward to a department while waiting_queue is disabled and allowReceiveForwardOffline is false, but department is online, transfer should succeed',
async () => {
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
const { department: initialDepartment } = await createDepartmentWithAnOnlineAgent();
const { department: targetDepartment } = await createDepartmentWithAnOnlineAgent();

const newVisitor = await createVisitor(initialDepartment._id);
const newRoom = await createLivechatRoom(newVisitor.token);

const manager = await createUser();
const managerCredentials = await login(manager.username, password);
await createManager(manager.username);

expect(newRoom).to.have.property('servedBy');
const res = await request.post(api('livechat/room.forward')).set(managerCredentials).send({
roomId: newRoom._id,
departmentId: targetDepartment._id,
clientAction: true,
comment: 'test comment',
});

expect(res.status).to.equal(200);

const inquiry = await fetchInquiry(newRoom._id);

expect(inquiry).to.have.property('department', targetDepartment._id);
expect(inquiry).to.have.property('status', 'taken');

await Promise.all([deleteDepartment(initialDepartment._id), deleteDepartment(targetDepartment._id)]);
},
);

(IS_EE ? it : it.skip)(
'when manager forward to online (agent away, accept when agent idle on) department the inquiry should not be set to the queue',
async () => {
Expand Down Expand Up @@ -1285,6 +1457,45 @@ describe('LIVECHAT - rooms', () => {
},
);

(IS_EE ? it : it.skip)(
'when manager forward to a department while waiting_queue is enabled, but department is online, transfer should succeed but it should end queued on target',
async () => {
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
const { department: initialDepartment } = await createDepartmentWithAnOnlineAgent();
const { department: targetDepartment } = await createDepartmentWithAnOnlineAgent();

const newVisitor = await createVisitor(initialDepartment._id);
const newRoom = await createLivechatRoom(newVisitor.token);

const manager = await createUser();
const managerCredentials = await login(manager.username, password);
await createManager(manager.username);

expect(newRoom).to.have.property('servedBy');

await updateSetting('Livechat_waiting_queue', true);
const res = await request.post(api('livechat/room.forward')).set(managerCredentials).send({
roomId: newRoom._id,
departmentId: targetDepartment._id,
clientAction: true,
comment: 'test comment',
});

expect(res.status).to.equal(200);

const inquiry = await fetchInquiry(newRoom._id);

expect(inquiry).to.have.property('department', targetDepartment._id);
expect(inquiry).to.have.property('status', 'queued');

await Promise.all([
deleteDepartment(initialDepartment._id),
deleteDepartment(targetDepartment._id),
updateSetting('Livechat_waiting_queue', false),
]);
},
);

(IS_EE ? it : it.skip)(
'should update inquiry last message when manager forward to offline department and the inquiry returns to queued',
async () => {
Expand Down
Loading