125 lines
4.6 KiB
TypeScript
125 lines
4.6 KiB
TypeScript
import { cloneDeep } from "lodash";
|
|
|
|
import { sendRescheduledSeatEmailAndSMS } from "@calcom/emails/email-manager";
|
|
import type EventManager from "@calcom/features/bookings/lib/EventManager";
|
|
import { addVideoCallDataToEvent } from "@calcom/features/bookings/lib/handleNewBooking/addVideoCallDataToEvent";
|
|
import { getTranslation } from "@calcom/i18n/server";
|
|
import prisma from "@calcom/prisma";
|
|
import type { Person, CalendarEvent } from "@calcom/types/Calendar";
|
|
|
|
import { findBookingQuery } from "../../../handleNewBooking/findBookingQuery";
|
|
import lastAttendeeDeleteBooking from "../../lib/lastAttendeeDeleteBooking";
|
|
import type { RescheduleSeatedBookingObject, SeatAttendee, NewTimeSlotBooking } from "../../types";
|
|
|
|
const attendeeRescheduleSeatedBooking = async (
|
|
rescheduleSeatedBookingObject: RescheduleSeatedBookingObject,
|
|
seatAttendee: SeatAttendee,
|
|
newTimeSlotBooking: NewTimeSlotBooking | null,
|
|
originalBookingEvt: CalendarEvent,
|
|
eventManager: EventManager
|
|
) => {
|
|
const { tAttendees, bookingSeat, bookerEmail, evt, eventType } = rescheduleSeatedBookingObject;
|
|
let { originalRescheduledBooking } = rescheduleSeatedBookingObject;
|
|
|
|
seatAttendee["language"] = { translate: tAttendees, locale: bookingSeat?.attendee.locale ?? "en" };
|
|
|
|
// Set attendeeSeatId so that reschedule/cancel links in emails use seatUid instead of bookingUid
|
|
evt.attendeeSeatId = bookingSeat?.referenceUid;
|
|
|
|
// Update the original calendar event by removing the attendee that is rescheduling
|
|
if (originalBookingEvt && originalRescheduledBooking) {
|
|
// Event would probably be deleted so we first check than instead of updating references
|
|
const filteredAttendees = originalRescheduledBooking?.attendees.filter((attendee) => {
|
|
return attendee.email !== bookerEmail;
|
|
});
|
|
const deletedReference = await lastAttendeeDeleteBooking(
|
|
originalRescheduledBooking,
|
|
filteredAttendees,
|
|
originalBookingEvt
|
|
);
|
|
|
|
if (!deletedReference) {
|
|
await eventManager.updateCalendarAttendees(originalBookingEvt, originalRescheduledBooking);
|
|
}
|
|
}
|
|
|
|
// If there is no booking then remove the attendee from the old booking and create a new one
|
|
if (!newTimeSlotBooking) {
|
|
await prisma.attendee.delete({
|
|
where: {
|
|
id: seatAttendee?.id,
|
|
},
|
|
});
|
|
|
|
const originalBookingReferences = originalRescheduledBooking?.references;
|
|
|
|
// We don't want to trigger rescheduling logic of the original booking
|
|
originalRescheduledBooking = null;
|
|
|
|
const evtWithVideoCallData = originalBookingReferences
|
|
? addVideoCallDataToEvent(originalBookingReferences, evt)
|
|
: evt;
|
|
|
|
await sendRescheduledSeatEmailAndSMS(evtWithVideoCallData, seatAttendee as Person, eventType.metadata);
|
|
|
|
return null;
|
|
}
|
|
|
|
// Need to change the new seat reference and attendee record to remove it from the old booking and add it to the new booking
|
|
// https://stackoverflow.com/questions/4980963/database-insert-new-rows-or-update-existing-ones
|
|
if (seatAttendee?.id && bookingSeat?.id) {
|
|
await prisma.$transaction([
|
|
prisma.attendee.update({
|
|
where: {
|
|
id: seatAttendee.id,
|
|
},
|
|
data: {
|
|
bookingId: newTimeSlotBooking.id,
|
|
},
|
|
}),
|
|
prisma.bookingSeat.update({
|
|
where: {
|
|
id: bookingSeat.id,
|
|
},
|
|
data: {
|
|
bookingId: newTimeSlotBooking.id,
|
|
},
|
|
}),
|
|
]);
|
|
}
|
|
// Add the new attendees to the new time slot booking attendees
|
|
for (const attendee of newTimeSlotBooking.attendees) {
|
|
const translate = await getTranslation(attendee.locale ?? "en", "common");
|
|
evt.attendees.push({
|
|
email: attendee.email,
|
|
name: attendee.name,
|
|
timeZone: attendee.timeZone,
|
|
language: { translate, locale: attendee.locale ?? "en" },
|
|
});
|
|
}
|
|
|
|
const copyEvent = cloneDeep({ ...evt, iCalUID: newTimeSlotBooking.iCalUID });
|
|
|
|
await eventManager.updateCalendarAttendees(copyEvent, newTimeSlotBooking);
|
|
|
|
const copyEventWithVideoCallData = newTimeSlotBooking.references
|
|
? addVideoCallDataToEvent(newTimeSlotBooking.references, copyEvent)
|
|
: copyEvent;
|
|
|
|
await sendRescheduledSeatEmailAndSMS(
|
|
copyEventWithVideoCallData,
|
|
seatAttendee as Person,
|
|
eventType.metadata
|
|
);
|
|
const filteredAttendees = originalRescheduledBooking?.attendees.filter((attendee) => {
|
|
return attendee.email !== bookerEmail;
|
|
});
|
|
await lastAttendeeDeleteBooking(originalRescheduledBooking, filteredAttendees, originalBookingEvt);
|
|
|
|
const foundBooking = await findBookingQuery(newTimeSlotBooking.id);
|
|
|
|
return { ...foundBooking, seatReferenceUid: bookingSeat?.referenceUid };
|
|
};
|
|
|
|
export default attendeeRescheduleSeatedBooking;
|