From 722c6f3f029b2bf9cd47bf8b2b4b9bb678fa98a9 Mon Sep 17 00:00:00 2001 From: Murtaza Patrawala <34130764+murtaza98@users.noreply.github.com> Date: Mon, 24 Jul 2023 12:04:36 +0400 Subject: [PATCH] regression: Open default BH not being unlinked when department is connected to a custom BH (#29894) Co-authored-by: Kevin Aleman <11577696+KevLehman@users.noreply.github.com> --- .../server/business-hour/Custom.ts | 54 +++++++++++++++---- .../tests/data/livechat/businessHours.ts | 4 +- .../api/livechat/19-business-hours.ts | 30 +++++++++++ 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/apps/meteor/ee/app/livechat-enterprise/server/business-hour/Custom.ts b/apps/meteor/ee/app/livechat-enterprise/server/business-hour/Custom.ts index 2ed0732463f..ecfa88b0673 100644 --- a/apps/meteor/ee/app/livechat-enterprise/server/business-hour/Custom.ts +++ b/apps/meteor/ee/app/livechat-enterprise/server/business-hour/Custom.ts @@ -5,6 +5,8 @@ import { LivechatDepartment, LivechatDepartmentAgents, Users } from '@rocket.cha import type { IBusinessHourType } from '../../../../../app/livechat/server/business-hour/AbstractBusinessHour'; import { AbstractBusinessHourType } from '../../../../../app/livechat/server/business-hour/AbstractBusinessHour'; import { businessHourManager } from '../../../../../app/livechat/server/business-hour'; +import { bhLogger } from '../lib/logger'; +import { filterBusinessHoursThatMustBeOpened } from '../../../../../app/livechat/server/business-hour/Helper'; type IBusinessHoursExtraProperties = { timezoneName: string; @@ -101,18 +103,50 @@ class CustomBusinessHour extends AbstractBusinessHourType implements IBusinessHo await LivechatDepartment.removeBusinessHourFromDepartmentsByIdsAndBusinessHourId(departmentsToRemove, businessHourId); } - private async removeBHFromPreviouslyConnectedDepartmentAgentsIfRequired(departments: string[]): Promise { - const oldBHIds = await ( - await LivechatDepartment.findInIds(departments, { - projection: { - businessHourId: 1, - }, + private async removeBHFromPreviouslyConnectedDepartmentAgentsIfRequired(departmentIds: string[]): Promise { + // we need to do 2 things here. + // 1st is to check if any of the departments are associated with any BH. If they are, then we need to remove + // that BH from all agents of that department. + // 2nd is to check if any of the departments are not associated with BH, meaning default BH + // is applied. So if default BH is open, then we need to remove it from all agents of that department. + const bhIdsConnectedToDepartment = []; + const departmentsWithoutBH = []; + + const departments = await LivechatDepartment.findInIds(departmentIds, { + projection: { + businessHourId: 1, + }, + }).toArray(); + + for (const dept of departments) { + if (dept?.businessHourId) { + bhIdsConnectedToDepartment.push(dept.businessHourId); + } else { + departmentsWithoutBH.push(dept._id); + } + } + await Users.closeAgentsBusinessHoursByBusinessHourIds(bhIdsConnectedToDepartment); + + // start of step 2 + const defaultBusinessHour = await this.BusinessHourRepository.findOneDefaultBusinessHour(); + if (!defaultBusinessHour) { + bhLogger.error('No default business hour found'); + return; + } + + const isDefaultBHActive = (await filterBusinessHoursThatMustBeOpened([defaultBusinessHour])).length > 0; + if (!isDefaultBHActive) { + bhLogger.debug('Default business hour is not active. No need to remove it from agents'); + return; + } + + const agentsConnectedToDefaultBH = await ( + await LivechatDepartmentAgents.findByDepartmentIds(departmentIds, { + projection: { agentId: 1 }, }).toArray() - ) - .filter((dept) => dept?.businessHourId) - .map((dept) => dept.businessHourId); + ).map((dept) => dept.agentId); - await Users.closeAgentsBusinessHoursByBusinessHourIds(oldBHIds); + await Users.removeBusinessHourByAgentIds(agentsConnectedToDefaultBH, defaultBusinessHour._id); await Users.updateLivechatStatusBasedOnBusinessHours(); } diff --git a/apps/meteor/tests/data/livechat/businessHours.ts b/apps/meteor/tests/data/livechat/businessHours.ts index 8ce1d91a79b..58d8affa3d2 100644 --- a/apps/meteor/tests/data/livechat/businessHours.ts +++ b/apps/meteor/tests/data/livechat/businessHours.ts @@ -16,13 +16,13 @@ export const saveBusinessHour = async (businessHour: ISaveBhApiWorkHour) => { return JSON.parse(body.message); }; -export const createCustomBusinessHour = async (departments: string[]): Promise => { +export const createCustomBusinessHour = async (departments: string[], open = true): Promise => { const name = `business-hour-${Date.now()}`; const businessHour: ISaveBhApiWorkHour = { name, active: true, type: LivechatBusinessHourTypes.CUSTOM, - workHours: getWorkHours(), + workHours: getWorkHours(open), timezoneName: 'Asia/Calcutta', departmentsToApplyBusinessHour: '', }; diff --git a/apps/meteor/tests/end-to-end/api/livechat/19-business-hours.ts b/apps/meteor/tests/end-to-end/api/livechat/19-business-hours.ts index af803a0af67..55d5fd7a9f1 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/19-business-hours.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/19-business-hours.ts @@ -250,6 +250,36 @@ describe('LIVECHAT - business hours', function () { }); }); + (IS_EE ? describe : describe.skip)('[EE] BH operations upon creation', () => { + let defaultBusinessHour: ILivechatBusinessHour; + + before(async () => { + await updateSetting('Livechat_business_hour_type', LivechatBusinessHourBehaviors.MULTIPLE); + // wait for the callbacks to be registered + await sleep(1000); + + // cleanup any existing business hours + await removeAllCustomBusinessHours(); + + // get default business hour + defaultBusinessHour = await getDefaultBusinessHour(); + + // close default business hour + await openOrCloseBusinessHour(defaultBusinessHour, true); + }); + + it('should create a custom business hour which is closed by default', async () => { + // create custom business hour and link it to a department + const { department, agent } = await createDepartmentWithAnOnlineAgent(); + await createCustomBusinessHour([department._id], false); + + const latestAgent: ILivechatAgent = await getMe(agent.credentials as any); + expect(latestAgent).to.be.an('object'); + expect(latestAgent.openBusinessHours).to.be.an('array').of.length(0); + expect(latestAgent.statusLivechat).to.be.equal(ILivechatAgentStatus.NOT_AVAILABLE); + }); + }); + // Scenario: Assume we have a BH linked to a department, and we archive the department // Expected result: // 1) If BH is open and only linked to that department, it should be closed