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

183 lines
4.8 KiB
TypeScript
Raw Normal View History

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.BookingWhereInput) => {
const { start, end } = timeRange;
const events = await prisma.booking.count({
where: {
...where,
createdAt: {
gte: start.toISOString(),
lte: end.toISOString(),
},
},
});
return events;
};
static getCreatedEventsInTimeRange = async (timeRange: ITimeRange, where: Prisma.BookingWhereInput) => {
const result = await this.getBookingsInTimeRange(timeRange, where);
return result;
};
static getCancelledEventsInTimeRange = async (timeRange: ITimeRange, where: Prisma.BookingWhereInput) => {
const result = await this.getBookingsInTimeRange(timeRange, {
...where,
status: "CANCELLED",
});
return result;
};
static getCompletedEventsInTimeRange = async (timeRange: ITimeRange, where: Prisma.BookingWhereInput) => {
const result = await this.getBookingsInTimeRange(timeRange, {
...where,
status: "ACCEPTED",
endTime: {
lte: dayjs().toISOString(),
},
});
return result;
};
static getRescheduledEventsInTimeRange = async (timeRange: ITimeRange, where: Prisma.BookingWhereInput) => {
const result = await this.getBookingsInTimeRange(timeRange, {
...where,
rescheduled: true,
});
return result;
};
static getBaseBookingForEventStatus = async (where: Prisma.BookingWhereInput) => {
const baseBookings = await prisma.booking.findMany({
where,
select: {
id: true,
eventType: true,
},
});
return baseBookings;
};
static getTotalRescheduledEvents = async (bookingIds: number[]) => {
return await prisma.booking.count({
where: {
id: {
in: bookingIds,
},
rescheduled: true,
},
});
};
static getTotalCancelledEvents = async (bookingIds: number[]) => {
return await prisma.booking.count({
where: {
id: {
in: bookingIds,
},
status: "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;
};
Follow up insights - user metrics (#8016) * init page * init insights frontend * nit * nit * nit * merge * fixed icons * i18n, needs features * Init insights trpc * Using trpc on client * Added events timeline * Seed analytics script * connect ui with trpc * Added and fixed event time lines * WIP popular days and avg time duration event type * added new metric graphs * improved upgrade tip * always show upgrade screen * upgrade tremor.so and select inputs for page * Remove log * Move everything to components and add context * Fix select types using calcom ui one * Adding translations * Add missing translations * Add more translations * min fix * Fixes for date select * Prefer early return and mobile design fixes * Fix style for mobile * Fix data with userId filter from popular events * add user id to average time duration * fix types for select-react * Removed submodules * Delete website * Update yarn.lock * Code organization and type fixes * trpc fixes * Builds are now passing * Relocates server code * Add url state in insights * Update FiltersProvider.tsx * Cleanup * Update embed-iframe.ts * Update FilterType.tsx * Update seed-app-store.config.json * Update index.tsx * Renamed seeder * Update FiltersProvider.tsx * Fix for query params * no wrap on lg screen * Fix shadow borders from tremor components, fix title font * Add ring-gray to match filters * add cursor pointer * copy improvements * blue to black * fixed date select focus * text right for table * Adds missing translation strings * Fix url state for filter type * more layout improvements * more padding improvements * more UI fixes (padding, sizes) requested by ciaran * Apply suggestions from code review * WIP user without team metrics * yarn * Adds loading state for graphs and tables * fix average render when no data * Multiple fixes in insights * Fix most and least booked members querys * More fix for clear filters --------- Co-authored-by: Peer Richelsen <peer@cal.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com>
2023-04-04 11:58:19 +00:00
static getWeekTimeline(startDate: Dayjs, endDate: Dayjs): string[] {
const now = dayjs();
const endOfDay = now.endOf("day");
let pivotDate = dayjs(startDate);
Follow up insights - user metrics (#8016) * init page * init insights frontend * nit * nit * nit * merge * fixed icons * i18n, needs features * Init insights trpc * Using trpc on client * Added events timeline * Seed analytics script * connect ui with trpc * Added and fixed event time lines * WIP popular days and avg time duration event type * added new metric graphs * improved upgrade tip * always show upgrade screen * upgrade tremor.so and select inputs for page * Remove log * Move everything to components and add context * Fix select types using calcom ui one * Adding translations * Add missing translations * Add more translations * min fix * Fixes for date select * Prefer early return and mobile design fixes * Fix style for mobile * Fix data with userId filter from popular events * add user id to average time duration * fix types for select-react * Removed submodules * Delete website * Update yarn.lock * Code organization and type fixes * trpc fixes * Builds are now passing * Relocates server code * Add url state in insights * Update FiltersProvider.tsx * Cleanup * Update embed-iframe.ts * Update FilterType.tsx * Update seed-app-store.config.json * Update index.tsx * Renamed seeder * Update FiltersProvider.tsx * Fix for query params * no wrap on lg screen * Fix shadow borders from tremor components, fix title font * Add ring-gray to match filters * add cursor pointer * copy improvements * blue to black * fixed date select focus * text right for table * Adds missing translation strings * Fix url state for filter type * more layout improvements * more padding improvements * more UI fixes (padding, sizes) requested by ciaran * Apply suggestions from code review * WIP user without team metrics * yarn * Adds loading state for graphs and tables * fix average render when no data * Multiple fixes in insights * Fix most and least booked members querys * More fix for clear filters --------- Co-authored-by: Peer Richelsen <peer@cal.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com>
2023-04-04 11:58:19 +00:00
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"));
Follow up insights - user metrics (#8016) * init page * init insights frontend * nit * nit * nit * merge * fixed icons * i18n, needs features * Init insights trpc * Using trpc on client * Added events timeline * Seed analytics script * connect ui with trpc * Added and fixed event time lines * WIP popular days and avg time duration event type * added new metric graphs * improved upgrade tip * always show upgrade screen * upgrade tremor.so and select inputs for page * Remove log * Move everything to components and add context * Fix select types using calcom ui one * Adding translations * Add missing translations * Add more translations * min fix * Fixes for date select * Prefer early return and mobile design fixes * Fix style for mobile * Fix data with userId filter from popular events * add user id to average time duration * fix types for select-react * Removed submodules * Delete website * Update yarn.lock * Code organization and type fixes * trpc fixes * Builds are now passing * Relocates server code * Add url state in insights * Update FiltersProvider.tsx * Cleanup * Update embed-iframe.ts * Update FilterType.tsx * Update seed-app-store.config.json * Update index.tsx * Renamed seeder * Update FiltersProvider.tsx * Fix for query params * no wrap on lg screen * Fix shadow borders from tremor components, fix title font * Add ring-gray to match filters * add cursor pointer * copy improvements * blue to black * fixed date select focus * text right for table * Adds missing translation strings * Fix url state for filter type * more layout improvements * more padding improvements * more UI fixes (padding, sizes) requested by ciaran * Apply suggestions from code review * WIP user without team metrics * yarn * Adds loading state for graphs and tables * fix average render when no data * Multiple fixes in insights * Fix most and least booked members querys * More fix for clear filters --------- Co-authored-by: Peer Richelsen <peer@cal.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com>
2023-04-04 11:58:19 +00:00
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 };