mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
f2a44279fe
* refactor: evt creation * refactor: evt creation * refactor: evt creation * fix: type * test: update unit tests * chore: add comments * fix: handle undefined in withConditional to match NonNullable<T> type Co-Authored-By: unknown <> * refactor: evt * fix: type err * refactor: remove add videoCallData * refactor: use error with code * test: update unit test * refactor: feedback * refactor: remove conditional * refactor: more strict types * fix: type err * chor: remove un used * refactor: improve recurring event handling in RegularBookingService Removed unnecessary whitespace and clarified comments regarding the attachment of recurring configurations in the booking handler. Adjusted logic to ensure that recurring settings are only applied when relevant. * refactor: test * fix: type error * refactor: improve code --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
129 lines
4.3 KiB
TypeScript
129 lines
4.3 KiB
TypeScript
import { cloneDeep } from "lodash";
|
|
|
|
import { sendRescheduledEmailsAndSMS } from "@calcom/emails/email-manager";
|
|
import type EventManager from "@calcom/features/bookings/lib/EventManager";
|
|
import prisma from "@calcom/prisma";
|
|
import type { AdditionalInformation, AppsStatus } from "@calcom/types/Calendar";
|
|
|
|
import { CalendarEventBuilder } from "@calcom/features/CalendarEventBuilder";
|
|
import type { Booking } from "../../../handleNewBooking/createBooking";
|
|
import { findBookingQuery } from "../../../handleNewBooking/findBookingQuery";
|
|
import { handleAppsStatus } from "../../../handleNewBooking/handleAppsStatus";
|
|
import type { createLoggerWithEventDetails } from "../../../handleNewBooking/logger";
|
|
import type { SeatedBooking, RescheduleSeatedBookingObject } from "../../types";
|
|
|
|
async function updateBooking({
|
|
bookingId,
|
|
startTime,
|
|
endTime,
|
|
cancellationReason,
|
|
}: {
|
|
bookingId: number;
|
|
startTime: string;
|
|
endTime: string;
|
|
cancellationReason: string;
|
|
}): Promise<Booking & { appsStatus?: AppsStatus[] }> {
|
|
const booking = await prisma.booking.update({
|
|
where: {
|
|
id: bookingId,
|
|
},
|
|
data: {
|
|
startTime,
|
|
endTime,
|
|
cancellationReason,
|
|
},
|
|
include: {
|
|
user: true,
|
|
references: true,
|
|
payment: true,
|
|
attendees: true,
|
|
},
|
|
});
|
|
return { ...booking, userUuid: booking.user?.uuid ?? null };
|
|
}
|
|
|
|
const moveSeatedBookingToNewTimeSlot = async (
|
|
rescheduleSeatedBookingObject: RescheduleSeatedBookingObject,
|
|
seatedBooking: SeatedBooking,
|
|
eventManager: EventManager,
|
|
loggerWithEventDetails: ReturnType<typeof createLoggerWithEventDetails>
|
|
) => {
|
|
const {
|
|
rescheduleReason,
|
|
rescheduleUid,
|
|
eventType,
|
|
organizerUser,
|
|
reqAppsStatus,
|
|
noEmail,
|
|
isConfirmedByDefault,
|
|
additionalNotes,
|
|
} = rescheduleSeatedBookingObject;
|
|
let { evt } = rescheduleSeatedBookingObject;
|
|
|
|
const newBooking = await updateBooking({
|
|
bookingId: seatedBooking.id,
|
|
startTime: evt.startTime,
|
|
endTime: evt.endTime,
|
|
cancellationReason: rescheduleReason,
|
|
});
|
|
|
|
evt = CalendarEventBuilder.fromEvent(evt)
|
|
.withVideoCallDataFromReferences(newBooking.references)
|
|
.build();
|
|
|
|
const copyEvent = cloneDeep(evt);
|
|
|
|
const updateManager = await eventManager.reschedule(copyEvent, rescheduleUid, newBooking.id);
|
|
|
|
// @NOTE: This code is duplicated and should be moved to a function
|
|
// This gets overridden when updating the event - to check if notes have been hidden or not. We just reset this back
|
|
// to the default description when we are sending the emails.
|
|
evt.description = eventType.description;
|
|
|
|
const results = updateManager.results;
|
|
|
|
const calendarResult = results.find((result) => result.type.includes("_calendar"));
|
|
|
|
evt.iCalUID = calendarResult?.updatedEvent.iCalUID || undefined;
|
|
|
|
if (results.length > 0 && results.some((res) => !res.success)) {
|
|
const error = {
|
|
errorCode: "BookingReschedulingMeetingFailed",
|
|
message: "Booking Rescheduling failed",
|
|
};
|
|
loggerWithEventDetails.error(`Booking ${organizerUser.name} failed`, JSON.stringify({ error, results }));
|
|
} else {
|
|
const metadata: AdditionalInformation = {};
|
|
if (results.length) {
|
|
// TODO: Handle created event metadata more elegantly
|
|
const [updatedEvent] = Array.isArray(results[0].updatedEvent)
|
|
? results[0].updatedEvent
|
|
: [results[0].updatedEvent];
|
|
if (updatedEvent) {
|
|
metadata.hangoutLink = updatedEvent.hangoutLink;
|
|
metadata.conferenceData = updatedEvent.conferenceData;
|
|
metadata.entryPoints = updatedEvent.entryPoints;
|
|
evt.appsStatus = handleAppsStatus(results, newBooking, reqAppsStatus);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (noEmail !== true && isConfirmedByDefault) {
|
|
const copyEvent = cloneDeep(evt);
|
|
loggerWithEventDetails.debug("Emails: Sending reschedule emails - handleSeats");
|
|
await sendRescheduledEmailsAndSMS(
|
|
{
|
|
...copyEvent,
|
|
additionalNotes, // Resets back to the additionalNote input and not the override value
|
|
cancellationReason: `$RCH$${rescheduleReason ? rescheduleReason : ""}`, // Removable code prefix to differentiate cancellation from rescheduling for email
|
|
},
|
|
eventType.metadata
|
|
);
|
|
}
|
|
const foundBooking = await findBookingQuery(newBooking.id);
|
|
|
|
return { ...foundBooking, appsStatus: newBooking.appsStatus };
|
|
};
|
|
|
|
export default moveSeatedBookingToNewTimeSlot;
|