diff --git a/packages/features/bookings/lib/handleConfirmation.ts b/packages/features/bookings/lib/handleConfirmation.ts
index 289e6f7148..debc12ec32 100644
--- a/packages/features/bookings/lib/handleConfirmation.ts
+++ b/packages/features/bookings/lib/handleConfirmation.ts
@@ -2,6 +2,7 @@ import type { Prisma, Workflow, WorkflowsOnEventTypes, WorkflowStep } from "@pri
import type { EventManagerUser } from "@calcom/core/EventManager";
import EventManager from "@calcom/core/EventManager";
+import { scheduleMandatoryReminder } from "@calcom/ee/workflows/lib/reminders/scheduleMandatoryReminder";
import { sendScheduledEmails } from "@calcom/emails";
import { scheduleWorkflowReminders } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler";
import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
@@ -256,27 +257,27 @@ export async function handleConfirmation(args: {
//Workflows - set reminders for confirmed events
try {
for (let index = 0; index < updatedBookings.length; index++) {
- if (updatedBookings[index].eventType?.workflows) {
- const evtOfBooking = evt;
- evtOfBooking.startTime = updatedBookings[index].startTime.toISOString();
- evtOfBooking.endTime = updatedBookings[index].endTime.toISOString();
- evtOfBooking.uid = updatedBookings[index].uid;
- const eventTypeSlug = updatedBookings[index].eventType?.slug || "";
-
- const isFirstBooking = index === 0;
-
- await scheduleWorkflowReminders({
- workflows: updatedBookings[index]?.eventType?.workflows || [],
- smsReminderNumber: updatedBookings[index].smsReminderNumber,
- calendarEvent: {
- ...evtOfBooking,
- ...{ metadata: { videoCallUrl }, eventType: { slug: eventTypeSlug } },
- },
- isFirstRecurringEvent: isFirstBooking,
- hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding,
- eventTypeRequiresConfirmation: true,
- });
- }
+ const eventTypeSlug = updatedBookings[index].eventType?.slug || "";
+ const evtOfBooking = { ...evt, metadata: { videoCallUrl }, eventType: { slug: eventTypeSlug } };
+ evtOfBooking.startTime = updatedBookings[index].startTime.toISOString();
+ evtOfBooking.endTime = updatedBookings[index].endTime.toISOString();
+ evtOfBooking.uid = updatedBookings[index].uid;
+ const isFirstBooking = index === 0;
+ await scheduleMandatoryReminder(
+ evtOfBooking,
+ updatedBookings[index]?.eventType?.workflows || [],
+ false,
+ !!updatedBookings[index].eventType?.owner?.hideBranding,
+ evt.attendeeSeatId
+ );
+ await scheduleWorkflowReminders({
+ workflows: updatedBookings[index]?.eventType?.workflows || [],
+ smsReminderNumber: updatedBookings[index].smsReminderNumber,
+ calendarEvent: evtOfBooking,
+ isFirstRecurringEvent: isFirstBooking,
+ hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding,
+ eventTypeRequiresConfirmation: true,
+ });
}
} catch (error) {
// Silently fail
diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts
index b3a4f5643c..bab66377a4 100644
--- a/packages/features/bookings/lib/handleNewBooking.ts
+++ b/packages/features/bookings/lib/handleNewBooking.ts
@@ -25,6 +25,7 @@ import { getEventName } from "@calcom/core/event";
import { getUserAvailability } from "@calcom/core/getUserAvailability";
import { deleteMeeting } from "@calcom/core/videoClient";
import dayjs from "@calcom/dayjs";
+import { scheduleMandatoryReminder } from "@calcom/ee/workflows/lib/reminders/scheduleMandatoryReminder";
import {
sendAttendeeRequestEmail,
sendOrganizerRequestEmail,
@@ -2718,15 +2719,21 @@ async function handler(
}
const metadataFromEvent = videoCallUrl ? { videoCallUrl } : undefined;
+ const evtWithMetadata = { ...evt, metadata: metadataFromEvent, eventType: { slug: eventType.slug } };
+
+ await scheduleMandatoryReminder(
+ evtWithMetadata,
+ eventType.workflows || [],
+ !isConfirmedByDefault,
+ !!eventType.owner?.hideBranding,
+ evt.attendeeSeatId
+ );
try {
await scheduleWorkflowReminders({
workflows: eventType.workflows,
smsReminderNumber: smsReminderNumber || null,
- calendarEvent: {
- ...evt,
- ...{ metadata: metadataFromEvent, eventType: { slug: eventType.slug } },
- },
+ calendarEvent: evtWithMetadata,
isNotConfirmed: !isConfirmedByDefault,
isRescheduleEvent: !!rescheduleUid,
isFirstRecurringEvent: true,
diff --git a/packages/features/ee/workflows/api/scheduleEmailReminders.ts b/packages/features/ee/workflows/api/scheduleEmailReminders.ts
index fa03762ad1..0ad746735e 100644
--- a/packages/features/ee/workflows/api/scheduleEmailReminders.ts
+++ b/packages/features/ee/workflows/api/scheduleEmailReminders.ts
@@ -6,6 +6,7 @@ import { v4 as uuidv4 } from "uuid";
import dayjs from "@calcom/dayjs";
import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses";
+import { SENDER_NAME } from "@calcom/lib/constants";
import logger from "@calcom/lib/logger";
import { defaultHandler } from "@calcom/lib/server";
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
@@ -121,100 +122,185 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
for (const reminder of unscheduledReminders) {
- if (!reminder.workflowStep || !reminder.booking) {
+ if (!reminder.booking) {
continue;
}
- try {
- let sendTo;
+ if (!reminder.isMandatoryReminder && reminder.workflowStep) {
+ try {
+ let sendTo;
- switch (reminder.workflowStep.action) {
- case WorkflowActions.EMAIL_HOST:
- sendTo = reminder.booking.user?.email;
- break;
- case WorkflowActions.EMAIL_ATTENDEE:
- sendTo = reminder.booking.attendees[0].email;
- break;
- case WorkflowActions.EMAIL_ADDRESS:
- sendTo = reminder.workflowStep.sendTo;
- }
+ switch (reminder.workflowStep.action) {
+ case WorkflowActions.EMAIL_HOST:
+ sendTo = reminder.booking.user?.email;
+ break;
+ case WorkflowActions.EMAIL_ATTENDEE:
+ sendTo = reminder.booking.attendees[0].email;
+ break;
+ case WorkflowActions.EMAIL_ADDRESS:
+ sendTo = reminder.workflowStep.sendTo;
+ }
- const name =
- reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
- ? reminder.booking.attendees[0].name
- : reminder.booking.user?.name;
+ const name =
+ reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
+ ? reminder.booking.attendees[0].name
+ : reminder.booking.user?.name;
- const attendeeName =
- reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
- ? reminder.booking.user?.name
- : reminder.booking.attendees[0].name;
+ const attendeeName =
+ reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
+ ? reminder.booking.user?.name
+ : reminder.booking.attendees[0].name;
- const timeZone =
- reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
- ? reminder.booking.attendees[0].timeZone
- : reminder.booking.user?.timeZone;
+ const timeZone =
+ reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
+ ? reminder.booking.attendees[0].timeZone
+ : reminder.booking.user?.timeZone;
- const locale =
- reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE ||
- reminder.workflowStep.action === WorkflowActions.SMS_ATTENDEE
- ? reminder.booking.attendees[0].locale
- : reminder.booking.user?.locale;
+ const locale =
+ reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE ||
+ reminder.workflowStep.action === WorkflowActions.SMS_ATTENDEE
+ ? reminder.booking.attendees[0].locale
+ : reminder.booking.user?.locale;
- let emailContent = {
- emailSubject: reminder.workflowStep.emailSubject || "",
- emailBody: `
${reminder.workflowStep.reminderBody || ""}`,
- };
-
- let emailBodyEmpty = false;
-
- if (reminder.workflowStep.reminderBody) {
- const { responses } = getCalEventResponses({
- bookingFields: reminder.booking.eventType?.bookingFields ?? null,
- booking: reminder.booking,
- });
-
- const variables: VariablesType = {
- eventName: reminder.booking.eventType?.title || "",
- organizerName: reminder.booking.user?.name || "",
- attendeeName: reminder.booking.attendees[0].name,
- attendeeEmail: reminder.booking.attendees[0].email,
- eventDate: dayjs(reminder.booking.startTime).tz(timeZone),
- eventEndTime: dayjs(reminder.booking?.endTime).tz(timeZone),
- timeZone: timeZone,
- location: reminder.booking.location || "",
- additionalNotes: reminder.booking.description,
- responses: responses,
- meetingUrl: bookingMetadataSchema.parse(reminder.booking.metadata || {})?.videoCallUrl,
- cancelLink: `/booking/${reminder.booking.uid}?cancel=true`,
- rescheduleLink: `/${reminder.booking.user?.username}/${reminder.booking.eventType?.slug}?rescheduleUid=${reminder.booking.uid}`,
+ let emailContent = {
+ emailSubject: reminder.workflowStep.emailSubject || "",
+ emailBody: `${
+ reminder.workflowStep.reminderBody || ""
+ }`,
};
- const emailLocale = locale || "en";
- const emailSubject = customTemplate(
- reminder.workflowStep.emailSubject || "",
- variables,
- emailLocale,
- getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat),
- !!reminder.booking.user?.hideBranding
- ).text;
- emailContent.emailSubject = emailSubject;
- emailContent.emailBody = customTemplate(
- reminder.workflowStep.reminderBody || "",
- variables,
- emailLocale,
- getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat),
- !!reminder.booking.user?.hideBranding
- ).html;
- emailBodyEmpty =
- customTemplate(
+ let emailBodyEmpty = false;
+
+ if (reminder.workflowStep.reminderBody) {
+ const { responses } = getCalEventResponses({
+ bookingFields: reminder.booking.eventType?.bookingFields ?? null,
+ booking: reminder.booking,
+ });
+
+ const variables: VariablesType = {
+ eventName: reminder.booking.eventType?.title || "",
+ organizerName: reminder.booking.user?.name || "",
+ attendeeName: reminder.booking.attendees[0].name,
+ attendeeEmail: reminder.booking.attendees[0].email,
+ eventDate: dayjs(reminder.booking.startTime).tz(timeZone),
+ eventEndTime: dayjs(reminder.booking?.endTime).tz(timeZone),
+ timeZone: timeZone,
+ location: reminder.booking.location || "",
+ additionalNotes: reminder.booking.description,
+ responses: responses,
+ meetingUrl: bookingMetadataSchema.parse(reminder.booking.metadata || {})?.videoCallUrl,
+ cancelLink: `/booking/${reminder.booking.uid}?cancel=true`,
+ rescheduleLink: `/${reminder.booking.user?.username}/${reminder.booking.eventType?.slug}?rescheduleUid=${reminder.booking.uid}`,
+ };
+ const emailLocale = locale || "en";
+ const emailSubject = customTemplate(
+ reminder.workflowStep.emailSubject || "",
+ variables,
+ emailLocale,
+ getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat),
+ !!reminder.booking.user?.hideBranding
+ ).text;
+ emailContent.emailSubject = emailSubject;
+ emailContent.emailBody = customTemplate(
reminder.workflowStep.reminderBody || "",
variables,
emailLocale,
- getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat)
- ).text.length === 0;
- } else if (reminder.workflowStep.template === WorkflowTemplates.REMINDER) {
+ getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat),
+ !!reminder.booking.user?.hideBranding
+ ).html;
+
+ emailBodyEmpty =
+ customTemplate(
+ reminder.workflowStep.reminderBody || "",
+ variables,
+ emailLocale,
+ getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat)
+ ).text.length === 0;
+ } else if (reminder.workflowStep.template === WorkflowTemplates.REMINDER) {
+ emailContent = emailReminderTemplate(
+ false,
+ reminder.workflowStep.action,
+ getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat),
+ reminder.booking.startTime.toISOString() || "",
+ reminder.booking.endTime.toISOString() || "",
+ reminder.booking.eventType?.title || "",
+ timeZone || "",
+ attendeeName || "",
+ name || "",
+ !!reminder.booking.user?.hideBranding
+ );
+ }
+
+ if (emailContent.emailSubject.length > 0 && !emailBodyEmpty && sendTo) {
+ const batchIdResponse = await client.request({
+ url: "/v3/mail/batch",
+ method: "POST",
+ });
+
+ const batchId = batchIdResponse[1].batch_id;
+
+ if (reminder.workflowStep.action !== WorkflowActions.EMAIL_ADDRESS) {
+ sendEmailPromises.push(
+ sgMail.send({
+ to: sendTo,
+ from: {
+ email: senderEmail,
+ name: reminder.workflowStep.sender || SENDER_NAME,
+ },
+ subject: emailContent.emailSubject,
+ html: emailContent.emailBody,
+ batchId: batchId,
+ sendAt: dayjs(reminder.scheduledDate).unix(),
+ replyTo: reminder.booking.user?.email || senderEmail,
+ mailSettings: {
+ sandboxMode: {
+ enable: sandboxMode,
+ },
+ },
+ attachments: reminder.workflowStep.includeCalendarEvent
+ ? [
+ {
+ content: Buffer.from(getiCalEventAsString(reminder.booking) || "").toString("base64"),
+ filename: "event.ics",
+ type: "text/calendar; method=REQUEST",
+ disposition: "attachment",
+ contentId: uuidv4(),
+ },
+ ]
+ : undefined,
+ })
+ );
+ }
+
+ await prisma.workflowReminder.update({
+ where: {
+ id: reminder.id,
+ },
+ data: {
+ scheduled: true,
+ referenceId: batchId,
+ },
+ });
+ }
+ } catch (error) {
+ logger.error(`Error scheduling Email with error ${error}`);
+ }
+ } else if (reminder.isMandatoryReminder) {
+ try {
+ const sendTo = reminder.booking.attendees[0].email;
+ const name = reminder.booking.attendees[0].name;
+ const attendeeName = reminder.booking.user?.name;
+ const timeZone = reminder.booking.attendees[0].timeZone;
+
+ let emailContent = {
+ emailSubject: "",
+ emailBody: "",
+ };
+
+ const emailBodyEmpty = false;
+
emailContent = emailReminderTemplate(
false,
- reminder.workflowStep.action,
+ WorkflowActions.EMAIL_ATTENDEE,
getTimeFormatStringFromUserTimeFormat(reminder.booking.user?.timeFormat),
reminder.booking.startTime.toISOString() || "",
reminder.booking.endTime.toISOString() || "",
@@ -224,23 +310,20 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
name || "",
!!reminder.booking.user?.hideBranding
);
- }
+ if (emailContent.emailSubject.length > 0 && !emailBodyEmpty && sendTo) {
+ const batchIdResponse = await client.request({
+ url: "/v3/mail/batch",
+ method: "POST",
+ });
- if (emailContent.emailSubject.length > 0 && !emailBodyEmpty && sendTo) {
- const batchIdResponse = await client.request({
- url: "/v3/mail/batch",
- method: "POST",
- });
+ const batchId = batchIdResponse[1].batch_id;
- const batchId = batchIdResponse[1].batch_id;
-
- if (reminder.workflowStep.action !== WorkflowActions.EMAIL_ADDRESS) {
sendEmailPromises.push(
sgMail.send({
to: sendTo,
from: {
email: senderEmail,
- name: reminder.workflowStep.sender || "Cal.com",
+ name: reminder.workflowStep?.sender || SENDER_NAME,
},
subject: emailContent.emailSubject,
html: emailContent.emailBody,
@@ -252,33 +335,23 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
enable: sandboxMode,
},
},
- attachments: reminder.workflowStep.includeCalendarEvent
- ? [
- {
- content: Buffer.from(getiCalEventAsString(reminder.booking) || "").toString("base64"),
- filename: "event.ics",
- type: "text/calendar; method=REQUEST",
- disposition: "attachment",
- contentId: uuidv4(),
- },
- ]
- : undefined,
+ attachments: undefined,
})
);
- }
- await prisma.workflowReminder.update({
- where: {
- id: reminder.id,
- },
- data: {
- scheduled: true,
- referenceId: batchId,
- },
- });
+ await prisma.workflowReminder.update({
+ where: {
+ id: reminder.id,
+ },
+ data: {
+ scheduled: true,
+ referenceId: batchId,
+ },
+ });
+ }
+ } catch (error) {
+ logger.error(`Error scheduling Email with error ${error}`);
}
- } catch (error) {
- logger.error(`Error scheduling Email with error ${error}`);
}
}
diff --git a/packages/features/ee/workflows/lib/getWorkflowReminders.ts b/packages/features/ee/workflows/lib/getWorkflowReminders.ts
index fe16bead7c..e251397aa4 100644
--- a/packages/features/ee/workflows/lib/getWorkflowReminders.ts
+++ b/packages/features/ee/workflows/lib/getWorkflowReminders.ts
@@ -26,7 +26,10 @@ type PartialBooking =
> & { eventType: Partial | null } & { user: Partial | null })
| null;
-export type PartialWorkflowReminder = Pick & {
+export type PartialWorkflowReminder = Pick<
+ WorkflowReminder,
+ "id" | "isMandatoryReminder" | "scheduledDate"
+> & {
booking: PartialBooking | null;
} & { workflowStep: PartialWorkflowStep };
@@ -113,6 +116,7 @@ export async function getAllUnscheduledReminders(): Promise;
-export const scheduleEmailReminder = async (
- evt: BookingInfo,
- triggerEvent: WorkflowTriggerEvents,
- action: ScheduleEmailReminderAction,
+export interface ScheduleReminderArgs {
+ evt: BookingInfo;
+ triggerEvent: WorkflowTriggerEvents;
timeSpan: {
time: number | null;
timeUnit: TimeUnit | null;
- },
- sendTo: MailData["to"],
- emailSubject: string,
- emailBody: string,
- workflowStepId: number,
- template: WorkflowTemplates,
- sender: string,
- hideBranding?: boolean,
- seatReferenceUid?: string,
- includeCalendarEvent?: boolean
-) => {
+ };
+ template: WorkflowTemplates;
+ sender?: string | null;
+ workflowStepId?: number;
+ seatReferenceUid?: string;
+}
+
+interface scheduleEmailReminderArgs extends ScheduleReminderArgs {
+ sendTo: MailData["to"];
+ action: ScheduleEmailReminderAction;
+ emailSubject?: string;
+ emailBody?: string;
+ hideBranding?: boolean;
+ includeCalendarEvent?: boolean;
+ isMandatoryReminder?: boolean;
+}
+
+export const scheduleEmailReminder = async (args: scheduleEmailReminderArgs) => {
+ const {
+ evt,
+ triggerEvent,
+ timeSpan,
+ template,
+ sender,
+ workflowStepId,
+ seatReferenceUid,
+ sendTo,
+ emailSubject = "",
+ emailBody = "",
+ hideBranding,
+ includeCalendarEvent,
+ isMandatoryReminder,
+ action,
+ } = args;
if (action === WorkflowActions.EMAIL_ADDRESS) return;
const { startTime, endTime } = evt;
const uid = evt.uid as string;
@@ -251,7 +274,7 @@ export const scheduleEmailReminder = async (
to: data.to,
from: {
email: senderEmail,
- name: sender,
+ name: sender || SENDER_NAME,
},
subject: emailContent.emailSubject,
html: emailContent.emailBody,
@@ -289,7 +312,7 @@ export const scheduleEmailReminder = async (
// TODO: Maybe don't await for this?
await Promise.all(promises);
} catch (error) {
- console.log("Error sending Email");
+ log.error("Error sending Email");
}
} else if (
(triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT ||
@@ -311,32 +334,59 @@ export const scheduleEmailReminder = async (
},
triggerEvent
);
+ if (!isMandatoryReminder) {
+ await prisma.workflowReminder.create({
+ data: {
+ bookingUid: uid,
+ workflowStepId: workflowStepId,
+ method: WorkflowMethods.EMAIL,
+ scheduledDate: scheduledDate.toDate(),
+ scheduled: true,
+ referenceId: batchId,
+ seatReferenceId: seatReferenceUid,
+ },
+ });
+ } else {
+ await prisma.workflowReminder.create({
+ data: {
+ bookingUid: uid,
+ method: WorkflowMethods.EMAIL,
+ scheduledDate: scheduledDate.toDate(),
+ scheduled: true,
+ referenceId: batchId,
+ seatReferenceId: seatReferenceUid,
+ isMandatoryReminder: true,
+ },
+ });
+ }
+ } catch (error) {
+ log.error(`Error scheduling email with error ${error}`);
+ }
+ } else if (scheduledDate.isAfter(currentDate.add(72, "hour"))) {
+ // Write to DB and send to CRON if scheduled reminder date is past 72 hours
+ if (!isMandatoryReminder) {
await prisma.workflowReminder.create({
data: {
bookingUid: uid,
workflowStepId: workflowStepId,
method: WorkflowMethods.EMAIL,
scheduledDate: scheduledDate.toDate(),
- scheduled: true,
- referenceId: batchId,
+ scheduled: false,
seatReferenceId: seatReferenceUid,
},
});
- } catch (error) {
- console.log(`Error scheduling email with error ${error}`);
+ } else {
+ await prisma.workflowReminder.create({
+ data: {
+ bookingUid: uid,
+ method: WorkflowMethods.EMAIL,
+ scheduledDate: scheduledDate.toDate(),
+ scheduled: false,
+ seatReferenceId: seatReferenceUid,
+ isMandatoryReminder: true,
+ },
+ });
}
- } else if (scheduledDate.isAfter(currentDate.add(72, "hour"))) {
- // Write to DB and send to CRON if scheduled reminder date is past 72 hours
- await prisma.workflowReminder.create({
- data: {
- bookingUid: uid,
- workflowStepId: workflowStepId,
- method: WorkflowMethods.EMAIL,
- scheduledDate: scheduledDate.toDate(),
- scheduled: false,
- seatReferenceId: seatReferenceUid,
- },
- });
}
}
};
@@ -362,6 +412,6 @@ export const deleteScheduledEmailReminder = async (reminderId: number, reference
},
});
} catch (error) {
- console.log(`Error canceling reminder with error ${error}`);
+ log.error(`Error canceling reminder with error ${error}`);
}
};
diff --git a/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts b/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts
index 7104fa1830..c23291ab94 100644
--- a/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts
+++ b/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts
@@ -1,14 +1,16 @@
import type { Workflow, WorkflowsOnEventTypes, WorkflowStep } from "@prisma/client";
import {
+ isSMSAction,
isTextMessageToAttendeeAction,
isWhatsappAction,
} from "@calcom/features/ee/workflows/lib/actionHelperFunctions";
-import { SENDER_ID, SENDER_NAME } from "@calcom/lib/constants";
+import { SENDER_NAME } from "@calcom/lib/constants";
import { WorkflowActions, WorkflowMethods, WorkflowTriggerEvents } from "@calcom/prisma/enums";
import type { CalendarEvent } from "@calcom/types/Calendar";
import { deleteScheduledEmailReminder, scheduleEmailReminder } from "./emailReminderManager";
+import type { ScheduleTextReminderAction } from "./smsReminderManager";
import { deleteScheduledSMSReminder, scheduleSMSReminder } from "./smsReminderManager";
import { deleteScheduledWhatsappReminder, scheduleWhatsappReminder } from "./whatsappReminderManager";
@@ -51,26 +53,26 @@ const processWorkflowStep = async (
) => {
if (isTextMessageToAttendeeAction(step.action) && !eventTypeRequiresConfirmation) return;
- if (step.action === WorkflowActions.SMS_ATTENDEE || step.action === WorkflowActions.SMS_NUMBER) {
+ if (isSMSAction(step.action)) {
const sendTo = step.action === WorkflowActions.SMS_ATTENDEE ? smsReminderNumber : step.sendTo;
- await scheduleSMSReminder(
+ await scheduleSMSReminder({
evt,
- sendTo,
- workflow.trigger,
- step.action,
- {
+ reminderPhone: sendTo,
+ triggerEvent: workflow.trigger,
+ action: step.action as ScheduleTextReminderAction,
+ timeSpan: {
time: workflow.time,
timeUnit: workflow.timeUnit,
},
- step.reminderBody || "",
- step.id,
- step.template,
- step.sender || SENDER_ID,
- workflow.userId,
- workflow.teamId,
- step.numberVerificationPending,
- seatReferenceUid
- );
+ message: step.reminderBody || "",
+ workflowStepId: step.id,
+ template: step.template,
+ sender: step.sender,
+ userId: workflow.userId,
+ teamId: workflow.teamId,
+ isVerificationPending: step.numberVerificationPending,
+ seatReferenceUid,
+ });
} else if (step.action === WorkflowActions.EMAIL_ATTENDEE || step.action === WorkflowActions.EMAIL_HOST) {
let sendTo: string[] = [];
@@ -88,43 +90,43 @@ const processWorkflowStep = async (
break;
}
- await scheduleEmailReminder(
+ await scheduleEmailReminder({
evt,
- workflow.trigger,
- step.action,
- {
+ triggerEvent: workflow.trigger,
+ action: step.action,
+ timeSpan: {
time: workflow.time,
timeUnit: workflow.timeUnit,
},
sendTo,
- step.emailSubject || "",
- step.reminderBody || "",
- step.id,
- step.template,
- step.sender || SENDER_NAME,
+ emailSubject: step.emailSubject || "",
+ emailBody: step.reminderBody || "",
+ template: step.template,
+ sender: step.sender || SENDER_NAME,
+ workflowStepId: step.id,
hideBranding,
seatReferenceUid,
- step.includeCalendarEvent
- );
+ includeCalendarEvent: step.includeCalendarEvent,
+ });
} else if (isWhatsappAction(step.action)) {
const sendTo = step.action === WorkflowActions.WHATSAPP_ATTENDEE ? smsReminderNumber : step.sendTo;
- await scheduleWhatsappReminder(
+ await scheduleWhatsappReminder({
evt,
- sendTo,
- workflow.trigger,
- step.action,
- {
+ reminderPhone: sendTo,
+ triggerEvent: workflow.trigger,
+ action: step.action as ScheduleTextReminderAction,
+ timeSpan: {
time: workflow.time,
timeUnit: workflow.timeUnit,
},
- step.reminderBody || "",
- step.id,
- step.template,
- workflow.userId,
- workflow.teamId,
- step.numberVerificationPending,
- seatReferenceUid
- );
+ message: step.reminderBody || "",
+ workflowStepId: step.id,
+ template: step.template,
+ userId: workflow.userId,
+ teamId: workflow.teamId,
+ isVerificationPending: step.numberVerificationPending,
+ seatReferenceUid,
+ });
}
};
@@ -164,7 +166,6 @@ export const scheduleWorkflowReminders = async (args: ScheduleWorkflowRemindersA
) {
continue;
}
-
for (const step of workflow.steps) {
await processWorkflowStep(workflow, step, {
calendarEvent: evt,
diff --git a/packages/features/ee/workflows/lib/reminders/scheduleMandatoryReminder.ts b/packages/features/ee/workflows/lib/reminders/scheduleMandatoryReminder.ts
new file mode 100644
index 0000000000..3512e9f9f1
--- /dev/null
+++ b/packages/features/ee/workflows/lib/reminders/scheduleMandatoryReminder.ts
@@ -0,0 +1,72 @@
+import type { Workflow, WorkflowsOnEventTypes, WorkflowStep } from "@prisma/client";
+
+import type { getEventTypesFromDB } from "@calcom/features/bookings/lib/handleNewBooking";
+import { scheduleEmailReminder } from "@calcom/features/ee/workflows/lib/reminders/emailReminderManager";
+import type { BookingInfo } from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager";
+import type { getDefaultEvent } from "@calcom/lib/defaultEvents";
+import logger from "@calcom/lib/logger";
+import { WorkflowTriggerEvents, TimeUnit, WorkflowActions, WorkflowTemplates } from "@calcom/prisma/enums";
+
+const log = logger.getSubLogger({ prefix: ["[scheduleMandatoryReminder]"] });
+
+export type NewBookingEventType =
+ | Awaited>
+ | Awaited>;
+
+export async function scheduleMandatoryReminder(
+ evt: BookingInfo,
+ workflows: (WorkflowsOnEventTypes & {
+ workflow: Workflow & {
+ steps: WorkflowStep[];
+ };
+ })[],
+ requiresConfirmation: boolean,
+ hideBranding: boolean,
+ seatReferenceUid: string | undefined
+) {
+ try {
+ const hasExistingWorkflow = workflows.some((workflow) => {
+ return (
+ workflow.workflow?.trigger === WorkflowTriggerEvents.BEFORE_EVENT &&
+ ((workflow.workflow.time !== null &&
+ workflow.workflow.time <= 12 &&
+ workflow.workflow?.timeUnit === TimeUnit.HOUR) ||
+ (workflow.workflow.time !== null &&
+ workflow.workflow.time <= 720 &&
+ workflow.workflow?.timeUnit === TimeUnit.MINUTE)) &&
+ workflow.workflow?.steps.some((step) => step?.action === WorkflowActions.EMAIL_ATTENDEE)
+ );
+ });
+
+ if (
+ !hasExistingWorkflow &&
+ evt.attendees.some((attendee) => attendee.email.includes("@gmail.com")) &&
+ !requiresConfirmation
+ ) {
+ try {
+ const filteredAttendees =
+ evt.attendees?.filter((attendee) => attendee.email.includes("@gmail.com")) || [];
+
+ await scheduleEmailReminder({
+ evt,
+ triggerEvent: WorkflowTriggerEvents.BEFORE_EVENT,
+ action: WorkflowActions.EMAIL_ATTENDEE,
+ timeSpan: {
+ time: 1,
+ timeUnit: TimeUnit.HOUR,
+ },
+ sendTo: filteredAttendees,
+ template: WorkflowTemplates.REMINDER,
+ hideBranding,
+ seatReferenceUid,
+ includeCalendarEvent: false,
+ isMandatoryReminder: true,
+ });
+ } catch (error) {
+ log.error("Error while scheduling mandatory reminders", JSON.stringify({ error }));
+ }
+ }
+ } catch (error) {
+ log.error("Error while scheduling mandatory reminders", JSON.stringify({ error }));
+ }
+}
diff --git a/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts b/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts
index 10fb2166d1..71a24f1345 100644
--- a/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts
+++ b/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts
@@ -1,15 +1,16 @@
import dayjs from "@calcom/dayjs";
+import { SENDER_ID } from "@calcom/lib/constants";
import logger from "@calcom/lib/logger";
import type { TimeFormat } from "@calcom/lib/timeFormat";
import prisma from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";
-import type { TimeUnit } from "@calcom/prisma/enums";
import { WorkflowTemplates, WorkflowActions, WorkflowMethods } from "@calcom/prisma/enums";
import { WorkflowTriggerEvents } from "@calcom/prisma/enums";
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
import type { CalEventResponses, RecurringEvent } from "@calcom/types/Calendar";
import { getSenderId } from "../alphanumericSenderIdSupport";
+import type { ScheduleReminderArgs } from "./emailReminderManager";
import * as twilio from "./smsProviders/twilioProvider";
import type { VariablesType } from "./templates/customTemplate";
import customTemplate from "./templates/customTemplate";
@@ -55,33 +56,42 @@ export type BookingInfo = {
metadata?: Prisma.JsonValue;
};
-type ScheduleSMSReminderAction = Extract;
+export type ScheduleTextReminderAction = Extract<
+ WorkflowActions,
+ "SMS_ATTENDEE" | "SMS_NUMBER" | "WHATSAPP_ATTENDEE" | "WHATSAPP_NUMBER"
+>;
+export interface ScheduleTextReminderArgs extends ScheduleReminderArgs {
+ reminderPhone: string | null;
+ message: string;
+ action: ScheduleTextReminderAction;
+ userId?: number | null;
+ teamId?: number | null;
+ isVerificationPending?: boolean;
+}
-export const scheduleSMSReminder = async (
- evt: BookingInfo,
- reminderPhone: string | null,
- triggerEvent: WorkflowTriggerEvents,
- action: ScheduleSMSReminderAction,
- timeSpan: {
- time: number | null;
- timeUnit: TimeUnit | null;
- },
- message: string,
- workflowStepId: number,
- template: WorkflowTemplates,
- sender: string,
- userId?: number | null,
- teamId?: number | null,
- isVerificationPending = false,
- seatReferenceUid?: string
-) => {
+export const scheduleSMSReminder = async (args: ScheduleTextReminderArgs) => {
+ const {
+ evt,
+ reminderPhone,
+ triggerEvent,
+ action,
+ timeSpan,
+ message = "",
+ workflowStepId,
+ template,
+ sender,
+ userId,
+ teamId,
+ isVerificationPending = false,
+ seatReferenceUid,
+ } = args;
const { startTime, endTime } = evt;
const uid = evt.uid as string;
const currentDate = dayjs();
const timeUnit: timeUnitLowerCase | undefined = timeSpan.timeUnit?.toLocaleLowerCase() as timeUnitLowerCase;
let scheduledDate = null;
- const senderID = getSenderId(reminderPhone, sender);
+ const senderID = getSenderId(reminderPhone, sender || SENDER_ID);
//SMS_ATTENDEE action does not need to be verified
//isVerificationPending is from all already existing workflows (once they edit their workflow, they will also have to verify the number)
@@ -126,7 +136,9 @@ export const scheduleSMSReminder = async (
? attendeeToBeUsedInSMS.language?.locale
: evt.organizer.language.locale;
- if (message) {
+ let smsMessage = message;
+
+ if (smsMessage) {
const variables: VariablesType = {
eventName: evt.title,
organizerName: evt.organizer.name,
@@ -144,10 +156,10 @@ export const scheduleSMSReminder = async (
cancelLink: `/booking/${evt.uid}?cancel=true`,
rescheduleLink: `/${evt.organizer.username}/${evt.eventType.slug}?rescheduleUid=${evt.uid}`,
};
- const customMessage = customTemplate(message, variables, locale, evt.organizer.timeFormat);
- message = customMessage.text;
+ const customMessage = customTemplate(smsMessage, variables, locale, evt.organizer.timeFormat);
+ smsMessage = customMessage.text;
} else if (template === WorkflowTemplates.REMINDER) {
- message =
+ smsMessage =
smsReminderTemplate(
false,
action,
@@ -161,9 +173,9 @@ export const scheduleSMSReminder = async (
}
// Allows debugging generated email content without waiting for sendgrid to send emails
- log.debug(`Sending sms for trigger ${triggerEvent}`, message);
+ log.debug(`Sending sms for trigger ${triggerEvent}`, smsMessage);
- if (message.length > 0 && reminderPhone && isNumberVerified) {
+ if (smsMessage.length > 0 && reminderPhone && isNumberVerified) {
//send SMS when event is booked/cancelled/rescheduled
if (
triggerEvent === WorkflowTriggerEvents.NEW_EVENT ||
@@ -171,9 +183,9 @@ export const scheduleSMSReminder = async (
triggerEvent === WorkflowTriggerEvents.RESCHEDULE_EVENT
) {
try {
- await twilio.sendSMS(reminderPhone, message, senderID);
+ await twilio.sendSMS(reminderPhone, smsMessage, senderID);
} catch (error) {
- console.log(`Error sending SMS with error ${error}`);
+ log.error(`Error sending SMS with error ${error}`);
}
} else if (
(triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT ||
@@ -188,7 +200,7 @@ export const scheduleSMSReminder = async (
try {
const scheduledSMS = await twilio.scheduleSMS(
reminderPhone,
- message,
+ smsMessage,
scheduledDate.toDate(),
senderID
);
@@ -205,7 +217,7 @@ export const scheduleSMSReminder = async (
},
});
} catch (error) {
- console.log(`Error scheduling SMS with error ${error}`);
+ log.error(`Error scheduling SMS with error ${error}`);
}
} else if (scheduledDate.isAfter(currentDate.add(7, "day"))) {
// Write to DB and send to CRON if scheduled reminder date is past 7 days
@@ -236,6 +248,6 @@ export const deleteScheduledSMSReminder = async (reminderId: number, referenceId
},
});
} catch (error) {
- console.log(`Error canceling reminder with error ${error}`);
+ log.error(`Error canceling reminder with error ${error}`);
}
};
diff --git a/packages/features/ee/workflows/lib/reminders/whatsappReminderManager.ts b/packages/features/ee/workflows/lib/reminders/whatsappReminderManager.ts
index 2945f0e55e..07a774aa9b 100644
--- a/packages/features/ee/workflows/lib/reminders/whatsappReminderManager.ts
+++ b/packages/features/ee/workflows/lib/reminders/whatsappReminderManager.ts
@@ -1,5 +1,3 @@
-import type { TimeUnit } from "@prisma/client";
-
import dayjs from "@calcom/dayjs";
import logger from "@calcom/lib/logger";
import prisma from "@calcom/prisma";
@@ -11,7 +9,7 @@ import {
} from "@calcom/prisma/enums";
import * as twilio from "./smsProviders/twilioProvider";
-import type { BookingInfo, timeUnitLowerCase } from "./smsReminderManager";
+import type { ScheduleTextReminderArgs, timeUnitLowerCase } from "./smsReminderManager";
import { deleteScheduledSMSReminder } from "./smsReminderManager";
import {
whatsappEventCancelledTemplate,
@@ -22,23 +20,21 @@ import {
const log = logger.getSubLogger({ prefix: ["[whatsappReminderManager]"] });
-export const scheduleWhatsappReminder = async (
- evt: BookingInfo,
- reminderPhone: string | null,
- triggerEvent: WorkflowTriggerEvents,
- action: WorkflowActions,
- timeSpan: {
- time: number | null;
- timeUnit: TimeUnit | null;
- },
- message: string,
- workflowStepId: number,
- template: WorkflowTemplates,
- userId?: number | null,
- teamId?: number | null,
- isVerificationPending = false,
- seatReferenceUid?: string
-) => {
+export const scheduleWhatsappReminder = async (args: ScheduleTextReminderArgs) => {
+ const {
+ evt,
+ reminderPhone,
+ triggerEvent,
+ action,
+ timeSpan,
+ message = "",
+ workflowStepId,
+ template,
+ userId,
+ teamId,
+ isVerificationPending = false,
+ seatReferenceUid,
+ } = args;
const { startTime, endTime } = evt;
const uid = evt.uid as string;
const currentDate = dayjs();
@@ -72,9 +68,11 @@ export const scheduleWhatsappReminder = async (
const timeZone =
action === WorkflowActions.WHATSAPP_ATTENDEE ? evt.attendees[0].timeZone : evt.organizer.timeZone;
+ let textMessage = message;
+
switch (template) {
case WorkflowTemplates.REMINDER:
- message =
+ textMessage =
whatsappReminderTemplate(
false,
action,
@@ -87,7 +85,7 @@ export const scheduleWhatsappReminder = async (
) || message;
break;
case WorkflowTemplates.CANCELLED:
- message =
+ textMessage =
whatsappEventCancelledTemplate(
false,
action,
@@ -100,7 +98,7 @@ export const scheduleWhatsappReminder = async (
) || message;
break;
case WorkflowTemplates.RESCHEDULED:
- message =
+ textMessage =
whatsappEventRescheduledTemplate(
false,
action,
@@ -113,7 +111,7 @@ export const scheduleWhatsappReminder = async (
) || message;
break;
case WorkflowTemplates.COMPLETED:
- message =
+ textMessage =
whatsappEventCompletedTemplate(
false,
action,
@@ -126,7 +124,7 @@ export const scheduleWhatsappReminder = async (
) || message;
break;
default:
- message =
+ textMessage =
whatsappReminderTemplate(
false,
action,
@@ -140,8 +138,8 @@ export const scheduleWhatsappReminder = async (
}
// Allows debugging generated whatsapp content without waiting for twilio to send whatsapp messages
- log.debug(`Sending Whatsapp for trigger ${triggerEvent}`, message);
- if (message.length > 0 && reminderPhone && isNumberVerified) {
+ log.debug(`Sending Whatsapp for trigger ${triggerEvent}`, textMessage);
+ if (textMessage.length > 0 && reminderPhone && isNumberVerified) {
//send WHATSAPP when event is booked/cancelled/rescheduled
if (
triggerEvent === WorkflowTriggerEvents.NEW_EVENT ||
@@ -149,7 +147,7 @@ export const scheduleWhatsappReminder = async (
triggerEvent === WorkflowTriggerEvents.RESCHEDULE_EVENT
) {
try {
- await twilio.sendSMS(reminderPhone, message, "", true);
+ await twilio.sendSMS(reminderPhone, textMessage, "", true);
} catch (error) {
console.log(`Error sending WHATSAPP with error ${error}`);
}
@@ -166,7 +164,7 @@ export const scheduleWhatsappReminder = async (
try {
const scheduledWHATSAPP = await twilio.scheduleSMS(
reminderPhone,
- message,
+ textMessage,
scheduledDate.toDate(),
"",
true
diff --git a/packages/prisma/migrations/20231203154633_adding_is_mandatory_reminder_field_for_mandatory_reminders/migration.sql b/packages/prisma/migrations/20231203154633_adding_is_mandatory_reminder_field_for_mandatory_reminders/migration.sql
new file mode 100644
index 0000000000..c9da8290d3
--- /dev/null
+++ b/packages/prisma/migrations/20231203154633_adding_is_mandatory_reminder_field_for_mandatory_reminders/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "WorkflowReminder" ADD COLUMN "isMandatoryReminder" BOOLEAN DEFAULT false;
diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma
index b65a687acb..70b3821e63 100644
--- a/packages/prisma/schema.prisma
+++ b/packages/prisma/schema.prisma
@@ -823,17 +823,18 @@ enum TimeUnit {
}
model WorkflowReminder {
- id Int @id @default(autoincrement())
- bookingUid String?
- booking Booking? @relation(fields: [bookingUid], references: [uid])
- method WorkflowMethods
- scheduledDate DateTime
- referenceId String? @unique
- scheduled Boolean
- workflowStepId Int?
- workflowStep WorkflowStep? @relation(fields: [workflowStepId], references: [id])
- cancelled Boolean?
- seatReferenceId String?
+ id Int @id @default(autoincrement())
+ bookingUid String?
+ booking Booking? @relation(fields: [bookingUid], references: [uid])
+ method WorkflowMethods
+ scheduledDate DateTime
+ referenceId String? @unique
+ scheduled Boolean
+ workflowStepId Int?
+ workflowStep WorkflowStep? @relation(fields: [workflowStepId], references: [id])
+ cancelled Boolean?
+ seatReferenceId String?
+ isMandatoryReminder Boolean? @default(false)
@@index([bookingUid])
@@index([workflowStepId])
diff --git a/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts b/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts
index a8f8c0e861..1068ab3fb4 100644
--- a/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts
+++ b/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts
@@ -10,7 +10,6 @@ import {
deleteScheduledWhatsappReminder,
scheduleWhatsappReminder,
} from "@calcom/features/ee/workflows/lib/reminders/whatsappReminderManager";
-import { SENDER_ID, SENDER_NAME } from "@calcom/lib/constants";
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
import { prisma } from "@calcom/prisma";
import { BookingStatus } from "@calcom/prisma/client";
@@ -197,54 +196,54 @@ export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventType
break;
}
- await scheduleEmailReminder(
- bookingInfo,
- eventTypeWorkflow.trigger,
- step.action,
- {
+ await scheduleEmailReminder({
+ evt: bookingInfo,
+ triggerEvent: eventTypeWorkflow.trigger,
+ action: step.action,
+ timeSpan: {
time: eventTypeWorkflow.time,
timeUnit: eventTypeWorkflow.timeUnit,
},
sendTo,
- step.emailSubject || "",
- step.reminderBody || "",
- step.id,
- step.template,
- step.sender || SENDER_NAME
- );
+ emailSubject: step.emailSubject || "",
+ emailBody: step.reminderBody || "",
+ template: step.template,
+ sender: step.sender,
+ workflowStepId: step.id,
+ });
} else if (step.action === WorkflowActions.SMS_NUMBER && step.sendTo) {
- await scheduleSMSReminder(
- bookingInfo,
- step.sendTo,
- eventTypeWorkflow.trigger,
- step.action,
- {
+ await scheduleSMSReminder({
+ evt: bookingInfo,
+ reminderPhone: step.sendTo,
+ triggerEvent: eventTypeWorkflow.trigger,
+ action: step.action,
+ timeSpan: {
time: eventTypeWorkflow.time,
timeUnit: eventTypeWorkflow.timeUnit,
},
- step.reminderBody || "",
- step.id,
- step.template,
- step.sender || SENDER_ID,
- booking.userId,
- eventTypeWorkflow.teamId
- );
+ message: step.reminderBody || "",
+ workflowStepId: step.id,
+ template: step.template,
+ sender: step.sender,
+ userId: booking.userId,
+ teamId: eventTypeWorkflow.teamId,
+ });
} else if (step.action === WorkflowActions.WHATSAPP_NUMBER && step.sendTo) {
- await scheduleWhatsappReminder(
- bookingInfo,
- step.sendTo,
- eventTypeWorkflow.trigger,
- step.action,
- {
+ await scheduleWhatsappReminder({
+ evt: bookingInfo,
+ reminderPhone: step.sendTo,
+ triggerEvent: eventTypeWorkflow.trigger,
+ action: step.action,
+ timeSpan: {
time: eventTypeWorkflow.time,
timeUnit: eventTypeWorkflow.timeUnit,
},
- step.reminderBody || "",
- step.id,
- step.template,
- booking.userId,
- eventTypeWorkflow.teamId
- );
+ message: step.reminderBody || "",
+ workflowStepId: step.id,
+ template: step.template,
+ userId: booking.userId,
+ teamId: eventTypeWorkflow.teamId,
+ });
}
}
}
diff --git a/packages/trpc/server/routers/viewer/workflows/update.handler.ts b/packages/trpc/server/routers/viewer/workflows/update.handler.ts
index 5799f96756..567dbedce8 100644
--- a/packages/trpc/server/routers/viewer/workflows/update.handler.ts
+++ b/packages/trpc/server/routers/viewer/workflows/update.handler.ts
@@ -17,7 +17,7 @@ import {
deleteScheduledWhatsappReminder,
scheduleWhatsappReminder,
} from "@calcom/features/ee/workflows/lib/reminders/whatsappReminderManager";
-import { IS_SELF_HOSTED, SENDER_ID, SENDER_NAME } from "@calcom/lib/constants";
+import { IS_SELF_HOSTED } from "@calcom/lib/constants";
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
import type { PrismaClient } from "@calcom/prisma";
@@ -315,54 +315,54 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
sendTo = step.sendTo || "";*/
}
- await scheduleEmailReminder(
- bookingInfo,
- trigger,
- step.action,
- {
+ await scheduleEmailReminder({
+ evt: bookingInfo,
+ triggerEvent: trigger,
+ action: step.action,
+ timeSpan: {
time,
timeUnit,
},
sendTo,
- step.emailSubject || "",
- step.reminderBody || "",
- step.id,
- step.template,
- step.senderName || SENDER_NAME
- );
+ emailSubject: step.emailSubject || "",
+ emailBody: step.reminderBody || "",
+ template: step.template,
+ sender: step.senderName,
+ workflowStepId: step.id,
+ });
} else if (step.action === WorkflowActions.SMS_NUMBER) {
- await scheduleSMSReminder(
- bookingInfo,
- step.sendTo || "",
- trigger,
- step.action,
- {
+ await scheduleSMSReminder({
+ evt: bookingInfo,
+ reminderPhone: step.sendTo || "",
+ triggerEvent: trigger,
+ action: step.action,
+ timeSpan: {
time,
timeUnit,
},
- step.reminderBody || "",
- step.id,
- step.template,
- step.sender || SENDER_ID,
- user.id,
- userWorkflow.teamId
- );
+ message: step.reminderBody || "",
+ workflowStepId: step.id,
+ template: step.template,
+ sender: step.sender,
+ userId: user.id,
+ teamId: userWorkflow.teamId,
+ });
} else if (step.action === WorkflowActions.WHATSAPP_NUMBER) {
- await scheduleWhatsappReminder(
- bookingInfo,
- step.sendTo || "",
- trigger,
- step.action,
- {
+ await scheduleWhatsappReminder({
+ evt: bookingInfo,
+ reminderPhone: step.sendTo || "",
+ triggerEvent: trigger,
+ action: step.action,
+ timeSpan: {
time,
timeUnit,
},
- step.reminderBody || "",
- step.id || 0,
- step.template,
- user.id,
- userWorkflow.teamId
- );
+ message: step.reminderBody || "",
+ workflowStepId: step.id || 0,
+ template: step.template,
+ userId: user.id,
+ teamId: userWorkflow.teamId,
+ });
}
});
await Promise.all(promiseScheduleReminders);
@@ -552,54 +552,54 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
sendTo = newStep.sendTo || "";*/
}
- await scheduleEmailReminder(
- bookingInfo,
- trigger,
- newStep.action,
- {
+ await scheduleEmailReminder({
+ evt: bookingInfo,
+ triggerEvent: trigger,
+ action: newStep.action,
+ timeSpan: {
time,
timeUnit,
},
sendTo,
- newStep.emailSubject || "",
- newStep.reminderBody || "",
- newStep.id,
- newStep.template,
- newStep.senderName || SENDER_NAME
- );
+ emailSubject: newStep.emailSubject || "",
+ emailBody: newStep.reminderBody || "",
+ template: newStep.template,
+ sender: newStep.senderName,
+ workflowStepId: newStep.id,
+ });
} else if (newStep.action === WorkflowActions.SMS_NUMBER) {
- await scheduleSMSReminder(
- bookingInfo,
- newStep.sendTo || "",
- trigger,
- newStep.action,
- {
+ await scheduleSMSReminder({
+ evt: bookingInfo,
+ reminderPhone: newStep.sendTo || "",
+ triggerEvent: trigger,
+ action: newStep.action,
+ timeSpan: {
time,
timeUnit,
},
- newStep.reminderBody || "",
- newStep.id || 0,
- newStep.template,
- newStep.sender || SENDER_ID,
- user.id,
- userWorkflow.teamId
- );
+ message: newStep.reminderBody || "",
+ workflowStepId: newStep.id || 0,
+ template: newStep.template,
+ sender: newStep.sender,
+ userId: user.id,
+ teamId: userWorkflow.teamId,
+ });
} else if (newStep.action === WorkflowActions.WHATSAPP_NUMBER) {
- await scheduleWhatsappReminder(
- bookingInfo,
- newStep.sendTo || "",
- trigger,
- newStep.action,
- {
+ await scheduleWhatsappReminder({
+ evt: bookingInfo,
+ reminderPhone: newStep.sendTo || "",
+ triggerEvent: trigger,
+ action: newStep.action,
+ timeSpan: {
time,
timeUnit,
},
- newStep.reminderBody || "",
- newStep.id || 0,
- newStep.template,
- user.id,
- userWorkflow.teamId
- );
+ message: newStep.reminderBody || "",
+ workflowStepId: newStep.id || 0,
+ template: newStep.template,
+ userId: user.id,
+ teamId: userWorkflow.teamId,
+ });
}
});
await Promise.all(promiseScheduleReminders);
@@ -703,54 +703,54 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
sendTo = step.sendTo || "";*/
}
- await scheduleEmailReminder(
- bookingInfo,
- trigger,
- step.action,
- {
+ await scheduleEmailReminder({
+ evt: bookingInfo,
+ triggerEvent: trigger,
+ action: step.action,
+ timeSpan: {
time,
timeUnit,
},
sendTo,
- step.emailSubject || "",
- step.reminderBody || "",
- createdStep.id,
- step.template,
- step.senderName || SENDER_NAME
- );
+ emailSubject: step.emailSubject || "",
+ emailBody: step.reminderBody || "",
+ template: step.template,
+ sender: step.senderName,
+ workflowStepId: createdStep.id,
+ });
} else if (step.action === WorkflowActions.SMS_NUMBER && step.sendTo) {
- await scheduleSMSReminder(
- bookingInfo,
- step.sendTo,
- trigger,
- step.action,
- {
+ await scheduleSMSReminder({
+ evt: bookingInfo,
+ reminderPhone: step.sendTo,
+ triggerEvent: trigger,
+ action: step.action,
+ timeSpan: {
time,
timeUnit,
},
- step.reminderBody || "",
- createdStep.id,
- step.template,
- step.sender || SENDER_ID,
- user.id,
- userWorkflow.teamId
- );
+ message: step.reminderBody || "",
+ workflowStepId: createdStep.id,
+ template: step.template,
+ sender: step.sender,
+ userId: user.id,
+ teamId: userWorkflow.teamId,
+ });
} else if (step.action === WorkflowActions.WHATSAPP_NUMBER && step.sendTo) {
- await scheduleWhatsappReminder(
- bookingInfo,
- step.sendTo,
- trigger,
- step.action,
- {
+ await scheduleWhatsappReminder({
+ evt: bookingInfo,
+ reminderPhone: step.sendTo,
+ triggerEvent: trigger,
+ action: step.action,
+ timeSpan: {
time,
timeUnit,
},
- step.reminderBody || "",
- createdStep.id,
- step.template,
- user.id,
- userWorkflow.teamId
- );
+ message: step.reminderBody || "",
+ workflowStepId: createdStep.id,
+ template: step.template,
+ userId: user.id,
+ teamId: userWorkflow.teamId,
+ });
}
}
}