Skip to content

Commit

Permalink
chore: add Updater on markRoomResponded and save-visitor-inactivity
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardogarim committed Aug 7, 2024
1 parent fd5eb17 commit ac90af4
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 51 deletions.
70 changes: 28 additions & 42 deletions apps/meteor/app/livechat/server/hooks/markRoomResponded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,15 @@ import moment from 'moment';
import { callbacks } from '../../../../lib/callbacks';
import { notifyOnLivechatInquiryChanged } from '../../../lib/server/lib/notifyListener';

function mountResponseBy(
export async function markRoomResponded(
message: IMessage,
room: IOmnichannelRoom,
roomUpdater: Updater<IOmnichannelRoom>,
): IOmnichannelRoom['responseBy'] | void {
if (room.responseBy && !room.waitingResponse) {
): Promise<IOmnichannelRoom['responseBy'] | undefined> {
if (message.t || isEditedMessage(message) || isMessageFromVisitor(message)) {
return;
}

const responseBy: IOmnichannelRoom['responseBy'] = room.responseBy || {
_id: message.u._id,
username: message.u.username,
firstResponseTs: new Date(message.ts),
lastMessageTs: new Date(message.ts),
};

LivechatRooms.getResponseByRoomIdUpdateQuery(responseBy, roomUpdater);

return responseBy;
}

function mountAgentLastMessageTs(room: IOmnichannelRoom, roomUpdater: Updater<IOmnichannelRoom>): void {
if (room.responseBy) {
LivechatRooms.getAgentLastMessageTsUpdateQuery(roomUpdater);
}

if (!room.waitingResponse) {
// case where agent sends second message or any subsequent message in a room before visitor responds to the first message
// in this case, we just need to update the lastMessageTs of the responseBy object
if (room.responseBy) {
LivechatRooms.getAgentLastMessageTsUpdateQuery(roomUpdater);
}
}
}

async function markVisitorAndInquiryActive(room: IOmnichannelRoom): Promise<void> {
const monthYear = moment().format('YYYY-MM');
const isVisitorActive = await LivechatVisitors.isVisitorActiveOnPeriod(room.v._id, monthYear);

Expand All @@ -61,28 +34,41 @@ async function markVisitorAndInquiryActive(room: IOmnichannelRoom): Promise<void
void notifyOnLivechatInquiryChanged(livechatInquiry, 'updated', { v: livechatInquiry.v });
}
}
}

export async function markRoomResponded(
message: IMessage,
room: IOmnichannelRoom,
roomUpdater: Updater<IOmnichannelRoom>,
): Promise<IOmnichannelRoom['responseBy'] | void> {
await markVisitorAndInquiryActive(room);
mountAgentLastMessageTs(room, roomUpdater);
return mountResponseBy(message, room, roomUpdater);
if (room.responseBy) {
LivechatRooms.getAgentLastMessageTsUpdateQuery(roomUpdater);
}

if (!room.waitingResponse) {
// case where agent sends second message or any subsequent message in a room before visitor responds to the first message
// in this case, we just need to update the lastMessageTs of the responseBy object
if (room.responseBy) {
LivechatRooms.getAgentLastMessageTsUpdateQuery(roomUpdater);
}

return room.responseBy;
}

const responseBy: IOmnichannelRoom['responseBy'] = room.responseBy || {
_id: message.u._id,
username: message.u.username,
firstResponseTs: new Date(message.ts),
lastMessageTs: new Date(message.ts),
};

LivechatRooms.getResponseByRoomIdUpdateQuery(responseBy, roomUpdater);

return responseBy;
}

callbacks.add(
'afterOmnichannelSaveMessage',
async (message, { room, roomUpdater }) => {
if (!message || message.t || isEditedMessage(message) || isMessageFromVisitor(message)) {
return message;
return;
}

await markRoomResponded(message, room, roomUpdater);

return message;
},
callbacks.priority.HIGH,
'markRoomResponded',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,19 @@ callbacks.remove('afterOmnichannelSaveMessage', 'markRoomResponded');
callbacks.add(
'afterOmnichannelSaveMessage',
async (message, { room, roomUpdater }) => {
if (!message || !shouldSaveInactivity(message)) {
const responseBy = await markRoomResponded(message, room, roomUpdater);

if (!shouldSaveInactivity(message)) {
return message;
}

const responseBy = await markRoomResponded(message, room, roomUpdater);

if (!responseBy) {
return message;
return;
}

if (moment(responseBy.firstResponseTs).isSame(moment(message.ts))) {
await setPredictedVisitorAbandonmentTime(room);
await setPredictedVisitorAbandonmentTime({ ...room, responseBy }, roomUpdater);
}

return message;
},
callbacks.priority.MEDIUM,
'save-visitor-inactivity',
Expand Down
12 changes: 10 additions & 2 deletions apps/meteor/ee/app/livechat-enterprise/server/lib/Helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { api } from '@rocket.chat/core-services';
import type { IOmnichannelRoom, IOmnichannelServiceLevelAgreements, InquiryWithAgentInfo } from '@rocket.chat/core-typings';
import type { Updater } from '@rocket.chat/models';
import {
Rooms as RoomRaw,
LivechatRooms,
Expand Down Expand Up @@ -139,7 +140,10 @@ const dispatchWaitingQueueStatus = async (department?: string) => {
// but we don't need to notify _each_ change that takes place, just their final position
export const debouncedDispatchWaitingQueueStatus = memoizeDebounce(dispatchWaitingQueueStatus, 1200);

export const setPredictedVisitorAbandonmentTime = async (room: Pick<IOmnichannelRoom, '_id' | 'responseBy' | 'departmentId'>) => {
export const setPredictedVisitorAbandonmentTime = async (
room: Pick<IOmnichannelRoom, '_id' | 'responseBy' | 'departmentId'>,
roomUpdater?: Updater<IOmnichannelRoom>,
) => {
if (
!room.responseBy?.firstResponseTs ||
!settings.get('Livechat_abandoned_rooms_action') ||
Expand All @@ -160,7 +164,11 @@ export const setPredictedVisitorAbandonmentTime = async (room: Pick<IOmnichannel
}

const willBeAbandonedAt = moment(room.responseBy.firstResponseTs).add(Number(secondsToAdd), 'seconds').toDate();
await LivechatRooms.setPredictedVisitorAbandonmentByRoomId(room._id, willBeAbandonedAt);
if (roomUpdater) {
await LivechatRooms.getPredictedVisitorAbandonmentByRoomIdUpdateQuery(willBeAbandonedAt, roomUpdater);
} else {
await LivechatRooms.setPredictedVisitorAbandonmentByRoomId(room._id, willBeAbandonedAt);
}
};

export const updatePredictedVisitorAbandonment = async () => {
Expand Down
9 changes: 9 additions & 0 deletions apps/meteor/ee/server/models/raw/LivechatRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
} from '@rocket.chat/core-typings';
import { LivechatPriorityWeight, DEFAULT_SLA_CONFIG } from '@rocket.chat/core-typings';
import type { ILivechatRoomsModel } from '@rocket.chat/model-typings';
import type { Updater } from '@rocket.chat/models';
import type { FindCursor, UpdateResult, Document, FindOptions, Db, Collection, Filter, AggregationCursor } from 'mongodb';

import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred';
Expand All @@ -20,6 +21,7 @@ declare module '@rocket.chat/model-typings' {
unsetPredictedVisitorAbandonmentByRoomId(rid: string): Promise<UpdateResult>;
findAbandonedOpenRooms(date: Date, extraQuery?: Filter<IOmnichannelRoom>): FindCursor<IOmnichannelRoom>;
setPredictedVisitorAbandonmentByRoomId(roomId: string, date: Date): Promise<UpdateResult>;
getPredictedVisitorAbandonmentByRoomIdUpdateQuery(date: Date, roomUpdater: Updater<IOmnichannelRoom>): Updater<IOmnichannelRoom>;
unsetAllPredictedVisitorAbandonment(): Promise<void>;
setOnHoldByRoomId(roomId: string): Promise<UpdateResult>;
unsetOnHoldByRoomId(roomId: string): Promise<UpdateResult>;
Expand Down Expand Up @@ -209,6 +211,13 @@ export class LivechatRoomsRawEE extends LivechatRoomsRaw implements ILivechatRoo
);
}

getPredictedVisitorAbandonmentByRoomIdUpdateQuery(
date: Date,
roomUpdater: Updater<IOmnichannelRoom> = this.getUpdater(),
): Updater<IOmnichannelRoom> {
return roomUpdater.set('omnichannel.predictedVisitorAbandonmentAt', date);
}

setPredictedVisitorAbandonmentByRoomId(rid: string, willBeAbandonedAt: Date): Promise<UpdateResult> {
const query = {
_id: rid,
Expand Down
7 changes: 7 additions & 0 deletions apps/meteor/server/models/raw/LivechatRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2616,6 +2616,13 @@ export class LivechatRoomsRaw extends BaseRaw<IOmnichannelRoom> implements ILive
throw new Error('Method not implemented.');
}

getPredictedVisitorAbandonmentByRoomIdUpdateQuery(
_willBeAbandonedAt: Date,
_updater: Updater<IOmnichannelRoom>,
): Updater<IOmnichannelRoom> {
throw new Error('Method not implemented.');
}

setPredictedVisitorAbandonmentByRoomId(_rid: string, _willBeAbandonedAt: Date): Promise<UpdateResult> {
throw new Error('Method not implemented.');
}
Expand Down

0 comments on commit ac90af4

Please sign in to comment.