fix: Host schedule not updating upon updating/deleting default schedule (#20750)
* fix: host schdule not updating * Update util.ts * tweak * Update delete.handler.ts * add test * update * Update util.test.ts
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
export class HostRepository {
|
||||
static async updateHostsSchedule(userId: number, oldScheduleId: number, newScheduleId: number) {
|
||||
return await prisma.host.updateMany({
|
||||
where: {
|
||||
userId,
|
||||
scheduleId: oldScheduleId,
|
||||
},
|
||||
data: {
|
||||
scheduleId: newScheduleId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { prisma } from "@calcom/prisma";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import type { TrpcSessionUser } from "../../../../types";
|
||||
import { updateHostsWithNewDefaultSchedule } from "../util";
|
||||
import type { TDeleteInputSchema } from "./delete.schema";
|
||||
|
||||
type DeleteOptions = {
|
||||
@@ -45,6 +46,8 @@ export const deleteHandler = async ({ input, ctx }: DeleteOptions) => {
|
||||
// to throw the error if there arent any other schedules
|
||||
if (!scheduleToSetAsDefault) throw new TRPCError({ code: "BAD_REQUEST" });
|
||||
|
||||
await updateHostsWithNewDefaultSchedule(user.id, input.scheduleId, scheduleToSetAsDefault.id);
|
||||
|
||||
await prisma.user.update({
|
||||
where: {
|
||||
id: user.id,
|
||||
@@ -53,7 +56,10 @@ export const deleteHandler = async ({ input, ctx }: DeleteOptions) => {
|
||||
defaultScheduleId: scheduleToSetAsDefault?.id || null,
|
||||
},
|
||||
});
|
||||
} else if (user.defaultScheduleId) {
|
||||
await updateHostsWithNewDefaultSchedule(user.id, input.scheduleId, user.defaultScheduleId);
|
||||
}
|
||||
|
||||
await prisma.schedule.delete({
|
||||
where: {
|
||||
id: input.scheduleId,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { prisma } from "@calcom/prisma";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import type { TrpcSessionUser } from "../../../../types";
|
||||
import { setupDefaultSchedule } from "../util";
|
||||
import { setupDefaultSchedule, updateHostsWithNewDefaultSchedule } from "../util";
|
||||
import type { TUpdateInputSchema } from "./update.schema";
|
||||
|
||||
type User = NonNullable<TrpcSessionUser>;
|
||||
@@ -61,6 +61,10 @@ export const updateHandler = async ({ input, ctx }: UpdateOptions) => {
|
||||
|
||||
let updatedUser;
|
||||
if (input.isDefault) {
|
||||
if (user?.defaultScheduleId) {
|
||||
await updateHostsWithNewDefaultSchedule(user.id, user.defaultScheduleId, input.scheduleId);
|
||||
}
|
||||
|
||||
const setupDefault = await setupDefaultSchedule(user.id, input.scheduleId, prisma);
|
||||
updatedUser = setupDefault;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
|
||||
import { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
getDefaultScheduleId,
|
||||
hasDefaultSchedule,
|
||||
setupDefaultSchedule,
|
||||
updateHostsWithNewDefaultSchedule,
|
||||
} from "./util";
|
||||
|
||||
vi.mock("@calcom/prisma", () => {
|
||||
const mockPrisma = {
|
||||
user: {
|
||||
findUnique: vi.fn(),
|
||||
update: vi.fn(),
|
||||
},
|
||||
schedule: {
|
||||
findFirst: vi.fn(),
|
||||
},
|
||||
host: {
|
||||
updateMany: vi.fn(),
|
||||
},
|
||||
};
|
||||
return {
|
||||
__esModule: true,
|
||||
default: mockPrisma,
|
||||
PrismaClient: vi.fn(() => mockPrisma),
|
||||
};
|
||||
});
|
||||
|
||||
describe("Availability Utils", () => {
|
||||
let prisma: PrismaClient;
|
||||
|
||||
beforeEach(() => {
|
||||
prisma = new PrismaClient();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("getDefaultScheduleId", () => {
|
||||
it("should return defaultScheduleId if user has one", async () => {
|
||||
const userId = 1;
|
||||
const defaultScheduleId = 123;
|
||||
|
||||
(prisma.user.findUnique as any).mockResolvedValue({
|
||||
defaultScheduleId,
|
||||
});
|
||||
|
||||
const result = await getDefaultScheduleId(userId, prisma);
|
||||
|
||||
expect(prisma.user.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: userId },
|
||||
select: { defaultScheduleId: true },
|
||||
});
|
||||
expect(result).toBe(defaultScheduleId);
|
||||
});
|
||||
|
||||
it("should find and return first schedule if user has no defaultScheduleId", async () => {
|
||||
const userId = 1;
|
||||
const scheduleId = 456;
|
||||
|
||||
(prisma.user.findUnique as any).mockResolvedValue({
|
||||
defaultScheduleId: null,
|
||||
});
|
||||
|
||||
(prisma.schedule.findFirst as any).mockResolvedValue({
|
||||
id: scheduleId,
|
||||
});
|
||||
|
||||
const result = await getDefaultScheduleId(userId, prisma);
|
||||
|
||||
expect(prisma.user.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: userId },
|
||||
select: { defaultScheduleId: true },
|
||||
});
|
||||
expect(prisma.schedule.findFirst).toHaveBeenCalledWith({
|
||||
where: { userId },
|
||||
select: { id: true },
|
||||
});
|
||||
expect(result).toBe(scheduleId);
|
||||
});
|
||||
|
||||
it("should throw error if no schedules found", async () => {
|
||||
const userId = 1;
|
||||
|
||||
(prisma.user.findUnique as any).mockResolvedValue({
|
||||
defaultScheduleId: null,
|
||||
});
|
||||
|
||||
(prisma.schedule.findFirst as any).mockResolvedValue(null);
|
||||
|
||||
await expect(getDefaultScheduleId(userId, prisma)).rejects.toThrow("No schedules found for user");
|
||||
});
|
||||
});
|
||||
|
||||
describe("hasDefaultSchedule", () => {
|
||||
it("should return true if user has defaultScheduleId", async () => {
|
||||
const user = { id: 1, defaultScheduleId: 123 };
|
||||
|
||||
const result = await hasDefaultSchedule(user, prisma);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should return true if user has a schedule", async () => {
|
||||
const user = { id: 1, defaultScheduleId: null };
|
||||
|
||||
(prisma.schedule.findFirst as any).mockResolvedValue({
|
||||
id: 456,
|
||||
});
|
||||
|
||||
const result = await hasDefaultSchedule(user, prisma);
|
||||
|
||||
expect(prisma.schedule.findFirst).toHaveBeenCalledWith({
|
||||
where: { userId: user.id },
|
||||
});
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if user has no defaultScheduleId and no schedules", async () => {
|
||||
const user = { id: 1, defaultScheduleId: null };
|
||||
|
||||
(prisma.schedule.findFirst as any).mockResolvedValue(null);
|
||||
|
||||
const result = await hasDefaultSchedule(user, prisma);
|
||||
|
||||
expect(prisma.schedule.findFirst).toHaveBeenCalledWith({
|
||||
where: { userId: user.id },
|
||||
});
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setupDefaultSchedule", () => {
|
||||
it("should update user with new defaultScheduleId", async () => {
|
||||
const userId = 1;
|
||||
const scheduleId = 123;
|
||||
const updatedUser = { id: userId, defaultScheduleId: scheduleId };
|
||||
|
||||
(prisma.user.update as any).mockResolvedValue(updatedUser);
|
||||
|
||||
const result = await setupDefaultSchedule(userId, scheduleId, prisma);
|
||||
|
||||
expect(prisma.user.update).toHaveBeenCalledWith({
|
||||
where: { id: userId },
|
||||
data: { defaultScheduleId: scheduleId },
|
||||
});
|
||||
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
|
||||
|
||||
(prisma.host.updateMany as any).mockResolvedValue(updateResult);
|
||||
|
||||
const result = await updateHostsWithNewDefaultSchedule(userId, oldScheduleId, newScheduleId, prisma);
|
||||
|
||||
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
|
||||
|
||||
(prisma.host.updateMany as any).mockResolvedValue(updateResult);
|
||||
|
||||
const result = await updateHostsWithNewDefaultSchedule(userId, oldScheduleId, newScheduleId, prisma);
|
||||
|
||||
expect(prisma.host.updateMany).toHaveBeenCalledWith({
|
||||
where: {
|
||||
userId,
|
||||
scheduleId: oldScheduleId,
|
||||
},
|
||||
data: {
|
||||
scheduleId: newScheduleId,
|
||||
},
|
||||
});
|
||||
expect(result).toEqual(updateResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { User } from "@prisma/client";
|
||||
|
||||
import { HostRepository } from "@calcom/lib/server/repository/host";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
export const getDefaultScheduleId = async (userId: number, prisma: PrismaClient) => {
|
||||
@@ -53,3 +54,11 @@ export const setupDefaultSchedule = async (userId: number, scheduleId: number, p
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const updateHostsWithNewDefaultSchedule = async (
|
||||
userId: number,
|
||||
defaultScheduleId: number,
|
||||
scheduleId: number
|
||||
) => {
|
||||
return await HostRepository.updateHostsSchedule(userId, defaultScheduleId, scheduleId);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user