diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 3b64f74d62..42b54203a9 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -2031,8 +2031,12 @@ "event_end_time_info": "The event end time", "cancel_url_variable": "Cancel URL", "cancel_url_info": "The URL to cancel the booking", + "cancel_reason_variable": "Cancellation Reason", + "cancel_reason_info": "The reason for canceling the booking", "reschedule_url_variable": "Reschedule URL", "reschedule_url_info": "The URL to reschedule the booking", + "reschedule_reason_variable": "Reschedule Reason", + "reschedule_reason_info": "The reason for rescheduling the booking", "invalid_event_name_variables": "{{item}} is an invalid variable in your event name", "select_all": "Select All", "default_conferencing_bulk_title": "Bulk update existing event types", diff --git a/packages/features/bookings/lib/handleConfirmation.ts b/packages/features/bookings/lib/handleConfirmation.ts index 75510ed52e..35235757c9 100644 --- a/packages/features/bookings/lib/handleConfirmation.ts +++ b/packages/features/bookings/lib/handleConfirmation.ts @@ -152,6 +152,7 @@ export async function handleConfirmation(args: { endTime: Date; uid: string; smsReminderNumber: string | null; + cancellationReason?: string | null; metadata: Prisma.JsonValue | null; customInputs: Prisma.JsonValue; eventType: { @@ -229,6 +230,7 @@ export async function handleConfirmation(args: { }, }, description: true, + cancellationReason: true, attendees: true, location: true, uid: true, @@ -291,6 +293,7 @@ export async function handleConfirmation(args: { uid: true, startTime: true, metadata: true, + cancellationReason: true, endTime: true, smsReminderNumber: true, description: true, @@ -324,6 +327,7 @@ export async function handleConfirmation(args: { const eventTypeSlug = updatedBookings[index].eventType?.slug || ""; const evtOfBooking = { ...evt, + rescheduleReason: updatedBookings[index].cancellationReason || null, metadata: { videoCallUrl: meetingUrl }, eventType: { slug: eventTypeSlug, diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index 20b16dfa31..d7e1666f16 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -1941,6 +1941,7 @@ async function handler( const evtWithMetadata = { ...evt, + rescheduleReason, metadata, eventType: { slug: eventType.slug, schedulingType: eventType.schedulingType, hosts: eventType.hosts }, bookerUrl, diff --git a/packages/features/bookings/lib/handleSeats/handleSeats.ts b/packages/features/bookings/lib/handleSeats/handleSeats.ts index c4d4b672ac..251096770f 100644 --- a/packages/features/bookings/lib/handleSeats/handleSeats.ts +++ b/packages/features/bookings/lib/handleSeats/handleSeats.ts @@ -32,6 +32,7 @@ const handleSeats = async (newSeatedBookingObject: NewSeatedBookingObject) => { evt, workflows, rescheduledBy, + rescheduleReason, isDryRun = false, } = newSeatedBookingObject; // TODO: We could allow doing more things to support good dry run for seats @@ -112,6 +113,7 @@ const handleSeats = async (newSeatedBookingObject: NewSeatedBookingObject) => { smsReminderNumber: smsReminderNumber || null, calendarEvent: { ...evt, + rescheduleReason, ...{ metadata, eventType: { diff --git a/packages/features/ee/workflows/lib/constants.ts b/packages/features/ee/workflows/lib/constants.ts index b57020d7bf..c288e37ff2 100644 --- a/packages/features/ee/workflows/lib/constants.ts +++ b/packages/features/ee/workflows/lib/constants.ts @@ -61,7 +61,9 @@ export const DYNAMIC_TEXT_VARIABLES = [ "additional_notes", "meeting_url", "cancel_url", + "cancel_reason", "reschedule_url", + "reschedule_reason", "rating_url", "no_show_url", "attendee_timezone", diff --git a/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts b/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts index 6ca689aab7..1cc6453b2a 100644 --- a/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts +++ b/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts @@ -160,7 +160,9 @@ export const scheduleEmailReminder = async (args: scheduleEmailReminderArgs) => responses: evt.responses, meetingUrl: bookingMetadataSchema.parse(evt.metadata || {})?.videoCallUrl, cancelLink: `${bookerUrl}/booking/${evt.uid}?cancel=true`, + cancelReason: evt.cancellationReason, rescheduleLink: `${bookerUrl}/reschedule/${evt.uid}`, + rescheduleReason: evt.rescheduleReason, ratingUrl: `${bookerUrl}/booking/${evt.uid}?rating`, noShowUrl: `${bookerUrl}/booking/${evt.uid}?noShow=true`, attendeeTimezone: evt.attendees[0].timeZone, diff --git a/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts b/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts index cd8875f02d..c3325838df 100644 --- a/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts +++ b/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts @@ -21,6 +21,8 @@ export type ExtendedCalendarEvent = Omit & { schedulingType?: SchedulingType | null; hosts?: { user: { email: string; destinationCalendar?: { primaryEmail: string | null } | null } }[]; }; + rescheduleReason?: string | null; + cancellationReason?: string | null; bookerUrl: string; }; diff --git a/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts b/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts index b3de73dc02..25269ef38e 100644 --- a/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts +++ b/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts @@ -57,6 +57,8 @@ export type BookingInfo = { additionalNotes?: string | null; responses?: CalEventResponses | null; metadata?: Prisma.JsonValue; + cancellationReason?: string | null; + rescheduleReason?: string | null; }; export type ScheduleTextReminderAction = Extract< @@ -159,7 +161,9 @@ export const scheduleSMSReminder = async (args: ScheduleTextReminderArgs) => { responses: evt.responses, meetingUrl: bookingMetadataSchema.parse(evt.metadata || {})?.videoCallUrl, cancelLink: `${evt.bookerUrl ?? WEBSITE_URL}/booking/${evt.uid}?cancel=true`, + cancelReason: evt.cancellationReason, rescheduleLink: `${evt.bookerUrl ?? WEBSITE_URL}/reschedule/${evt.uid}`, + rescheduleReason: evt.rescheduleReason, attendeeTimezone: evt.attendees[0].timeZone, eventTimeInAttendeeTimezone: dayjs(evt.startTime).tz(evt.attendees[0].timeZone), eventEndTimeInAttendeeTimezone: dayjs(evt.endTime).tz(evt.attendees[0].timeZone), diff --git a/packages/features/ee/workflows/lib/reminders/templates/customTemplate.ts b/packages/features/ee/workflows/lib/reminders/templates/customTemplate.ts index d44c5ed6a6..27c5c421a4 100644 --- a/packages/features/ee/workflows/lib/reminders/templates/customTemplate.ts +++ b/packages/features/ee/workflows/lib/reminders/templates/customTemplate.ts @@ -20,7 +20,9 @@ export type VariablesType = { responses?: CalEventResponses | null; meetingUrl?: string; cancelLink?: string; + cancelReason?: string | null; rescheduleLink?: string; + rescheduleReason?: string | null; ratingUrl?: string; noShowUrl?: string; attendeeTimezone?: string; @@ -83,7 +85,9 @@ const customTemplate = ( .replaceAll("{ATTENDEE_EMAIL}", variables.attendeeEmail || "") .replaceAll("{TIMEZONE}", variables.timeZone || "") .replaceAll("{CANCEL_URL}", cancelLink) + .replaceAll("{CANCELLATION_REASON}", variables.cancelReason || "") .replaceAll("{RESCHEDULE_URL}", rescheduleLink) + .replaceAll("{RESCHEDULE_REASON}", variables.rescheduleReason || "") .replaceAll("{MEETING_URL}", variables.meetingUrl || "") .replaceAll("{RATING_URL}", variables.ratingUrl || "") .replaceAll("{NO_SHOW_URL}", variables.noShowUrl || "")