Refactor and cleaning up code
This commit is contained in:
parent
ad2b6fbdce
commit
2b07cab25a
|
@ -1,12 +1,12 @@
|
|||
import { BookingStatus, User, SchedulingType, Booking, Attendee } from "@prisma/client";
|
||||
import { BookingStatus, User, Booking, Attendee } from "@prisma/client";
|
||||
import dayjs from "dayjs";
|
||||
import type { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { getSession } from "next-auth/react";
|
||||
import type { TFunction } from "next-i18next";
|
||||
import { z, ZodError } from "zod";
|
||||
|
||||
import { CalendarEventBuilder } from "@calcom/core/builders/CalendarEvent/builder";
|
||||
import { CalendarEventClass } from "@calcom/core/builders/CalendarEvent/class";
|
||||
import { CalendarEventDirector } from "@calcom/core/builders/CalendarEvent/director";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { Person } from "@calcom/types/Calendar";
|
||||
|
||||
|
@ -16,6 +16,10 @@ import prisma from "@lib/prisma";
|
|||
export type RescheduleResponse = Booking & {
|
||||
attendees: Attendee[];
|
||||
};
|
||||
export type PersonAttendeeCommonFields = Pick<
|
||||
User,
|
||||
"id" | "email" | "name" | "locale" | "timeZone" | "username"
|
||||
>;
|
||||
|
||||
const rescheduleSchema = z.object({
|
||||
bookingId: z.string(),
|
||||
|
@ -27,9 +31,11 @@ const handler = async (
|
|||
res: NextApiResponse
|
||||
): Promise<RescheduleResponse | NextApiResponse | void> => {
|
||||
const session = await getSession({ req });
|
||||
const { bookingId, rescheduleReason: cancellationReason } = req.body;
|
||||
type PersonAttendee = Pick<User, "id" | "email" | "name" | "locale" | "timeZone" | "username">;
|
||||
let userOwner: PersonAttendee | null;
|
||||
const {
|
||||
bookingId,
|
||||
rescheduleReason: cancellationReason,
|
||||
}: { bookingId: string; rescheduleReason: string; cancellationReason: string } = req.body;
|
||||
let userOwner: PersonAttendeeCommonFields | null;
|
||||
try {
|
||||
if (session?.user?.id) {
|
||||
userOwner = await prisma.user.findUnique({
|
||||
|
@ -51,17 +57,35 @@ const handler = async (
|
|||
}
|
||||
|
||||
const bookingToReschedule = await prisma.booking.findFirst({
|
||||
select: {
|
||||
id: true,
|
||||
uid: true,
|
||||
title: true,
|
||||
startTime: true,
|
||||
endTime: true,
|
||||
eventTypeId: true,
|
||||
location: true,
|
||||
attendees: true,
|
||||
},
|
||||
rejectOnNotFound: true,
|
||||
include: { attendees: true },
|
||||
where: {
|
||||
uid: bookingId,
|
||||
NOT: {
|
||||
status: BookingStatus.CANCELLED,
|
||||
status: {
|
||||
in: [BookingStatus.CANCELLED, BookingStatus.REJECTED],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (bookingToReschedule && bookingToReschedule.eventTypeId && userOwner) {
|
||||
const event = await prisma.eventType.findFirst({
|
||||
select: {
|
||||
title: true,
|
||||
users: true,
|
||||
schedulingType: true,
|
||||
},
|
||||
rejectOnNotFound: true,
|
||||
where: {
|
||||
id: bookingToReschedule.eventTypeId,
|
||||
},
|
||||
|
@ -78,20 +102,15 @@ const handler = async (
|
|||
},
|
||||
});
|
||||
|
||||
// Soft delete
|
||||
await prisma.bookingReference.deleteMany({
|
||||
where: {
|
||||
bookingId: bookingToReschedule.id,
|
||||
},
|
||||
});
|
||||
|
||||
// @NOTE: Lets assume all guests are the same language
|
||||
const [firstAttendee] = bookingToReschedule.attendees;
|
||||
const tAttendees = await getTranslation(firstAttendee.locale ?? "en", "common");
|
||||
const usersToPeopleType = (users: PersonAttendee[], selectedLanguage: TFunction): Person[] => {
|
||||
const [mainAttendee] = bookingToReschedule.attendees;
|
||||
// @NOTE: Should we assume attendees language?
|
||||
const tAttendees = await getTranslation(mainAttendee.locale ?? "en", "common");
|
||||
const usersToPeopleType = (
|
||||
users: PersonAttendeeCommonFields[],
|
||||
selectedLanguage: TFunction
|
||||
): Person[] => {
|
||||
return users?.map((user) => {
|
||||
return {
|
||||
id: user.id || "",
|
||||
email: user.email || "",
|
||||
name: user.name || "",
|
||||
username: user?.username || "",
|
||||
|
@ -103,46 +122,37 @@ const handler = async (
|
|||
|
||||
const userOwnerTranslation = await getTranslation(userOwner.locale ?? "en", "common");
|
||||
const [userOwnerAsPeopleType] = usersToPeopleType([userOwner], userOwnerTranslation);
|
||||
const calendarEventBuilder = new CalendarEventBuilder();
|
||||
calendarEventBuilder.init({
|
||||
// Using builder as assembling calEvent can take some time
|
||||
const builder = new CalendarEventBuilder();
|
||||
builder.init({
|
||||
title: bookingToReschedule.title,
|
||||
type: event?.title || "Nameless Event",
|
||||
type: event.title,
|
||||
startTime: bookingToReschedule.startTime.toISOString(),
|
||||
endTime: bookingToReschedule.endTime.toISOString(),
|
||||
attendees: usersToPeopleType(
|
||||
// username field doesn't exists on attendee but could be in the future
|
||||
bookingToReschedule.attendees as unknown as PersonAttendee[],
|
||||
bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[],
|
||||
tAttendees
|
||||
),
|
||||
organizer: userOwnerAsPeopleType,
|
||||
});
|
||||
await calendarEventBuilder.buildEventObjectFromInnerClass(bookingToReschedule.eventTypeId);
|
||||
await calendarEventBuilder.buildUsersFromInnerClass();
|
||||
if (event?.schedulingType === SchedulingType.ROUND_ROBIN) {
|
||||
await calendarEventBuilder.buildLuckyUsers();
|
||||
}
|
||||
if (event?.schedulingType === SchedulingType.COLLECTIVE) {
|
||||
await calendarEventBuilder.buildLuckyUsers();
|
||||
}
|
||||
await calendarEventBuilder.buildAttendeesList();
|
||||
calendarEventBuilder.setLocation(bookingToReschedule.location);
|
||||
calendarEventBuilder.setUId(bookingToReschedule.uid);
|
||||
calendarEventBuilder.setCancellationReason(cancellationReason);
|
||||
console.log({ calendarEventBuilder });
|
||||
|
||||
const director = new CalendarEventDirector();
|
||||
director.setBuilder(builder);
|
||||
director.setExistingBooking(bookingToReschedule as unknown as Booking);
|
||||
director.setCancellationReason(cancellationReason);
|
||||
director.buildForRescheduleEmail();
|
||||
|
||||
// Send email =================
|
||||
calendarEventBuilder.buildRescheduleLink(bookingToReschedule.uid);
|
||||
await sendRequestRescheduleEmail(calendarEventBuilder.calendarEvent, {
|
||||
rescheduleLink: calendarEventBuilder.rescheduleLink,
|
||||
await sendRequestRescheduleEmail(builder.calendarEvent, {
|
||||
rescheduleLink: builder.rescheduleLink,
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json(bookingToReschedule);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
// throw new Error(error?.message);
|
||||
throw new Error("Error.request.reschedule");
|
||||
}
|
||||
|
||||
return res.status(204);
|
||||
};
|
||||
|
||||
function validate(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { User, BookingStatus } from "@prisma/client";
|
||||
import { BookingStatus } from "@prisma/client";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { TestUtilCreateBookingOnUserId, TestUtilCreatePayment } from "./lib/dbSetup";
|
||||
|
|
|
@ -25,12 +25,12 @@ const userSelect = Prisma.validator<Prisma.UserArgs>()({
|
|||
});
|
||||
|
||||
type User = Prisma.UserGetPayload<typeof userSelect>;
|
||||
|
||||
type PersonAttendeeCommonFields = Pick<User, "id" | "email" | "name" | "locale" | "timeZone" | "username">;
|
||||
interface ICalendarEventBuilder {
|
||||
calendarEvent: CalendarEventClass;
|
||||
eventType: Awaited<ReturnType<CalendarEventBuilder["getEventFromEventId"]>>;
|
||||
users: Awaited<ReturnType<CalendarEventBuilder["getUserById"]>>[];
|
||||
attendeesList: any;
|
||||
attendeesList: PersonAttendeeCommonFields[];
|
||||
teamMembers: Awaited<ReturnType<CalendarEventBuilder["getTeamMembers"]>>;
|
||||
rescheduleLink: string;
|
||||
}
|
||||
|
@ -55,6 +55,10 @@ export class CalendarEventBuilder implements ICalendarEventBuilder {
|
|||
this.calendarEvent = new CalendarEventClass(initProps);
|
||||
}
|
||||
|
||||
public setEventType(eventType: ICalendarEventBuilder["eventType"]) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public async buildEventObjectFromInnerClass(eventId: number) {
|
||||
const resultEvent = await this.getEventFromEventId(eventId);
|
||||
if (resultEvent) {
|
||||
|
@ -80,7 +84,11 @@ export class CalendarEventBuilder implements ICalendarEventBuilder {
|
|||
}
|
||||
|
||||
public buildAttendeesList() {
|
||||
this.attendeesList = [...this.calendarEvent.attendees, ...this.teamMembers];
|
||||
// Language Function was set on builder init
|
||||
this.attendeesList = [
|
||||
...(this.calendarEvent.attendees as unknown as PersonAttendeeCommonFields[]),
|
||||
...this.teamMembers,
|
||||
];
|
||||
}
|
||||
|
||||
private async getUserById(userId: number) {
|
||||
|
@ -209,6 +217,8 @@ export class CalendarEventBuilder implements ICalendarEventBuilder {
|
|||
// Users[0] its organizer so we are omitting with slice(1)
|
||||
const teamMemberPromises = this.users.slice(1).map(async function (user) {
|
||||
return {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email || "", // @NOTE: Should we change this "" to teamMemberId?
|
||||
name: user.name || "",
|
||||
timeZone: user.timeZone,
|
||||
|
@ -216,7 +226,8 @@ export class CalendarEventBuilder implements ICalendarEventBuilder {
|
|||
translate: await getTranslation(user.locale ?? "en", "common"),
|
||||
locale: user.locale ?? "en",
|
||||
},
|
||||
} as Person;
|
||||
locale: user.locale,
|
||||
} as PersonAttendeeCommonFields;
|
||||
});
|
||||
return await Promise.all(teamMemberPromises);
|
||||
}
|
||||
|
@ -262,7 +273,7 @@ export class CalendarEventBuilder implements ICalendarEventBuilder {
|
|||
throw new Error("Run buildEventObjectFromInnerClass before this function");
|
||||
}
|
||||
const isTeam = !!this.eventType.teamId;
|
||||
console.log(process.env);
|
||||
|
||||
const queryParams = new URLSearchParams();
|
||||
queryParams.set("rescheduleUid", `${originalBookingUId}`);
|
||||
const rescheduleLink = `${process.env.BASE_URL}/${
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import { Booking } from "@prisma/client";
|
||||
|
||||
import { CalendarEventBuilder } from "./builder";
|
||||
|
||||
export class CalendarEventDirector {
|
||||
private builder!: CalendarEventBuilder;
|
||||
private existingBooking!: Partial<Booking>;
|
||||
private cancellationReason!: string;
|
||||
|
||||
public setBuilder(builder: CalendarEventBuilder): void {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
public setExistingBooking(booking: Booking) {
|
||||
this.existingBooking = booking;
|
||||
}
|
||||
|
||||
public setCancellationReason(reason: string) {
|
||||
this.cancellationReason = reason;
|
||||
}
|
||||
|
||||
public async buildForRescheduleEmail(): Promise<void> {
|
||||
if (this.existingBooking && this.existingBooking.eventTypeId && this.existingBooking.uid) {
|
||||
this.builder.buildEventObjectFromInnerClass(this.existingBooking.eventTypeId);
|
||||
await this.builder.buildUsersFromInnerClass();
|
||||
await this.builder.buildAttendeesList();
|
||||
this.builder.setLocation(this.existingBooking.location);
|
||||
this.builder.setUId(this.existingBooking.uid);
|
||||
this.builder.setCancellationReason(this.cancellationReason);
|
||||
this.builder.buildRescheduleLink(this.existingBooking.uid);
|
||||
} else {
|
||||
throw new Error("buildForRescheduleEmail.missing.params.required");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -204,7 +204,7 @@ model BookingReference {
|
|||
meetingId String?
|
||||
meetingPassword String?
|
||||
meetingUrl String?
|
||||
booking Booking? @relation(fields: [bookingId], references: [id])
|
||||
booking Booking? @relation(fields: [bookingId], references: [id], onDelete: Cascade)
|
||||
bookingId Int?
|
||||
deleted Boolean?
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ export type Person = {
|
|||
timeZone: string;
|
||||
language: { translate: TFunction; locale: string };
|
||||
username?: string;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
export type EventBusyDate = Record<"start" | "end", Date | string>;
|
||||
|
@ -77,9 +78,9 @@ export interface CalendarEvent {
|
|||
title: string;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
organizer: Person;
|
||||
attendees: Person[];
|
||||
additionalNotes?: string | null;
|
||||
organizer: Person; //@TODO: check if needed for builder
|
||||
attendees: Person[]; //@TODO: check if needed for builder
|
||||
description?: string | null;
|
||||
team?: {
|
||||
name: string;
|
||||
|
|
Loading…
Reference in New Issue
Block a user