From c316721051a30771e715fae4a25abf9914a4bdbd Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 18:06:57 +0000 Subject: [PATCH] refactor: convert BookingRepository to use dependency injection pattern (#22389) * refactor: convert BookingRepository to use dependency injection pattern - Add constructor injection for PrismaClient to BookingRepository - Convert all static methods to instance methods using this.prismaClient - Update all usage sites to use two-step instantiation pattern: const bookingRepo = new BookingRepository(prisma); bookingRepo.method(...) - Apply same dependency injection pattern as UserRepository, TeamRepository, and SelectedSlotsRepository - Update test files to use correct prismaMock import paths - Maintain all existing functionality and type safety Files updated: - BookingRepository class structure and all 15 static methods - Video meeting pages and booking views - Booking utilities and services (handleNewBooking, originalRescheduledBookingUtils) - Round robin handlers and reassignment logic - Interval limits and booking limits checking - Test files with proper mocking setup Co-Authored-By: morgan@cal.com * chore: bump platform libs --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: morgan@cal.com --- apps/api/v2/package.json | 2 +- .../video/meeting-not-started/[uid]/page.tsx | 4 +- .../web/lib/video/[uid]/getServerSideProps.ts | 3 +- .../meeting-ended/[uid]/getServerSideProps.ts | 4 +- .../[uid]/getServerSideProps.ts | 4 +- ...ookings-single-view.getServerSideProps.tsx | 6 +- .../features/bookings/lib/handleNewBooking.ts | 3 +- .../originalRescheduledBookingUtils.ts | 4 +- .../roundRobinManualReassignment.test.ts | 5 +- .../roundRobinReassignment.test.ts | 5 +- packages/features/handleMarkNoShow.ts | 3 +- packages/lib/getBusyTimes.ts | 5 +- .../server/checkBookingLimits.ts | 3 +- .../server/getBusyTimesFromLimits.ts | 4 +- packages/lib/server/getLuckyUser.ts | 3 +- .../lib/server/repository/booking.test.ts | 21 ++-- packages/lib/server/repository/booking.ts | 107 +++++++++--------- .../trpc/server/routers/viewer/slots/util.ts | 8 +- .../roundRobinManualReassign.handler.ts | 4 +- .../roundRobin/roundRobinReassign.handler.ts | 4 +- yarn.lock | 10 +- 21 files changed, 124 insertions(+), 88 deletions(-) diff --git a/apps/api/v2/package.json b/apps/api/v2/package.json index 8e6fd564f8..9fb2b6f375 100644 --- a/apps/api/v2/package.json +++ b/apps/api/v2/package.json @@ -38,7 +38,7 @@ "@axiomhq/winston": "^1.2.0", "@calcom/platform-constants": "*", "@calcom/platform-enums": "*", - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.255", + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.256", "@calcom/platform-types": "*", "@calcom/platform-utils": "*", "@calcom/prisma": "*", diff --git a/apps/web/app/(use-page-wrapper)/video/meeting-not-started/[uid]/page.tsx b/apps/web/app/(use-page-wrapper)/video/meeting-not-started/[uid]/page.tsx index d938a1fb4c..bbfb461dd2 100644 --- a/apps/web/app/(use-page-wrapper)/video/meeting-not-started/[uid]/page.tsx +++ b/apps/web/app/(use-page-wrapper)/video/meeting-not-started/[uid]/page.tsx @@ -6,6 +6,7 @@ import { notFound } from "next/navigation"; import { z } from "zod"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import { prisma } from "@calcom/prisma"; import { buildLegacyCtx } from "@lib/buildLegacyCtx"; import { getServerSideProps } from "@lib/video/meeting-not-started/[uid]/getServerSideProps"; @@ -22,7 +23,8 @@ export const generateMetadata = async ({ params }: ServerPageProps) => { if (!parsed.success) { notFound(); } - const booking = await BookingRepository.findBookingByUid({ + const bookingRepo = new BookingRepository(prisma); + const booking = await bookingRepo.findBookingByUid({ bookingUid: parsed.data.uid, }); diff --git a/apps/web/lib/video/[uid]/getServerSideProps.ts b/apps/web/lib/video/[uid]/getServerSideProps.ts index e86d2a5205..ff71b8cf3e 100644 --- a/apps/web/lib/video/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/[uid]/getServerSideProps.ts @@ -106,7 +106,8 @@ const checkIfUserIsHost = async ({ export async function getServerSideProps(context: GetServerSidePropsContext) { const { req } = context; - const booking = await BookingRepository.findBookingForMeetingPage({ + const bookingRepo = new BookingRepository(prisma); + const booking = await bookingRepo.findBookingForMeetingPage({ bookingUid: context.query.uid as string, }); diff --git a/apps/web/lib/video/meeting-ended/[uid]/getServerSideProps.ts b/apps/web/lib/video/meeting-ended/[uid]/getServerSideProps.ts index 3aa4fc476c..bcdfeb3b6d 100644 --- a/apps/web/lib/video/meeting-ended/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/meeting-ended/[uid]/getServerSideProps.ts @@ -1,12 +1,14 @@ import type { GetServerSidePropsContext } from "next"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import { prisma } from "@calcom/prisma"; import { type inferSSRProps } from "@lib/types/inferSSRProps"; export type PageProps = inferSSRProps; export async function getServerSideProps(context: GetServerSidePropsContext) { - const booking = await BookingRepository.findBookingForMeetingEndedPage({ + const bookingRepo = new BookingRepository(prisma); + const booking = await bookingRepo.findBookingForMeetingEndedPage({ bookingUid: context.query.uid as string, }); diff --git a/apps/web/lib/video/meeting-not-started/[uid]/getServerSideProps.ts b/apps/web/lib/video/meeting-not-started/[uid]/getServerSideProps.ts index ce1e6d3a9c..aa66d8be6d 100644 --- a/apps/web/lib/video/meeting-not-started/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/meeting-not-started/[uid]/getServerSideProps.ts @@ -1,10 +1,12 @@ import type { GetServerSidePropsContext } from "next"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import { prisma } from "@calcom/prisma"; // change the type export async function getServerSideProps(context: GetServerSidePropsContext) { - const booking = await BookingRepository.findBookingByUid({ + const bookingRepo = new BookingRepository(prisma); + const booking = await bookingRepo.findBookingByUid({ bookingUid: context.query.uid as string, }); diff --git a/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx b/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx index 50fd5eb59b..41a4c31c39 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx @@ -77,7 +77,8 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { let rescheduledToUid: string | null = null; if (bookingInfo.rescheduled) { - const rescheduledTo = await BookingRepository.findFirstBookingByReschedule({ + const bookingRepo = new BookingRepository(prisma); + const rescheduledTo = await bookingRepo.findFirstBookingByReschedule({ originalBookingUid: bookingInfo.uid, }); rescheduledToUid = rescheduledTo?.uid ?? null; @@ -89,7 +90,8 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { } | null = null; if (bookingInfo.fromReschedule) { - previousBooking = await BookingRepository.findReschedulerByUid({ + const bookingRepo = new BookingRepository(prisma); + previousBooking = await bookingRepo.findReschedulerByUid({ uid: bookingInfo.fromReschedule, }); } diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index cfec551c89..417564da20 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -506,7 +506,8 @@ async function handler( (!isConfirmedByDefault && !userReschedulingIsOwner) || eventType.schedulingType === SchedulingType.ROUND_ROBIN ) { - const existingBooking = await BookingRepository.getValidBookingFromEventTypeForAttendee({ + const bookingRepo = new BookingRepository(prisma); + const existingBooking = await bookingRepo.getValidBookingFromEventTypeForAttendee({ eventTypeId, bookerEmail, bookerPhoneNumber, diff --git a/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts b/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts index 39256263d7..fc513f57dd 100644 --- a/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts +++ b/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts @@ -3,10 +3,12 @@ import type { Prisma } from "@prisma/client"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { HttpError } from "@calcom/lib/http-error"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import { prisma } from "@calcom/prisma"; import { BookingStatus } from "@calcom/prisma/enums"; export async function getOriginalRescheduledBooking(uid: string, seatsEventType?: boolean) { - const originalBooking = await BookingRepository.findOriginalRescheduledBooking(uid, seatsEventType); + const bookingRepo = new BookingRepository(prisma); + const originalBooking = await bookingRepo.findOriginalRescheduledBooking(uid, seatsEventType); if (!originalBooking) { throw new HttpError({ statusCode: 404, message: "Could not find original booking" }); diff --git a/packages/features/ee/round-robin/roundRobinManualReassignment.test.ts b/packages/features/ee/round-robin/roundRobinManualReassignment.test.ts index 9c3023c45b..385fa46a6a 100644 --- a/packages/features/ee/round-robin/roundRobinManualReassignment.test.ts +++ b/packages/features/ee/round-robin/roundRobinManualReassignment.test.ts @@ -1,3 +1,5 @@ +import prismaMock from "../../../../tests/libs/__mocks__/prisma"; + import { getDate, createBookingScenario, @@ -242,7 +244,8 @@ describe("roundRobinManualReassignment test", () => { userId: fixedHost.id, }); - const attendees = await BookingRepository.getBookingAttendees(123); + const bookingRepo = new BookingRepository(prismaMock); + const attendees = await bookingRepo.getBookingAttendees(123); expect(attendees.some((attendee) => attendee.email === currentRRHost.email)).toBe(false); expect(attendees.some((attendee) => attendee.email === newHost.email)).toBe(true); diff --git a/packages/features/ee/round-robin/roundRobinReassignment.test.ts b/packages/features/ee/round-robin/roundRobinReassignment.test.ts index 3a1a65747a..d849973410 100644 --- a/packages/features/ee/round-robin/roundRobinReassignment.test.ts +++ b/packages/features/ee/round-robin/roundRobinReassignment.test.ts @@ -1,3 +1,5 @@ +import prismaMock from "../../../../tests/libs/__mocks__/prisma"; + import { getDate, createBookingScenario, @@ -286,7 +288,8 @@ describe("roundRobinReassignment test", () => { userId: 1, }); - const attendees = await BookingRepository.getBookingAttendees(123); + const bookingRepo = new BookingRepository(prismaMock); + const attendees = await bookingRepo.getBookingAttendees(123); expect(attendees.some((attendee) => attendee.email === currentRRHost.email)).toBe(false); diff --git a/packages/features/handleMarkNoShow.ts b/packages/features/handleMarkNoShow.ts index fd09510301..764ba63b54 100644 --- a/packages/features/handleMarkNoShow.ts +++ b/packages/features/handleMarkNoShow.ts @@ -223,7 +223,8 @@ const getWebhooksService = async (bookingUid: string, platformClientId?: string) const assertCanAccessBooking = async (bookingUid: string, userId?: number) => { if (!userId) throw new HttpError({ statusCode: 401 }); - const booking = await BookingRepository.findBookingByUidAndUserId({ bookingUid, userId }); + const bookingRepo = new BookingRepository(prisma); + const booking = await bookingRepo.findBookingByUidAndUserId({ bookingUid, userId }); if (!booking) throw new HttpError({ statusCode: 403, message: "You are not allowed to access this booking" }); diff --git a/packages/lib/getBusyTimes.ts b/packages/lib/getBusyTimes.ts index 62107ab264..b14784c45e 100644 --- a/packages/lib/getBusyTimes.ts +++ b/packages/lib/getBusyTimes.ts @@ -18,7 +18,7 @@ import type { EventBusyDetails } from "@calcom/types/Calendar"; import type { CredentialForCalendarService } from "@calcom/types/Credential"; import { getDefinedBufferTimes } from "../features/eventtypes/lib/getDefinedBufferTimes"; -import { BookingRepository as BookingRepo } from "./server/repository/booking"; +import { BookingRepository } from "./server/repository/booking"; const _getBusyTimes = async (params: { credentials: CredentialForCalendarService[]; @@ -108,7 +108,8 @@ const _getBusyTimes = async (params: { let bookings = params.currentBookings; if (!bookings) { - bookings = await BookingRepo.findAllExistingBookingsForEventTypeBetween({ + const bookingRepo = new BookingRepository(prisma); + bookings = await bookingRepo.findAllExistingBookingsForEventTypeBetween({ userIdAndEmailMap: new Map([[userId, userEmail]]), eventTypeId, startDate: startTimeAdjustedWithMaxBuffer, diff --git a/packages/lib/intervalLimits/server/checkBookingLimits.ts b/packages/lib/intervalLimits/server/checkBookingLimits.ts index e69f60ce23..d9265e83c4 100644 --- a/packages/lib/intervalLimits/server/checkBookingLimits.ts +++ b/packages/lib/intervalLimits/server/checkBookingLimits.ts @@ -77,7 +77,8 @@ async function _checkBookingLimit({ let bookingsInPeriod; if (teamId && user) { - bookingsInPeriod = await BookingRepository.getAllAcceptedTeamBookingsOfUser({ + const bookingRepo = new BookingRepository(prisma); + bookingsInPeriod = await bookingRepo.getAllAcceptedTeamBookingsOfUser({ user: { id: user.id, email: user.email }, teamId, startDate: startDate, diff --git a/packages/lib/intervalLimits/server/getBusyTimesFromLimits.ts b/packages/lib/intervalLimits/server/getBusyTimesFromLimits.ts index f87261f34d..a3fecdbe99 100644 --- a/packages/lib/intervalLimits/server/getBusyTimesFromLimits.ts +++ b/packages/lib/intervalLimits/server/getBusyTimesFromLimits.ts @@ -7,6 +7,7 @@ import { withReporting } from "@calcom/lib/sentryWrapper"; import { performance } from "@calcom/lib/server/perfObserver"; import { getTotalBookingDuration } from "@calcom/lib/server/queries/booking"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import prisma from "@calcom/prisma"; import type { EventBusyDetails } from "@calcom/types/Calendar"; import { descendingLimitKeys, intervalLimitKeyToUnit } from "../intervalLimit"; @@ -233,7 +234,8 @@ const _getBusyTimesFromTeamLimits = async ( bookingLimits ); - const bookings = await BookingRepository.getAllAcceptedTeamBookingsOfUser({ + const bookingRepo = new BookingRepository(prisma); + const bookings = await bookingRepo.getAllAcceptedTeamBookingsOfUser({ user, teamId, startDate: limitDateFrom.toDate(), diff --git a/packages/lib/server/getLuckyUser.ts b/packages/lib/server/getLuckyUser.ts index 215ba54255..25354d5399 100644 --- a/packages/lib/server/getLuckyUser.ts +++ b/packages/lib/server/getLuckyUser.ts @@ -490,7 +490,8 @@ async function getBookingsOfInterval({ rrTimestampBasis: RRTimestampBasis; meetingStartTime?: Date; }) { - return await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prisma); + return await bookingRepo.getAllBookingsForRoundRobin({ eventTypeId: eventTypeId, users, startDate: getIntervalStartDate({ interval, rrTimestampBasis, meetingStartTime }), diff --git a/packages/lib/server/repository/booking.test.ts b/packages/lib/server/repository/booking.test.ts index de3719cfc9..4ca0f192f2 100644 --- a/packages/lib/server/repository/booking.test.ts +++ b/packages/lib/server/repository/booking.test.ts @@ -104,7 +104,8 @@ describe("BookingRepository", () => { it("it should not include bookings where the attendee is a no show", async () => { await createAttendeeNoShowTestBookings(); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date(), @@ -118,7 +119,8 @@ describe("BookingRepository", () => { it("it should include bookings where the attendee is a no show", async () => { await createAttendeeNoShowTestBookings(); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date(), @@ -132,7 +134,8 @@ describe("BookingRepository", () => { it("it should not include bookings where the host is a no show", async () => { await createHostNoShowTestBookings(); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date(), @@ -146,7 +149,8 @@ describe("BookingRepository", () => { it("it should include bookings where the host is a no show", async () => { await createHostNoShowTestBookings(); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date(), @@ -161,7 +165,8 @@ describe("BookingRepository", () => { await createHostNoShowTestBookings(); await createAttendeeNoShowTestBookings(); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date(), @@ -176,7 +181,8 @@ describe("BookingRepository", () => { await createHostNoShowTestBookings(); await createAttendeeNoShowTestBookings(); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date(), @@ -232,7 +238,8 @@ describe("BookingRepository", () => { }), ]); - const bookings = await BookingRepository.getAllBookingsForRoundRobin({ + const bookingRepo = new BookingRepository(prismaMock); + const bookings = await bookingRepo.getAllBookingsForRoundRobin({ users: [{ id: 1, email: "organizer1@example.com" }], eventTypeId: 1, startDate: new Date("2025-06-01T00:00:00.000Z"), diff --git a/packages/lib/server/repository/booking.ts b/packages/lib/server/repository/booking.ts index 11042c63d4..2de6d33462 100644 --- a/packages/lib/server/repository/booking.ts +++ b/packages/lib/server/repository/booking.ts @@ -2,7 +2,8 @@ import type { Prisma } from "@prisma/client"; import type { FormResponse } from "@calcom/app-store/routing-forms/types/types"; import { withReporting } from "@calcom/lib/sentryWrapper"; -import prisma, { bookingMinimalSelect } from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; +import { bookingMinimalSelect } from "@calcom/prisma"; import type { Booking } from "@calcom/prisma/client"; import { RRTimestampBasis } from "@calcom/prisma/enums"; import { BookingStatus } from "@calcom/prisma/enums"; @@ -113,8 +114,10 @@ const buildWhereClauseForActiveBookings = ({ }); export class BookingRepository { - static async getBookingAttendees(bookingId: number) { - return await prisma.attendee.findMany({ + constructor(private prismaClient: PrismaClient) {} + + async getBookingAttendees(bookingId: number) { + return await this.prismaClient.attendee.findMany({ where: { bookingId, }, @@ -122,8 +125,8 @@ export class BookingRepository { } /** Determines if the user is the organizer, team admin, or org admin that the booking was created under */ - static async doesUserIdHaveAccessToBooking({ userId, bookingId }: { userId: number; bookingId: number }) { - const booking = await prisma.booking.findUnique({ + async doesUserIdHaveAccessToBooking({ userId, bookingId }: { userId: number; bookingId: number }) { + const booking = await this.prismaClient.booking.findUnique({ where: { id: bookingId, }, @@ -145,7 +148,7 @@ export class BookingRepository { if (!booking.eventType || !booking.eventType.teamId) return false; // TODO add checks for team and org - const userRepo = new UserRepository(prisma); + const userRepo = new UserRepository(this.prismaClient); const isAdminOrUser = await userRepo.isAdminOfTeamOrParentOrg({ userId, teamId: booking.eventType.teamId, @@ -154,8 +157,8 @@ export class BookingRepository { return isAdminOrUser; } - static async findFirstBookingByReschedule({ originalBookingUid }: { originalBookingUid: string }) { - return await prisma.booking.findFirst({ + async findFirstBookingByReschedule({ originalBookingUid }: { originalBookingUid: string }) { + return await this.prismaClient.booking.findFirst({ where: { fromReschedule: originalBookingUid, }, @@ -165,8 +168,8 @@ export class BookingRepository { }); } - static async findReschedulerByUid({ uid }: { uid: string }) { - return await prisma.booking.findUnique({ + async findReschedulerByUid({ uid }: { uid: string }) { + return await this.prismaClient.booking.findUnique({ where: { uid, }, @@ -177,7 +180,7 @@ export class BookingRepository { }); } - private static async _findAllExistingBookingsForEventTypeBetween({ + private async _findAllExistingBookingsForEventTypeBetween({ eventTypeId, seatedEvent = false, startDate, @@ -228,7 +231,7 @@ export class BookingRepository { }), } satisfies Prisma.BookingSelect; - const currentBookingsAllUsersQueryOne = prisma.booking.findMany({ + const currentBookingsAllUsersQueryOne = this.prismaClient.booking.findMany({ where: { ...sharedQuery, userId: { @@ -238,7 +241,7 @@ export class BookingRepository { select: bookingsSelect, }); - const currentBookingsAllUsersQueryTwo = prisma.booking.findMany({ + const currentBookingsAllUsersQueryTwo = this.prismaClient.booking.findMany({ where: { ...sharedQuery, attendees: { @@ -253,7 +256,7 @@ export class BookingRepository { }); const currentBookingsAllUsersQueryThree = eventTypeId - ? prisma.booking.findMany({ + ? this.prismaClient.booking.findMany({ where: { startTime: { lte: endDate }, endTime: { gte: startDate }, @@ -289,12 +292,12 @@ export class BookingRepository { return [...resultOne, ...resultTwoWithOrganizersRemoved, ...resultThree]; } - static findAllExistingBookingsForEventTypeBetween = withReporting( - BookingRepository._findAllExistingBookingsForEventTypeBetween, + findAllExistingBookingsForEventTypeBetween = withReporting( + this._findAllExistingBookingsForEventTypeBetween.bind(this), "findAllExistingBookingsForEventTypeBetween" ); - static async getAllBookingsForRoundRobin({ + async getAllBookingsForRoundRobin({ users, eventTypeId, startDate, @@ -317,7 +320,7 @@ export class BookingRepository { includeNoShowInRRCalculation: boolean; rrTimestampBasis: RRTimestampBasis; }) { - const allBookings = await prisma.booking.findMany({ + const allBookings = await this.prismaClient.booking.findMany({ where: buildWhereClauseForActiveBookings({ eventTypeId, startDate, @@ -367,8 +370,8 @@ export class BookingRepository { return queueBookings; } - static async findBookingByUid({ bookingUid }: { bookingUid: string }) { - return await prisma.booking.findUnique({ + async findBookingByUid({ bookingUid }: { bookingUid: string }) { + return await this.prismaClient.booking.findUnique({ where: { uid: bookingUid, }, @@ -376,8 +379,8 @@ export class BookingRepository { }); } - static async findBookingForMeetingPage({ bookingUid }: { bookingUid: string }) { - return await prisma.booking.findUnique({ + async findBookingForMeetingPage({ bookingUid }: { bookingUid: string }) { + return await this.prismaClient.booking.findUnique({ where: { uid: bookingUid, }, @@ -431,8 +434,8 @@ export class BookingRepository { }); } - static async findBookingForMeetingEndedPage({ bookingUid }: { bookingUid: string }) { - return await prisma.booking.findUnique({ + async findBookingForMeetingEndedPage({ bookingUid }: { bookingUid: string }) { + return await this.prismaClient.booking.findUnique({ where: { uid: bookingUid, }, @@ -455,8 +458,8 @@ export class BookingRepository { }); } - static async findBookingByUidAndUserId({ bookingUid, userId }: { bookingUid: string; userId: number }) { - return await prisma.booking.findFirst({ + async findBookingByUidAndUserId({ bookingUid, userId }: { bookingUid: string; userId: number }) { + return await this.prismaClient.booking.findFirst({ where: { uid: bookingUid, OR: [ @@ -516,7 +519,7 @@ export class BookingRepository { }); } - static async updateLocationById({ + async updateLocationById({ where: { id }, data: { location, metadata, referencesToCreate }, }: { @@ -527,7 +530,7 @@ export class BookingRepository { referencesToCreate: Prisma.BookingReferenceCreateInput[]; }; }) { - await prisma.booking.update({ + await this.prismaClient.booking.update({ where: { id, }, @@ -541,13 +544,11 @@ export class BookingRepository { }); } - static async getAllAcceptedTeamBookingsOfUser(params: TeamBookingsParamsWithCount): Promise; + async getAllAcceptedTeamBookingsOfUser(params: TeamBookingsParamsWithCount): Promise; - static async getAllAcceptedTeamBookingsOfUser( - params: TeamBookingsParamsWithoutCount - ): Promise>; + async getAllAcceptedTeamBookingsOfUser(params: TeamBookingsParamsWithoutCount): Promise>; - static async getAllAcceptedTeamBookingsOfUser(params: TeamBookingsParamsBase) { + async getAllAcceptedTeamBookingsOfUser(params: TeamBookingsParamsBase) { const { user, teamId, startDate, endDate, excludedUid, shouldReturnCount, includeManagedEvents } = params; const baseWhere: Prisma.BookingWhereInput = { @@ -596,18 +597,18 @@ export class BookingRepository { }; if (shouldReturnCount) { - const collectiveRoundRobinBookingsOwner = await prisma.booking.count({ + const collectiveRoundRobinBookingsOwner = await this.prismaClient.booking.count({ where: whereCollectiveRoundRobinOwner, }); - const collectiveRoundRobinBookingsAttendee = await prisma.booking.count({ + const collectiveRoundRobinBookingsAttendee = await this.prismaClient.booking.count({ where: whereCollectiveRoundRobinBookingsAttendee, }); let managedBookings = 0; if (includeManagedEvents) { - managedBookings = await prisma.booking.count({ + managedBookings = await this.prismaClient.booking.count({ where: whereManagedBookings, }); } @@ -617,18 +618,18 @@ export class BookingRepository { return totalNrOfBooking; } - const collectiveRoundRobinBookingsOwner = await prisma.booking.findMany({ + const collectiveRoundRobinBookingsOwner = await this.prismaClient.booking.findMany({ where: whereCollectiveRoundRobinOwner, }); - const collectiveRoundRobinBookingsAttendee = await prisma.booking.findMany({ + const collectiveRoundRobinBookingsAttendee = await this.prismaClient.booking.findMany({ where: whereCollectiveRoundRobinBookingsAttendee, }); let managedBookings: typeof collectiveRoundRobinBookingsAttendee = []; if (includeManagedEvents) { - managedBookings = await prisma.booking.findMany({ + managedBookings = await this.prismaClient.booking.findMany({ where: whereManagedBookings, }); } @@ -640,8 +641,8 @@ export class BookingRepository { ]; } - static async findOriginalRescheduledBooking(uid: string, seatsEventType?: boolean) { - return await prisma.booking.findFirst({ + async findOriginalRescheduledBooking(uid: string, seatsEventType?: boolean) { + return await this.prismaClient.booking.findFirst({ where: { uid: uid, status: { @@ -693,15 +694,13 @@ export class BookingRepository { }); } - static async getAllAcceptedTeamBookingsOfUsers( - params: TeamBookingsMultipleUsersParamsWithCount - ): Promise; + async getAllAcceptedTeamBookingsOfUsers(params: TeamBookingsMultipleUsersParamsWithCount): Promise; - static async getAllAcceptedTeamBookingsOfUsers( + async getAllAcceptedTeamBookingsOfUsers( params: TeamBookingsMultipleUsersParamsWithoutCount ): Promise>; - static async getAllAcceptedTeamBookingsOfUsers(params: TeamBookingsMultipleUsersParamsBase) { + async getAllAcceptedTeamBookingsOfUsers(params: TeamBookingsMultipleUsersParamsBase) { const { users, teamId, startDate, endDate, excludedUid, shouldReturnCount, includeManagedEvents } = params; @@ -760,18 +759,18 @@ export class BookingRepository { }; if (shouldReturnCount) { - const collectiveRoundRobinBookingsOwner = await prisma.booking.count({ + const collectiveRoundRobinBookingsOwner = await this.prismaClient.booking.count({ where: whereCollectiveRoundRobinOwner, }); - const collectiveRoundRobinBookingsAttendee = await prisma.booking.count({ + const collectiveRoundRobinBookingsAttendee = await this.prismaClient.booking.count({ where: whereCollectiveRoundRobinBookingsAttendee, }); let managedBookings = 0; if (includeManagedEvents) { - managedBookings = await prisma.booking.count({ + managedBookings = await this.prismaClient.booking.count({ where: whereManagedBookings, }); } @@ -782,18 +781,18 @@ export class BookingRepository { return totalNrOfBooking; } - const collectiveRoundRobinBookingsOwner = await prisma.booking.findMany({ + const collectiveRoundRobinBookingsOwner = await this.prismaClient.booking.findMany({ where: whereCollectiveRoundRobinOwner, }); - const collectiveRoundRobinBookingsAttendee = await prisma.booking.findMany({ + const collectiveRoundRobinBookingsAttendee = await this.prismaClient.booking.findMany({ where: whereCollectiveRoundRobinBookingsAttendee, }); let managedBookings: typeof collectiveRoundRobinBookingsAttendee = []; if (includeManagedEvents) { - managedBookings = await prisma.booking.findMany({ + managedBookings = await this.prismaClient.booking.findMany({ where: whereManagedBookings, }); } @@ -805,7 +804,7 @@ export class BookingRepository { ]; } - static async getValidBookingFromEventTypeForAttendee({ + async getValidBookingFromEventTypeForAttendee({ eventTypeId, bookerEmail, bookerPhoneNumber, @@ -818,7 +817,7 @@ export class BookingRepository { startTime: Date; filterForUnconfirmed?: boolean; }) { - return await prisma.booking.findFirst({ + return await this.prismaClient.booking.findFirst({ where: { eventTypeId, attendees: { diff --git a/packages/trpc/server/routers/viewer/slots/util.ts b/packages/trpc/server/routers/viewer/slots/util.ts index 492891a482..d5be18837f 100644 --- a/packages/trpc/server/routers/viewer/slots/util.ts +++ b/packages/trpc/server/routers/viewer/slots/util.ts @@ -41,7 +41,7 @@ import { isRestrictionScheduleEnabled } from "@calcom/lib/restrictionSchedule"; import { safeStringify } from "@calcom/lib/safeStringify"; import { withReporting } from "@calcom/lib/sentryWrapper"; import { getTotalBookingDuration } from "@calcom/lib/server/queries/booking"; -import { BookingRepository as BookingRepo } from "@calcom/lib/server/repository/booking"; +import { BookingRepository } from "@calcom/lib/server/repository/booking"; import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import { RoutingFormResponseRepository } from "@calcom/lib/server/repository/formResponse"; import type { PrismaOOORepository } from "@calcom/lib/server/repository/ooo"; @@ -506,7 +506,8 @@ export class AvailableSlotsService { bookingLimits ); - const bookings = await BookingRepo.getAllAcceptedTeamBookingsOfUsers({ + const bookingRepo = new BookingRepository(prisma); + const bookings = await bookingRepo.getAllAcceptedTeamBookingsOfUsers({ users, teamId, startDate: limitDateFrom.toDate(), @@ -708,8 +709,9 @@ export class AvailableSlotsService { const userIdAndEmailMap = new Map(usersWithCredentials.map((user) => [user.id, user.email])); const allUserIds = Array.from(userIdAndEmailMap.keys()); + const bookingRepo = new BookingRepository(prisma); const [currentBookingsAllUsers, outOfOfficeDaysAllUsers] = await Promise.all([ - BookingRepo.findAllExistingBookingsForEventTypeBetween({ + bookingRepo.findAllExistingBookingsForEventTypeBetween({ startDate: startTimeDate, endDate: endTimeDate, eventTypeId: eventType.id, diff --git a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts index 360ea536c4..f1f26b48fe 100644 --- a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts @@ -1,5 +1,6 @@ import { roundRobinManualReassignment } from "@calcom/features/ee/round-robin/roundRobinManualReassignment"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; import { TRPCError } from "@trpc/server"; @@ -17,7 +18,8 @@ export const roundRobinManualReassignHandler = async ({ ctx, input }: RoundRobin const { bookingId, teamMemberId, reassignReason } = input; // Check if user has access to change booking - const isAllowed = await BookingRepository.doesUserIdHaveAccessToBooking({ userId: ctx.user.id, bookingId }); + const bookingRepo = new BookingRepository(prisma); + const isAllowed = await bookingRepo.doesUserIdHaveAccessToBooking({ userId: ctx.user.id, bookingId }); if (!isAllowed) { throw new TRPCError({ code: "FORBIDDEN", message: "You do not have permission" }); diff --git a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts index 75ff43465d..4e49dbc385 100644 --- a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts @@ -1,5 +1,6 @@ import { roundRobinReassignment } from "@calcom/features/ee/round-robin/roundRobinReassignment"; import { BookingRepository } from "@calcom/lib/server/repository/booking"; +import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; import { TRPCError } from "@trpc/server"; @@ -17,7 +18,8 @@ export const roundRobinReassignHandler = async ({ ctx, input }: RoundRobinReassi const { bookingId } = input; // Check if user has access to change booking - const isAllowed = await BookingRepository.doesUserIdHaveAccessToBooking({ userId: ctx.user.id, bookingId }); + const bookingRepo = new BookingRepository(prisma); + const isAllowed = await bookingRepo.doesUserIdHaveAccessToBooking({ userId: ctx.user.id, bookingId }); if (!isAllowed) { throw new TRPCError({ code: "FORBIDDEN", message: "You do not have permission" }); diff --git a/yarn.lock b/yarn.lock index 191cf46544..b34d25667a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2519,7 +2519,7 @@ __metadata: "@axiomhq/winston": ^1.2.0 "@calcom/platform-constants": "*" "@calcom/platform-enums": "*" - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.255" + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.256" "@calcom/platform-types": "*" "@calcom/platform-utils": "*" "@calcom/prisma": "*" @@ -3565,13 +3565,13 @@ __metadata: languageName: unknown linkType: soft -"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.255": - version: 0.0.255 - resolution: "@calcom/platform-libraries@npm:0.0.255" +"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.256": + version: 0.0.256 + resolution: "@calcom/platform-libraries@npm:0.0.256" dependencies: "@calcom/features": "*" "@calcom/lib": "*" - checksum: 50ec08f31a1a30fde270335f93065554ff93d74ab96d059262cec44f9efcae2036c2a7c26177cb3a1a2f708dabea4736b26110629ab08691e97a62f9d3464cd9 + checksum: 4c0b238ce803f7c660803bfcf4bc90435aef76a2efd1a476c10755a57e720354c739e88e3eaf44b176369750b211f81fc4a83f3eea452bac1d512bbf808a1085 languageName: node linkType: hard