cal.pub0.org/packages/features/insights/server/events.ts

194 lines
4.9 KiB
TypeScript

import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs";
import { prisma } from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
interface ITimeRange {
start: Dayjs;
end: Dayjs;
}
type TimeViewType = "week" | "month" | "year" | "day";
class EventsInsights {
static getBookingsInTimeRange = async (
timeRange: ITimeRange,
where: Prisma.BookingTimeStatusWhereInput
) => {
const { start, end } = timeRange;
const events = await prisma.bookingTimeStatus.count({
where: {
...where,
createdAt: {
gte: start.toISOString(),
lte: end.toISOString(),
},
},
});
return events;
};
static getCreatedEventsInTimeRange = async (
timeRange: ITimeRange,
where: Prisma.BookingTimeStatusWhereInput
) => {
const result = await this.getBookingsInTimeRange(timeRange, where);
return result;
};
static getCancelledEventsInTimeRange = async (
timeRange: ITimeRange,
where: Prisma.BookingTimeStatusWhereInput
) => {
const result = await this.getBookingsInTimeRange(timeRange, {
...where,
timeStatus: "cancelled",
});
return result;
};
static getCompletedEventsInTimeRange = async (
timeRange: ITimeRange,
where: Prisma.BookingTimeStatusWhereInput
) => {
const result = await this.getBookingsInTimeRange(timeRange, {
...where,
timeStatus: "completed",
});
return result;
};
static getRescheduledEventsInTimeRange = async (
timeRange: ITimeRange,
where: Prisma.BookingTimeStatusWhereInput
) => {
const result = await this.getBookingsInTimeRange(timeRange, {
...where,
timeStatus: "rescheduled",
});
return result;
};
static getBaseBookingForEventStatus = async (where: Prisma.BookingTimeStatusWhereInput) => {
const baseBookings = await prisma.bookingTimeStatus.findMany({
where,
select: {
id: true,
},
});
return baseBookings;
};
static getTotalRescheduledEvents = async (bookingIds: number[]) => {
return await prisma.bookingTimeStatus.count({
where: {
id: {
in: bookingIds,
},
timeStatus: "rescheduled",
},
});
};
static getTotalCancelledEvents = async (bookingIds: number[]) => {
return await prisma.bookingTimeStatus.count({
where: {
id: {
in: bookingIds,
},
timeStatus: "cancelled",
},
});
};
static getTimeLine = async (timeView: TimeViewType, startDate: Dayjs, endDate: Dayjs) => {
let resultTimeLine: string[] = [];
if (timeView) {
switch (timeView) {
case "week":
resultTimeLine = this.getWeekTimeline(startDate, endDate);
break;
case "month":
resultTimeLine = this.getMonthTimeline(startDate, endDate);
break;
case "year":
resultTimeLine = this.getYearTimeline(startDate, endDate);
break;
default:
resultTimeLine = this.getWeekTimeline(startDate, endDate);
break;
}
}
return resultTimeLine;
};
static getTimeView = (timeView: TimeViewType, startDate: Dayjs, endDate: Dayjs) => {
let resultTimeView = timeView;
if (startDate.diff(endDate, "day") > 90) {
resultTimeView = "month";
} else if (startDate.diff(endDate, "day") > 365) {
resultTimeView = "year";
}
return resultTimeView;
};
static getWeekTimeline(startDate: Dayjs, endDate: Dayjs): string[] {
const now = dayjs();
const endOfDay = now.endOf("day");
let pivotDate = dayjs(startDate);
const dates: string[] = [];
while (pivotDate.isBefore(endDate) && pivotDate.isBefore(endOfDay)) {
const weekEndDate = pivotDate.add(7, "day").isBefore(endOfDay) ? pivotDate.add(7, "day") : endOfDay;
dates.push(pivotDate.format("YYYY-MM-DD"));
pivotDate = weekEndDate.add(1, "day");
}
return dates;
}
static getMonthTimeline(startDate: Dayjs, endDate: Dayjs) {
let pivotDate = dayjs(startDate);
const dates = [];
while (pivotDate.isBefore(endDate)) {
pivotDate = pivotDate.set("month", pivotDate.get("month") + 1);
dates.push(pivotDate.format("YYYY-MM-DD"));
}
return dates;
}
static getYearTimeline(startDate: Dayjs, endDate: Dayjs) {
const pivotDate = dayjs(startDate);
const dates = [];
while (pivotDate.isBefore(endDate)) {
pivotDate.set("year", pivotDate.get("year") + 1);
dates.push(pivotDate.format("YYYY-MM-DD"));
}
return dates;
}
static getPercentage = (actualMetric: number, previousMetric: number) => {
const differenceActualVsPrevious = actualMetric - previousMetric;
if (differenceActualVsPrevious === 0) {
return 0;
}
const result = (differenceActualVsPrevious * 100) / previousMetric;
if (isNaN(result) || !isFinite(result)) {
return 0;
}
return result;
};
}
export { EventsInsights };