diff --git a/apps/api/v2/src/ee/schedules/schedules_2024_04_15/schedules.module.ts b/apps/api/v2/src/ee/schedules/schedules_2024_04_15/schedules.module.ts index c6564123a5..8a8f7d4e0e 100644 --- a/apps/api/v2/src/ee/schedules/schedules_2024_04_15/schedules.module.ts +++ b/apps/api/v2/src/ee/schedules/schedules_2024_04_15/schedules.module.ts @@ -1,6 +1,7 @@ import { SchedulesController_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/controllers/schedules.controller"; import { SchedulesRepository_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.repository"; import { SchedulesService_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/services/schedules.service"; +import { PrismaScheduleRepository } from "@/lib/repositories/prisma-schedule.repository"; import { PrismaModule } from "@/modules/prisma/prisma.module"; import { TokensModule } from "@/modules/tokens/tokens.module"; import { UsersModule } from "@/modules/users/users.module"; @@ -8,7 +9,7 @@ import { Module } from "@nestjs/common"; @Module({ imports: [PrismaModule, UsersModule, TokensModule], - providers: [SchedulesRepository_2024_04_15, SchedulesService_2024_04_15], + providers: [SchedulesRepository_2024_04_15, SchedulesService_2024_04_15, PrismaScheduleRepository], controllers: [SchedulesController_2024_04_15], exports: [SchedulesService_2024_04_15, SchedulesRepository_2024_04_15], }) diff --git a/apps/api/v2/src/ee/schedules/schedules_2024_04_15/services/schedules.service.ts b/apps/api/v2/src/ee/schedules/schedules_2024_04_15/services/schedules.service.ts index 955af10901..5980a8243a 100644 --- a/apps/api/v2/src/ee/schedules/schedules_2024_04_15/services/schedules.service.ts +++ b/apps/api/v2/src/ee/schedules/schedules_2024_04_15/services/schedules.service.ts @@ -1,12 +1,12 @@ import { CreateAvailabilityInput_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/inputs/create-availability.input"; import { CreateScheduleInput_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/inputs/create-schedule.input"; import { SchedulesRepository_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.repository"; +import { PrismaScheduleRepository } from "@/lib/repositories/prisma-schedule.repository"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { UserWithProfile, UsersRepository } from "@/modules/users/users.repository"; import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; import { updateSchedule } from "@calcom/platform-libraries/schedules"; -import { ScheduleRepository } from "@calcom/platform-libraries/schedules"; import type { UpdateScheduleInput_2024_04_15 } from "@calcom/platform-types"; import type { PrismaClient } from "@calcom/prisma"; import type { Schedule } from "@calcom/prisma/client"; @@ -16,7 +16,8 @@ export class SchedulesService_2024_04_15 { constructor( private readonly schedulesRepository: SchedulesRepository_2024_04_15, private readonly usersRepository: UsersRepository, - private readonly dbWrite: PrismaWriteService + private readonly dbWrite: PrismaWriteService, + private readonly prismaScheduleRepository: PrismaScheduleRepository ) {} async createUserDefaultSchedule(userId: number, timeZone: string) { @@ -53,8 +54,7 @@ export class SchedulesService_2024_04_15 { const user = await this.usersRepository.findById(userId); if (!user?.defaultScheduleId) return null; - - return await ScheduleRepository.findDetailedScheduleById({ + return await this.prismaScheduleRepository.findDetailedScheduleById({ scheduleId: user.defaultScheduleId, isManagedEventType: undefined, userId, @@ -70,7 +70,7 @@ export class SchedulesService_2024_04_15 { throw new NotFoundException(`User with ID=${userId} does not exist.`); } - const existingSchedule = await ScheduleRepository.findDetailedScheduleById({ + const existingSchedule = await this.prismaScheduleRepository.findDetailedScheduleById({ scheduleId: scheduleId, isManagedEventType: undefined, userId, @@ -88,7 +88,11 @@ export class SchedulesService_2024_04_15 { } async getUserSchedules(userId: number, timeZone: string, defaultScheduleId: number | null) { - return ScheduleRepository.findManyDetailedScheduleByUserId({ userId, timeZone, defaultScheduleId }); + return this.prismaScheduleRepository.findManyDetailedScheduleByUserId({ + userId, + timeZone, + defaultScheduleId, + }); } async updateUserSchedule( diff --git a/apps/api/v2/src/modules/atoms/services/schedules-atom.service.ts b/apps/api/v2/src/modules/atoms/services/schedules-atom.service.ts index ff7184961a..dc27f41930 100644 --- a/apps/api/v2/src/modules/atoms/services/schedules-atom.service.ts +++ b/apps/api/v2/src/modules/atoms/services/schedules-atom.service.ts @@ -32,8 +32,8 @@ export class SchedulesAtomsService { const user = await this.usersRepository.findById(userId); if (!user?.defaultScheduleId) return null; - - return await ScheduleRepository.findDetailedScheduleById({ + const scheduleRepo = new ScheduleRepository(this.dbWrite.prisma as unknown as PrismaClient); + return await scheduleRepo.findDetailedScheduleById({ scheduleId: scheduleId ?? user.defaultScheduleId, isManagedEventType, userId, diff --git a/apps/web/app/api/cron/changeTimeZone/route.ts b/apps/web/app/api/cron/changeTimeZone/route.ts index 4df162c498..5b87f427b9 100644 --- a/apps/web/app/api/cron/changeTimeZone/route.ts +++ b/apps/web/app/api/cron/changeTimeZone/route.ts @@ -3,8 +3,8 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; import dayjs from "@calcom/dayjs"; +import { ScheduleRepository } from "@calcom/features/schedules/repositories/ScheduleRepository"; import prisma from "@calcom/prisma"; -import { getDefaultScheduleId } from "@calcom/trpc/server/routers/viewer/availability/util"; const travelScheduleSelect = { id: true, @@ -40,7 +40,8 @@ async function postHandler(request: NextRequest) { }, }); - const defaultScheduleId = await getDefaultScheduleId(user.id, prisma); + const scheduleRepository = new ScheduleRepository(prisma); + const defaultScheduleId = await scheduleRepository.getDefaultScheduleId(user.id); if (!user.defaultScheduleId) { // set default schedule if not already set diff --git a/packages/trpc/server/routers/viewer/availability/util.test.ts b/packages/features/schedules/repositories/ScheduleRepository.test.ts similarity index 63% rename from packages/trpc/server/routers/viewer/availability/util.test.ts rename to packages/features/schedules/repositories/ScheduleRepository.test.ts index 19f88e508d..9d383e99b3 100644 --- a/packages/trpc/server/routers/viewer/availability/util.test.ts +++ b/packages/features/schedules/repositories/ScheduleRepository.test.ts @@ -1,9 +1,8 @@ import { describe, expect, it, vi, beforeEach } from "vitest"; -import { HostRepository } from "@calcom/lib/server/repository/host"; import { PrismaClient } from "@calcom/prisma"; -import { getDefaultScheduleId, hasDefaultSchedule, setupDefaultSchedule } from "./util"; +import { ScheduleRepository } from "./ScheduleRepository"; vi.mock("@calcom/prisma", () => { const mockPrisma = { @@ -14,9 +13,6 @@ vi.mock("@calcom/prisma", () => { schedule: { findFirst: vi.fn(), }, - host: { - updateMany: vi.fn(), - }, }; return { __esModule: true, @@ -25,16 +21,36 @@ vi.mock("@calcom/prisma", () => { }; }); -describe("Availability Utils", () => { +vi.mock("@calcom/lib/hasEditPermissionForUser", () => ({ + hasReadPermissionsForUserId: vi.fn().mockResolvedValue(true), +})); + +describe("ScheduleRepository", () => { let prisma: PrismaClient; - let hostRepo: HostRepository; + let scheduleRepository: ScheduleRepository; beforeEach(() => { prisma = new PrismaClient(); - hostRepo = new HostRepository(prisma); + scheduleRepository = new ScheduleRepository(prisma); vi.clearAllMocks(); }); + describe("constructor", () => { + it("should throw error if prismaClient is not provided", () => { + expect(() => new ScheduleRepository(null as any)).toThrow( + "PrismaClient is required for ScheduleRepository" + ); + expect(() => new ScheduleRepository(undefined as any)).toThrow( + "PrismaClient is required for ScheduleRepository" + ); + }); + + it("should create instance successfully with valid prismaClient", () => { + const repo = new ScheduleRepository(prisma); + expect(repo).toBeInstanceOf(ScheduleRepository); + }); + }); + describe("getDefaultScheduleId", () => { it("should return defaultScheduleId if user has one", async () => { const userId = 1; @@ -44,7 +60,7 @@ describe("Availability Utils", () => { defaultScheduleId, }); - const result = await getDefaultScheduleId(userId, prisma); + const result = await scheduleRepository.getDefaultScheduleId(userId); expect(prisma.user.findUnique).toHaveBeenCalledWith({ where: { id: userId }, @@ -65,7 +81,7 @@ describe("Availability Utils", () => { id: scheduleId, }); - const result = await getDefaultScheduleId(userId, prisma); + const result = await scheduleRepository.getDefaultScheduleId(userId); expect(prisma.user.findUnique).toHaveBeenCalledWith({ where: { id: userId }, @@ -87,7 +103,9 @@ describe("Availability Utils", () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any (prisma.schedule.findFirst as any).mockResolvedValue(null); - await expect(getDefaultScheduleId(userId, prisma)).rejects.toThrow("No schedules found for user"); + await expect(scheduleRepository.getDefaultScheduleId(userId)).rejects.toThrow( + "No schedules found for user" + ); }); }); @@ -95,7 +113,7 @@ describe("Availability Utils", () => { it("should return true if user has defaultScheduleId", async () => { const user = { id: 1, defaultScheduleId: 123 }; - const result = await hasDefaultSchedule(user, prisma); + const result = await scheduleRepository.hasDefaultSchedule(user); expect(result).toBe(true); }); @@ -107,7 +125,7 @@ describe("Availability Utils", () => { id: 456, }); - const result = await hasDefaultSchedule(user, prisma); + const result = await scheduleRepository.hasDefaultSchedule(user); expect(prisma.schedule.findFirst).toHaveBeenCalledWith({ where: { userId: user.id }, @@ -120,7 +138,7 @@ describe("Availability Utils", () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any (prisma.schedule.findFirst as any).mockResolvedValue(null); - const result = await hasDefaultSchedule(user, prisma); + const result = await scheduleRepository.hasDefaultSchedule(user); expect(prisma.schedule.findFirst).toHaveBeenCalledWith({ where: { userId: user.id }, @@ -137,7 +155,7 @@ describe("Availability Utils", () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any (prisma.user.update as any).mockResolvedValue(updatedUser); - const result = await setupDefaultSchedule(userId, scheduleId, prisma); + const result = await scheduleRepository.setupDefaultSchedule(userId, scheduleId); expect(prisma.user.update).toHaveBeenCalledWith({ where: { id: userId }, @@ -146,50 +164,4 @@ describe("Availability Utils", () => { expect(result).toEqual(updatedUser); }); }); - - describe("updateHostsWithNewDefaultSchedule", () => { - it("should update hosts with new scheduleId", async () => { - const userId = 1; - const oldScheduleId = 123; - const newScheduleId = 456; - const updateResult = { count: 2 }; // 2 hosts updated - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (prisma.host.updateMany as any).mockResolvedValue(updateResult); - - const result = await hostRepo.updateHostsSchedule(userId, oldScheduleId, newScheduleId); - - expect(prisma.host.updateMany).toHaveBeenCalledWith({ - where: { - userId, - scheduleId: oldScheduleId, - }, - data: { - scheduleId: newScheduleId, - }, - }); - expect(result).toEqual(updateResult); - }); - - it("should handle case with no hosts to update", async () => { - const userId = 1; - const oldScheduleId = 123; - const newScheduleId = 456; - const updateResult = { count: 0 }; // No hosts updated - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (prisma.host.updateMany as any).mockResolvedValue(updateResult); - - const result = await hostRepo.updateHostsSchedule(userId, oldScheduleId, newScheduleId); - - expect(prisma.host.updateMany).toHaveBeenCalledWith({ - where: { - userId, - scheduleId: oldScheduleId, - }, - data: { - scheduleId: newScheduleId, - }, - }); - expect(result).toEqual(updateResult); - }); - }); }); diff --git a/packages/features/schedules/repositories/ScheduleRepository.ts b/packages/features/schedules/repositories/ScheduleRepository.ts index 4d25018f81..41de2f09af 100644 --- a/packages/features/schedules/repositories/ScheduleRepository.ts +++ b/packages/features/schedules/repositories/ScheduleRepository.ts @@ -5,16 +5,19 @@ import { transformWorkingHoursForAtom, } from "@calcom/lib/schedules/transformers"; import type { PrismaClient } from "@calcom/prisma"; -import prisma from "@calcom/prisma"; -import { getDefaultScheduleId } from "@calcom/trpc/server/routers/viewer/availability/util"; +import type { User } from "@calcom/prisma/client"; export type FindDetailedScheduleByIdReturnType = Awaited< - ReturnType + ReturnType >; export class ScheduleRepository { // when instantiating, prismaClient injection is required - constructor(private prismaClient: PrismaClient) {} + constructor(private readonly prismaClient: PrismaClient) { + if (!prismaClient) { + throw new Error("PrismaClient is required for ScheduleRepository"); + } + } async findScheduleByIdForBuildDateRanges({ scheduleId }: { scheduleId: number }) { const schedule = await this.prismaClient.schedule.findUnique({ @@ -63,8 +66,8 @@ export class ScheduleRepository { return schedule; } - static async findScheduleById({ id }: { id: number }) { - const schedule = await prisma.schedule.findUnique({ + async findScheduleById({ id }: { id: number }) { + const schedule = await this.prismaClient.schedule.findUnique({ where: { id, }, @@ -80,7 +83,7 @@ export class ScheduleRepository { return schedule; } - static async findDetailedScheduleById({ + async findDetailedScheduleById({ isManagedEventType, scheduleId, userId, @@ -93,9 +96,9 @@ export class ScheduleRepository { scheduleId?: number; isManagedEventType?: boolean; }) { - const schedule = await prisma.schedule.findUnique({ + const schedule = await this.prismaClient.schedule.findUnique({ where: { - id: scheduleId || (await getDefaultScheduleId(userId, prisma)), + id: scheduleId || (await this.getDefaultScheduleId(userId)), }, select: { id: true, @@ -119,7 +122,7 @@ export class ScheduleRepository { const timeZone = schedule.timeZone || userTimeZone; - const schedulesCount = await prisma.schedule.count({ + const schedulesCount = await this.prismaClient.schedule.count({ where: { userId: userId, }, @@ -141,7 +144,7 @@ export class ScheduleRepository { }; } - static async findManyDetailedScheduleByUserId({ + async findManyDetailedScheduleByUserId({ isManagedEventType, userId, defaultScheduleId, @@ -154,7 +157,7 @@ export class ScheduleRepository { isManagedEventType?: boolean; }) { - const schedules = await prisma.schedule.findMany({ + const schedules = await this.prismaClient.schedule.findMany({ where: { userId: userId, }, @@ -203,4 +206,56 @@ export class ScheduleRepository { return schedulesFormatted; } + + async getDefaultScheduleId(userId: number) { + const user = await this.prismaClient.user.findUnique({ + where: { + id: userId, + }, + select: { + defaultScheduleId: true, + }, + }); + + if (user?.defaultScheduleId) { + return user.defaultScheduleId; + } + + // If we're returning the default schedule for the first time then we should set it in the user record + const defaultSchedule = await this.prismaClient.schedule.findFirst({ + where: { + userId, + }, + select: { + id: true, + }, + }); + + if (!defaultSchedule) { + // Handle case where defaultSchedule is null by throwing an error + throw new Error("No schedules found for user"); + } + + return defaultSchedule.id; + } + + async hasDefaultSchedule(user: Partial) { + const defaultSchedule = await this.prismaClient.schedule.findFirst({ + where: { + userId: user.id, + }, + }); + return !!user.defaultScheduleId || !!defaultSchedule; + } + + async setupDefaultSchedule(userId: number, scheduleId: number) { + return this.prismaClient.user.update({ + where: { + id: userId, + }, + data: { + defaultScheduleId: scheduleId, + }, + }); + } } diff --git a/packages/features/schedules/services/ScheduleService.ts b/packages/features/schedules/services/ScheduleService.ts index c91d1da1e5..3fdff326cb 100644 --- a/packages/features/schedules/services/ScheduleService.ts +++ b/packages/features/schedules/services/ScheduleService.ts @@ -4,9 +4,10 @@ import { HttpError } from "@calcom/lib/http-error"; import { transformScheduleToAvailabilityForAtom } from "@calcom/lib/schedules/transformers/for-atom"; import type { PrismaClient } from "@calcom/prisma"; import type { TUpdateInputSchema } from "@calcom/trpc/server/routers/viewer/availability/schedule/update.schema"; -import { setupDefaultSchedule } from "@calcom/trpc/server/routers/viewer/availability/util"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; +import { ScheduleRepository } from "../repositories/ScheduleRepository"; + interface IUpdateScheduleOptions { input: TUpdateInputSchema; user: Pick, "id" | "defaultScheduleId" | "timeZone">; @@ -64,7 +65,9 @@ export class ScheduleService { let updatedUser; if (input.isDefault) { - const setupDefault = await setupDefaultSchedule(user.id, input.scheduleId, this.prisma); + const scheduleRepo = new ScheduleRepository(this.prisma); + + const setupDefault = await scheduleRepo.setupDefaultSchedule(user.id, input.scheduleId); updatedUser = setupDefault; } diff --git a/packages/lib/server/repository/host.test.ts b/packages/lib/server/repository/host.test.ts new file mode 100644 index 0000000000..d7d8ef178e --- /dev/null +++ b/packages/lib/server/repository/host.test.ts @@ -0,0 +1,76 @@ +import { describe, expect, it, vi, beforeEach } from "vitest"; + +import { PrismaClient } from "@calcom/prisma"; + +import { HostRepository } from "./host"; + +vi.mock("@calcom/prisma", () => { + const mockPrisma = { + host: { + updateMany: vi.fn(), + findMany: vi.fn(), + }, + }; + return { + __esModule: true, + default: mockPrisma, + PrismaClient: vi.fn(() => mockPrisma), + }; +}); + +describe("HostRepository", () => { + let prisma: PrismaClient; + let hostRepo: HostRepository; + + beforeEach(() => { + prisma = new PrismaClient(); + hostRepo = new HostRepository(prisma); + vi.clearAllMocks(); + }); + + describe("updateHostsWithNewDefaultSchedule", () => { + it("should update hosts with new scheduleId", async () => { + const userId = 1; + const oldScheduleId = 123; + const newScheduleId = 456; + const updateResult = { count: 2 }; // 2 hosts updated + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (prisma.host.updateMany as any).mockResolvedValue(updateResult); + + const result = await hostRepo.updateHostsSchedule(userId, oldScheduleId, newScheduleId); + + expect(prisma.host.updateMany).toHaveBeenCalledWith({ + where: { + userId, + scheduleId: oldScheduleId, + }, + data: { + scheduleId: newScheduleId, + }, + }); + expect(result).toEqual(updateResult); + }); + + it("should handle case with no hosts to update", async () => { + const userId = 1; + const oldScheduleId = 123; + const newScheduleId = 456; + const updateResult = { count: 0 }; // No hosts updated + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (prisma.host.updateMany as any).mockResolvedValue(updateResult); + + const result = await hostRepo.updateHostsSchedule(userId, oldScheduleId, newScheduleId); + + expect(prisma.host.updateMany).toHaveBeenCalledWith({ + where: { + userId, + scheduleId: oldScheduleId, + }, + data: { + scheduleId: newScheduleId, + }, + }); + expect(result).toEqual(updateResult); + }); + }); +}); diff --git a/packages/trpc/server/routers/viewer/availability/list.handler.ts b/packages/trpc/server/routers/viewer/availability/list.handler.ts index cae273f534..502a3ffe49 100644 --- a/packages/trpc/server/routers/viewer/availability/list.handler.ts +++ b/packages/trpc/server/routers/viewer/availability/list.handler.ts @@ -1,7 +1,7 @@ +import { ScheduleRepository } from "@calcom/features/schedules/repositories/ScheduleRepository"; import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "../../../types"; -import { getDefaultScheduleId } from "./util"; type ListOptions = { ctx: { @@ -37,7 +37,8 @@ export const listHandler = async ({ ctx }: ListOptions) => { let defaultScheduleId: number | null; try { - defaultScheduleId = await getDefaultScheduleId(user.id, prisma); + const scheduleRepository = new ScheduleRepository(prisma); + defaultScheduleId = await scheduleRepository.getDefaultScheduleId(user.id); if (!user.defaultScheduleId) { await prisma.user.update({ diff --git a/packages/trpc/server/routers/viewer/availability/schedule/get.handler.ts b/packages/trpc/server/routers/viewer/availability/schedule/get.handler.ts index a7f1220fa7..c5e031ab5a 100644 --- a/packages/trpc/server/routers/viewer/availability/schedule/get.handler.ts +++ b/packages/trpc/server/routers/viewer/availability/schedule/get.handler.ts @@ -1,4 +1,5 @@ import { ScheduleRepository } from "@calcom/features/schedules/repositories/ScheduleRepository"; +import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "../../../../types"; import type { TGetInputSchema } from "./get.schema"; @@ -11,7 +12,8 @@ type GetOptions = { }; export const getHandler = async ({ ctx, input }: GetOptions) => { - return await ScheduleRepository.findDetailedScheduleById({ + const scheduleRepo = new ScheduleRepository(prisma); + return await scheduleRepo.findDetailedScheduleById({ scheduleId: input.scheduleId, isManagedEventType: input.isManagedEventType, userId: ctx.user.id, diff --git a/packages/trpc/server/routers/viewer/availability/schedule/getAllSchedulesByUserId.handler.ts b/packages/trpc/server/routers/viewer/availability/schedule/getAllSchedulesByUserId.handler.ts index 2f446879e7..01e5f251f7 100644 --- a/packages/trpc/server/routers/viewer/availability/schedule/getAllSchedulesByUserId.handler.ts +++ b/packages/trpc/server/routers/viewer/availability/schedule/getAllSchedulesByUserId.handler.ts @@ -1,3 +1,4 @@ +import { ScheduleRepository } from "@calcom/features/schedules/repositories/ScheduleRepository"; import { hasReadPermissionsForUserId } from "@calcom/lib/hasEditPermissionForUser"; import logger from "@calcom/lib/logger"; import { prisma } from "@calcom/prisma"; @@ -5,7 +6,6 @@ import { prisma } from "@calcom/prisma"; import { TRPCError } from "@trpc/server"; import type { TrpcSessionUser } from "../../../../types"; -import { getDefaultScheduleId } from "../util"; import type { TGetAllByUserIdInputSchema } from "./getAllSchedulesByUserId.schema"; const log = logger.getSubLogger({ prefix: ["getAllSchedulesByUserIdHandler"] }); @@ -48,7 +48,8 @@ export const getAllSchedulesByUserIdHandler = async ({ ctx, input }: GetOptions) }); } - const defaultScheduleId = await getDefaultScheduleId(input.userId, prisma); + const scheduleRepository = new ScheduleRepository(prisma); + const defaultScheduleId = await scheduleRepository.getDefaultScheduleId(input.userId); return { schedules: schedules.map((schedule) => { diff --git a/packages/trpc/server/routers/viewer/availability/util.ts b/packages/trpc/server/routers/viewer/availability/util.ts deleted file mode 100644 index 2a7897b126..0000000000 --- a/packages/trpc/server/routers/viewer/availability/util.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { PrismaClient } from "@calcom/prisma"; -import type { User } from "@calcom/prisma/client"; - -export const getDefaultScheduleId = async (userId: number, prisma: PrismaClient) => { - const user = await prisma.user.findUnique({ - where: { - id: userId, - }, - select: { - defaultScheduleId: true, - }, - }); - - if (user?.defaultScheduleId) { - return user.defaultScheduleId; - } - - // If we're returning the default schedule for the first time then we should set it in the user record - const defaultSchedule = await prisma.schedule.findFirst({ - where: { - userId, - }, - select: { - id: true, - }, - }); - - if (!defaultSchedule) { - // Handle case where defaultSchedule is null by throwing an error - throw new Error("No schedules found for user"); - } - - return defaultSchedule.id; -}; - -export const hasDefaultSchedule = async (user: Partial, prisma: PrismaClient) => { - const defaultSchedule = await prisma.schedule.findFirst({ - where: { - userId: user.id, - }, - }); - return !!user.defaultScheduleId || !!defaultSchedule; -}; - -export const setupDefaultSchedule = async (userId: number, scheduleId: number, prisma: PrismaClient) => { - return prisma.user.update({ - where: { - id: userId, - }, - data: { - defaultScheduleId: scheduleId, - }, - }); -}; diff --git a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts index 81d4f1cc4f..8c05be4a4e 100644 --- a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts +++ b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts @@ -7,6 +7,7 @@ import { sendChangeOfEmailVerification } from "@calcom/features/auth/lib/verifyE import { updateNewTeamMemberEventTypes } from "@calcom/features/ee/teams/lib/queries"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { checkUsername } from "@calcom/features/profile/lib/checkUsername"; +import { ScheduleRepository } from "@calcom/features/schedules/repositories/ScheduleRepository"; import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; @@ -22,7 +23,6 @@ import type { TrpcSessionUser } from "@calcom/trpc/server/types"; import { TRPCError } from "@trpc/server"; -import { getDefaultScheduleId } from "../availability/util"; import { updateUserMetadataAllowedKeys, type TUpdateProfileInputSchema } from "./updateProfile.schema"; const log = logger.getSubLogger({ prefix: ["updateProfile"] }); @@ -263,7 +263,8 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) if (user.timeZone !== data.timeZone && updatedUser.schedules.length > 0) { // on timezone change update timezone of default schedule - const defaultScheduleId = await getDefaultScheduleId(user.id, prisma); + const scheduleRepository = new ScheduleRepository(prisma); + const defaultScheduleId = await scheduleRepository.getDefaultScheduleId(user.id); if (!user.defaultScheduleId) { // set default schedule if not already set