Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 106 additions & 84 deletions packages/lib/server/service/InsightsBookingBaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
isNumberFilterValue,
} from "@calcom/features/data-table/lib/utils";
import type { DateRange } from "@calcom/features/insights/server/insightsDateUtils";
import { Prisma } from "@calcom/prisma/client";
import type { PrismaClient } from "@calcom/prisma";
import { Prisma } from "@calcom/prisma/client";
import { MembershipRole } from "@calcom/prisma/enums";

import { MembershipRepository } from "../repository/membership";
Expand Down Expand Up @@ -168,12 +168,7 @@ export class InsightsBookingBaseService {
async getBookingsByHourStats({ timeZone }: { timeZone: string }) {
const baseConditions = await this.getBaseConditions();

const results = await this.prisma.$queryRaw<
Array<{
hour: string;
count: number;
}>
>`
const query = Prisma.sql`
SELECT
EXTRACT(HOUR FROM ("startTime" AT TIME ZONE 'UTC' AT TIME ZONE ${timeZone}))::int as "hour",
COUNT(*)::int as "count"
Expand All @@ -184,6 +179,13 @@ export class InsightsBookingBaseService {
ORDER BY 1
`;

const results = await this.prisma.$queryRaw<
Array<{
hour: string;
count: number;
}>
>(query);

// Create a map of results by hour for easy lookup
const resultsMap = new Map(results.map((row) => [Number(row.hour), row.count]));

Expand Down Expand Up @@ -216,11 +218,13 @@ export class InsightsBookingBaseService {
}
}

return await this.prisma.$queryRaw<Array<SelectedFields<TSelect>>>`
const query = Prisma.sql`
SELECT ${selectFields}
FROM "BookingTimeStatusDenormalized"
WHERE ${baseConditions}
`;

return await this.prisma.$queryRaw<Array<SelectedFields<TSelect>>>(query);
}

async getBaseConditions(): Promise<Prisma.Sql> {
Expand Down Expand Up @@ -449,33 +453,17 @@ export class InsightsBookingBaseService {
const baseConditions = await this.getBaseConditions();

// Get total count first
const totalCountResult = await this.prisma.$queryRaw<[{ count: number }]>`
const totalCountQuery = Prisma.sql`
SELECT COUNT(*)::int as count
FROM "BookingTimeStatusDenormalized"
WHERE ${baseConditions}
`;

const totalCountResult = await this.prisma.$queryRaw<[{ count: number }]>(totalCountQuery);
const totalCount = totalCountResult[0]?.count || 0;

// 1. Get booking data from BookingTimeStatusDenormalized
const csvData = await this.prisma.$queryRaw<
Array<{
id: number;
uid: string | null;
title: string;
createdAt: Date;
timeStatus: string;
eventTypeId: number | null;
eventLength: number;
startTime: Date;
endTime: Date;
paid: boolean;
userEmail: string;
userUsername: string;
rating: number | null;
ratingFeedback: string | null;
noShowHost: boolean;
}>
>`
const csvDataQuery = Prisma.sql`
SELECT
"id",
"uid",
Expand All @@ -499,6 +487,26 @@ export class InsightsBookingBaseService {
OFFSET ${offset}
`;

const csvData = await this.prisma.$queryRaw<
Array<{
id: number;
uid: string | null;
title: string;
createdAt: Date;
timeStatus: string;
eventTypeId: number | null;
eventLength: number;
startTime: Date;
endTime: Date;
paid: boolean;
userEmail: string;
userUsername: string;
rating: number | null;
ratingFeedback: string | null;
noShowHost: boolean;
}>
>(csvDataQuery);

if (csvData.length === 0) {
return { data: csvData, total: totalCount };
}
Expand Down Expand Up @@ -641,15 +649,7 @@ export class InsightsBookingBaseService {

const baseConditions = await this.getBaseConditions();

const data = await this.prisma.$queryRaw<
{
date: Date;
bookingsCount: number;
timeStatus: string;
noShowHost: boolean;
noShowGuests: number;
}[]
>`
const query = Prisma.sql`
WITH booking_stats AS (
SELECT
DATE("createdAt" AT TIME ZONE ${timeZone}) as "date",
Expand Down Expand Up @@ -688,6 +688,16 @@ export class InsightsBookingBaseService {
ORDER BY bs."date"
`;

const data = await this.prisma.$queryRaw<
{
date: Date;
bookingsCount: number;
timeStatus: string;
noShowHost: boolean;
noShowGuests: number;
}[]
>(query);

// Initialize aggregate object with zero counts for all date ranges
const aggregate: {
[date: string]: {
Expand Down Expand Up @@ -777,12 +787,7 @@ export class InsightsBookingBaseService {
async getPopularEventsStats() {
const baseConditions = await this.getBaseConditions();

const bookingsFromSelected = await this.prisma.$queryRaw<
Array<{
eventTypeId: number;
count: number;
}>
>`
const query = Prisma.sql`
SELECT
"eventTypeId",
COUNT(id)::int as count
Expand All @@ -793,6 +798,13 @@ export class InsightsBookingBaseService {
LIMIT 10
`;

const bookingsFromSelected = await this.prisma.$queryRaw<
Array<{
eventTypeId: number;
count: number;
}>
>(query);

const eventTypeIds = bookingsFromSelected.map((booking) => booking.eventTypeId);

if (eventTypeIds.length === 0) {
Expand Down Expand Up @@ -866,12 +878,7 @@ export class InsightsBookingBaseService {
additionalCondition = Prisma.sql`AND status = 'accepted'`;
}

const bookingsFromTeam = await this.prisma.$queryRaw<
Array<{
userId: number;
count: number;
}>
>`
const query = Prisma.sql`
SELECT
"userId",
COUNT(id)::int as count
Expand All @@ -882,6 +889,13 @@ export class InsightsBookingBaseService {
LIMIT 10
`;

const bookingsFromTeam = await this.prisma.$queryRaw<
Array<{
userId: number;
count: number;
}>
>(query);

if (bookingsFromTeam.length === 0) {
return [];
}
Expand Down Expand Up @@ -927,12 +941,7 @@ export class InsightsBookingBaseService {
async getMembersRatingStats(sortOrder: "ASC" | "DESC" = "DESC"): Promise<UserStatsData> {
const baseConditions = await this.getBaseConditions();

const bookingsFromTeam = await this.prisma.$queryRaw<
Array<{
userId: number;
count: number;
}>
>`
const query = Prisma.sql`
SELECT
"userId",
AVG("rating")::float as "count"
Expand All @@ -943,6 +952,13 @@ export class InsightsBookingBaseService {
LIMIT 10
`;

const bookingsFromTeam = await this.prisma.$queryRaw<
Array<{
userId: number;
count: number;
}>
>(query);

if (bookingsFromTeam.length === 0) {
return [];
}
Expand Down Expand Up @@ -988,13 +1004,7 @@ export class InsightsBookingBaseService {
async getRecentRatingsStats() {
const baseConditions = await this.getBaseConditions();

const bookingsFromTeam = await this.prisma.$queryRaw<
Array<{
userId: number | null;
rating: number | null;
ratingFeedback: string | null;
}>
>`
const query = Prisma.sql`
SELECT
"userId",
"rating",
Expand All @@ -1005,6 +1015,14 @@ export class InsightsBookingBaseService {
LIMIT 10
`;

const bookingsFromTeam = await this.prisma.$queryRaw<
Array<{
userId: number | null;
rating: number | null;
ratingFeedback: string | null;
}>
>(query);

if (bookingsFromTeam.length === 0) {
return [];
}
Expand Down Expand Up @@ -1062,19 +1080,7 @@ export class InsightsBookingBaseService {
async getBookingStats() {
const baseConditions = await this.getBaseConditions();

const stats = await this.prisma.$queryRaw<
Array<{
total_bookings: bigint;
completed_bookings: bigint;
rescheduled_bookings: bigint;
cancelled_bookings: bigint;
no_show_host_bookings: bigint;
avg_rating: number | null;
total_ratings: bigint;
ratings_above_3: bigint;
no_show_guests: bigint;
}>
>`
const query = Prisma.sql`
WITH booking_stats AS (
SELECT
COUNT(*) as total_bookings,
Expand Down Expand Up @@ -1107,6 +1113,20 @@ export class InsightsBookingBaseService {
FROM booking_stats bs, guest_stats gs
`;

const stats = await this.prisma.$queryRaw<
Array<{
total_bookings: bigint;
completed_bookings: bigint;
rescheduled_bookings: bigint;
cancelled_bookings: bigint;
no_show_host_bookings: bigint;
avg_rating: number | null;
total_ratings: bigint;
ratings_above_3: bigint;
no_show_guests: bigint;
}>
>(query);

const rawStats = stats[0];
return rawStats
? {
Expand Down Expand Up @@ -1136,15 +1156,7 @@ export class InsightsBookingBaseService {
async getRecentNoShowGuests() {
const baseConditions = await this.getBaseConditions();

const recentNoShowBookings = await this.prisma.$queryRaw<
Array<{
bookingId: number;
startTime: Date;
eventTypeName: string;
guestName: string;
guestEmail: string;
}>
>`
const query = Prisma.sql`
WITH booking_attendee_stats AS (
SELECT
b.id as booking_id,
Expand Down Expand Up @@ -1182,6 +1194,16 @@ export class InsightsBookingBaseService {
LIMIT 10
`;

const recentNoShowBookings = await this.prisma.$queryRaw<
Array<{
bookingId: number;
startTime: Date;
eventTypeName: string;
guestName: string;
guestEmail: string;
}>
>(query);

return recentNoShowBookings;
}

Expand Down
Loading
Loading