Skip to content

Commit

Permalink
Calculate and store MAC stats
Browse files Browse the repository at this point in the history
  • Loading branch information
KevLehman committed Sep 19, 2023
1 parent 7af80bb commit ae80366
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type WorkspaceRegistrationData<T> = {
setupComplete: boolean;
connectionDisable: boolean;
npsEnabled: SettingValue;
activeContactsBillingMonth: unknown;
activeContactsYesterday: unknown;
};

export async function buildWorkspaceRegistrationData<T extends string | undefined>(contactEmail: T): Promise<WorkspaceRegistrationData<T>> {
Expand Down Expand Up @@ -78,5 +80,7 @@ export async function buildWorkspaceRegistrationData<T extends string | undefine
setupComplete: setupWizardState === 'completed',
connectionDisable: !registerServer,
npsEnabled,
activeContactsBillingMonth: stats.omnichannelContactsBySource.contactsCount,
activeContactsYesterday: stats.uniqueContactsOfYesterday.contactsCount,
};
}
32 changes: 32 additions & 0 deletions apps/meteor/app/statistics/server/lib/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import {
LivechatCustomField,
Subscriptions,
Users,
LivechatRooms,
} from '@rocket.chat/models';
import { MongoInternals } from 'meteor/mongo';
import moment from 'moment';

import { getStatistics as getEnterpriseStatistics } from '../../../../ee/app/license/server';
import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred';
Expand Down Expand Up @@ -259,6 +261,36 @@ export const statistics = {
}),
);

const defaultValue = { contactsCount: 0, conversationsCount: 0, sources: [] };
const billablePeriod = moment.utc().format('YYYY-MM');
statsPms.push(
LivechatRooms.getMACStatisticsForPeriod(billablePeriod).then(([result]) => {
statistics.omnichannelContactsBySource = result || defaultValue;
}),
);

const monthAgo = moment.utc().subtract(30, 'days').toDate();
const today = moment.utc().toDate();
statsPms.push(
LivechatRooms.getMACStatisticsBetweenDates(monthAgo, today).then(([result]) => {
statistics.uniqueContactsOfLastMonth = result || defaultValue;
}),
);

const weekAgo = moment.utc().subtract(7, 'days').toDate();
statsPms.push(
LivechatRooms.getMACStatisticsBetweenDates(weekAgo, today).then(([result]) => {
statistics.uniqueContactsOfLastWeek = result || defaultValue;
}),
);

const yesterday = moment.utc().subtract(1, 'days').toDate();
statsPms.push(
LivechatRooms.getMACStatisticsBetweenDates(yesterday, today).then(([result]) => {
statistics.uniqueContactsOfYesterday = result || defaultValue;
}),
);

// Message statistics
statistics.totalChannelMessages = (await Rooms.findByType('c', { projection: { msgs: 1 } }).toArray()).reduce(
function _countChannelMessages(num: number, room: IRoom) {
Expand Down
121 changes: 121 additions & 0 deletions apps/meteor/server/models/raw/LivechatRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
ILivechatPriority,
IOmnichannelServiceLevelAgreements,
ReportResult,
MACStats,
} from '@rocket.chat/core-typings';
import { UserStatus } from '@rocket.chat/core-typings';
import type { ILivechatRoomsModel } from '@rocket.chat/model-typings';
Expand Down Expand Up @@ -2466,6 +2467,126 @@ export class LivechatRoomsRaw extends BaseRaw<IOmnichannelRoom> implements ILive
return this.updateOne(query, update);
}

async getMACStatisticsForPeriod(period: string): Promise<MACStats[]> {
return this.col
.aggregate<MACStats>([
{
$match: {
't': 'l',
'v.activity': period,
},
},
{
$group: {
_id: {
source: {
$ifNull: ['$source.alias', '$source.type'],
},
},
contactsCount: {
$addToSet: '$v._id',
},
conversationsCount: {
$sum: 1,
},
},
},
{
$group: {
_id: null,
sources: {
$push: {
source: '$_id.source',
contactsCount: {
$size: '$contactsCount',
},
conversationsCount: '$conversationsCount',
},
},
totalContactsCount: {
$sum: {
$size: '$contactsCount',
},
},
totalConversationsCount: {
$sum: '$conversationsCount',
},
},
},
{
$project: {
_id: 0,
contactsCount: '$totalContactsCount',
conversationsCount: '$totalConversationsCount',
sources: 1,
},
},
])
.toArray();
}

async getMACStatisticsBetweenDates(start: Date, end: Date): Promise<MACStats[]> {
return this.col
.aggregate<MACStats>([
{
$match: {
't': 'l',
'v.activity': { $exists: true },
'ts': {
$gte: start,
$lt: end,
},
},
},
{
$group: {
_id: {
source: {
$ifNull: ['$source.alias', '$source.type'],
},
},
contactsCount: {
$addToSet: '$v._id',
},
conversationsCount: {
$sum: 1,
},
},
},
{
$group: {
_id: null,
sources: {
$push: {
source: '$_id.source',
contactsCount: {
$size: '$contactsCount',
},
conversationsCount: '$conversationsCount',
},
},
totalContactsCount: {
$sum: {
$size: '$contactsCount',
},
},
totalConversationsCount: {
$sum: '$conversationsCount',
},
},
},
{
$project: {
_id: 0,
contactsCount: '$totalContactsCount',
conversationsCount: '$totalConversationsCount',
sources: 1,
},
},
])
.toArray();
}

async unsetAllPredictedVisitorAbandonment(): Promise<void> {
throw new Error('Method not implemented.');
}
Expand Down
6 changes: 6 additions & 0 deletions apps/meteor/server/models/raw/LivechatVisitors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,12 @@ export class LivechatVisitorsRaw extends BaseRaw<ILivechatVisitor> implements IL
},
);
}

countVisitorsOnPeriod(period: string): Promise<number> {
return this.countDocuments({
activity: period,
});
}
}

type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };
5 changes: 5 additions & 0 deletions packages/core-typings/src/IStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { CpuInfo } from 'os';
import type { DeviceSessionAggregationResult, OSSessionAggregationResult, UserSessionAggregationResult } from './ISession';
import type { ISettingStatisticsObject } from './ISetting';
import type { ITeamStats } from './ITeam';
import type { MACStats } from './omnichannel';

export interface IStats {
_id: string;
Expand Down Expand Up @@ -85,6 +86,10 @@ export interface IStats {
mongoStorageEngine: string;
pushQueue: number;
omnichannelSources: { [key: string]: number | string }[];
omnichannelContactsBySource: MACStats;
uniqueContactsOfLastMonth: MACStats;
uniqueContactsOfLastWeek: MACStats;
uniqueContactsOfYesterday: MACStats;
departments: number;
archivedDepartments: number;
routingAlgorithm: string;
Expand Down
1 change: 1 addition & 0 deletions packages/core-typings/src/omnichannel/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './sms';
export * from './routing';
export * from './reports';
export * from './mac';
5 changes: 5 additions & 0 deletions packages/core-typings/src/omnichannel/mac.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type MACStats = {
contactsCount: number;
conversationsCount: number;
sources: { source: string; contactsCount: number; conversationsCount: number }[];
};
11 changes: 10 additions & 1 deletion packages/model-typings/src/models/ILivechatRoomsModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import type { IMessage, IOmnichannelRoom, IOmnichannelRoomClosingInfo, ISetting, ILivechatVisitor } from '@rocket.chat/core-typings';
import type {
IMessage,
IOmnichannelRoom,
IOmnichannelRoomClosingInfo,
ISetting,
ILivechatVisitor,
MACStats,
} from '@rocket.chat/core-typings';
import type { FindCursor, UpdateResult, AggregationCursor, Document, FindOptions, DeleteResult, Filter } from 'mongodb';

import type { FindPaginated } from '..';
Expand Down Expand Up @@ -235,4 +242,6 @@ export interface ILivechatRoomsModel extends IBaseModel<IOmnichannelRoom> {
changeVisitorByRoomId(roomId: string, visitor: { _id: string; username: string; token: string }): Promise<UpdateResult>;
unarchiveOneById(roomId: string): Promise<UpdateResult>;
markVisitorActiveForPeriod(rid: string, period: string): Promise<UpdateResult>;
getMACStatisticsForPeriod(period: string): Promise<MACStats[]>;
getMACStatisticsBetweenDates(start: Date, end: Date): Promise<MACStats[]>;
}
2 changes: 2 additions & 0 deletions packages/model-typings/src/models/ILivechatVisitorsModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ export interface ILivechatVisitorsModel extends IBaseModel<ILivechatVisitor> {
disableById(_id: string): Promise<UpdateResult>;

findEnabled(query: Filter<ILivechatVisitor>, options?: FindOptions<ILivechatVisitor>): FindCursor<ILivechatVisitor>;

countVisitorsOnPeriod(period: string): Promise<number>;
}

0 comments on commit ae80366

Please sign in to comment.