diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json
index b943fd986b..424a7441a7 100644
--- a/apps/web/public/static/locales/en/common.json
+++ b/apps/web/public/static/locales/en/common.json
@@ -1295,5 +1295,7 @@
"update_timezone": "Update timezone",
"update_timezone_question": "Update Timezone?",
"update_timezone_description": "It seems like your local timezone has changed to {{formattedCurrentTz}}. It's very important to have the correct timezone to prevent bookings at undesired times. Do you want to update it?",
- "dont_update": "Don't update"
+ "dont_update": "Don't update",
+ "after_event_trigger": "after event ends",
+ "how_long_after": "How long after event ends?"
}
diff --git a/packages/features/ee/workflows/components/v2/WorkflowStepContainer.tsx b/packages/features/ee/workflows/components/v2/WorkflowStepContainer.tsx
index 2b133b6b2b..c1931d85e5 100644
--- a/packages/features/ee/workflows/components/v2/WorkflowStepContainer.tsx
+++ b/packages/features/ee/workflows/components/v2/WorkflowStepContainer.tsx
@@ -60,7 +60,12 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
);
const [showTimeSection, setShowTimeSection] = useState(
- form.getValues("trigger") === WorkflowTriggerEvents.BEFORE_EVENT ? true : false
+ form.getValues("trigger") === WorkflowTriggerEvents.BEFORE_EVENT ||
+ form.getValues("trigger") === WorkflowTriggerEvents.AFTER_EVENT
+ );
+
+ const [showTimeSectionAfter, setShowTimeSectionAfter] = useState(
+ form.getValues("trigger") === WorkflowTriggerEvents.AFTER_EVENT
);
const actionOptions = getWorkflowActionOptions(t);
@@ -147,12 +152,21 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
onChange={(val) => {
if (val) {
form.setValue("trigger", val.value);
- if (val.value === WorkflowTriggerEvents.BEFORE_EVENT) {
+ if (
+ val.value === WorkflowTriggerEvents.BEFORE_EVENT ||
+ val.value === WorkflowTriggerEvents.AFTER_EVENT
+ ) {
setShowTimeSection(true);
+ if (val.value === WorkflowTriggerEvents.AFTER_EVENT) {
+ setShowTimeSectionAfter(true);
+ } else {
+ setShowTimeSectionAfter(false);
+ }
form.setValue("time", 24);
form.setValue("timeUnit", TimeUnit.HOUR);
} else {
setShowTimeSection(false);
+ setShowTimeSectionAfter(false);
form.unregister("time");
form.unregister("timeUnit");
}
@@ -166,7 +180,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
/>
{showTimeSection && (
-
+
)}
diff --git a/packages/features/ee/workflows/lib/constants.ts b/packages/features/ee/workflows/lib/constants.ts
index e496cfd9cc..2e99eed88d 100644
--- a/packages/features/ee/workflows/lib/constants.ts
+++ b/packages/features/ee/workflows/lib/constants.ts
@@ -4,6 +4,7 @@ export const WORKFLOW_TRIGGER_EVENTS = [
WorkflowTriggerEvents.BEFORE_EVENT,
WorkflowTriggerEvents.EVENT_CANCELLED,
WorkflowTriggerEvents.NEW_EVENT,
+ WorkflowTriggerEvents.AFTER_EVENT,
WorkflowTriggerEvents.RESCHEDULE_EVENT,
] as const;
diff --git a/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts b/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts
index 588962b4fa..369c3b0e98 100644
--- a/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts
+++ b/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts
@@ -29,7 +29,7 @@ export const scheduleEmailReminder = async (
evt: BookingInfo,
triggerEvent: WorkflowTriggerEvents,
action: WorkflowActions,
- timeBefore: {
+ timeSpan: {
time: number | null;
timeUnit: TimeUnit | null;
},
@@ -42,11 +42,15 @@ export const scheduleEmailReminder = async (
const { startTime, endTime } = evt;
const uid = evt.uid as string;
const currentDate = dayjs();
- const timeUnit: timeUnitLowerCase | undefined =
- timeBefore.timeUnit?.toLocaleLowerCase() as timeUnitLowerCase;
- const scheduledDate =
- timeBefore.time && timeUnit ? dayjs(startTime).subtract(timeBefore.time, timeUnit) : null;
+ const timeUnit: timeUnitLowerCase | undefined = timeSpan.timeUnit?.toLocaleLowerCase() as timeUnitLowerCase;
+ let scheduledDate = null;
+
+ if (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT) {
+ scheduledDate = timeSpan.time && timeUnit ? dayjs(startTime).subtract(timeSpan.time, timeUnit) : null;
+ } else if (triggerEvent === WorkflowTriggerEvents.AFTER_EVENT) {
+ scheduledDate = timeSpan.time && timeUnit ? dayjs(endTime).add(timeSpan.time, timeUnit) : null;
+ }
if (!process.env.SENDGRID_API_KEY || !process.env.SENDGRID_EMAIL) {
console.error("Sendgrid credentials are missing from the .env file");
return;
@@ -113,7 +117,11 @@ export const scheduleEmailReminder = async (
} catch (error) {
console.log("Error sending Email");
}
- } else if (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT && scheduledDate) {
+ } else if (
+ (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT ||
+ triggerEvent === WorkflowTriggerEvents.AFTER_EVENT) &&
+ scheduledDate
+ ) {
// Sendgrid to schedule emails
// Can only schedule at least 60 minutes and at most 72 hours in advance
if (
diff --git a/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts b/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts
index ba0c452d3d..a7aec1c3bd 100644
--- a/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts
+++ b/packages/features/ee/workflows/lib/reminders/reminderScheduler.ts
@@ -30,7 +30,8 @@ export const scheduleWorkflowReminders = async (
if (
workflow.trigger === WorkflowTriggerEvents.BEFORE_EVENT ||
(workflow.trigger === WorkflowTriggerEvents.NEW_EVENT && !isRescheduleEvent) ||
- (workflow.trigger === WorkflowTriggerEvents.RESCHEDULE_EVENT && isRescheduleEvent)
+ (workflow.trigger === WorkflowTriggerEvents.RESCHEDULE_EVENT && isRescheduleEvent) ||
+ workflow.trigger === WorkflowTriggerEvents.AFTER_EVENT
) {
workflow.steps.forEach(async (step) => {
if (step.action === WorkflowActions.SMS_ATTENDEE || step.action === WorkflowActions.SMS_NUMBER) {
diff --git a/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts b/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts
index ab3adf5656..eb315fe16b 100644
--- a/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts
+++ b/packages/features/ee/workflows/lib/reminders/smsReminderManager.ts
@@ -42,7 +42,7 @@ export const scheduleSMSReminder = async (
reminderPhone: string | null,
triggerEvent: WorkflowTriggerEvents,
action: WorkflowActions,
- timeBefore: {
+ timeSpan: {
time: number | null;
timeUnit: TimeUnit | null;
},
@@ -50,13 +50,17 @@ export const scheduleSMSReminder = async (
workflowStepId: number,
template: WorkflowTemplates
) => {
- const { startTime } = evt;
+ const { startTime, endTime } = evt;
const uid = evt.uid as string;
const currentDate = dayjs();
- const timeUnit: timeUnitLowerCase | undefined =
- timeBefore.timeUnit?.toLocaleLowerCase() as timeUnitLowerCase;
- const scheduledDate =
- timeBefore.time && timeUnit ? dayjs(startTime).subtract(timeBefore.time, timeUnit) : null;
+ const timeUnit: timeUnitLowerCase | undefined = timeSpan.timeUnit?.toLocaleLowerCase() as timeUnitLowerCase;
+ let scheduledDate = null;
+
+ if (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT) {
+ scheduledDate = timeSpan.time && timeUnit ? dayjs(startTime).subtract(timeSpan.time, timeUnit) : null;
+ } else if (triggerEvent === WorkflowTriggerEvents.AFTER_EVENT) {
+ scheduledDate = timeSpan.time && timeUnit ? dayjs(endTime).add(timeSpan.time, timeUnit) : null;
+ }
const name = action === WorkflowActions.SMS_ATTENDEE ? evt.attendees[0].name : "";
const attendeeName = action === WorkflowActions.SMS_ATTENDEE ? evt.organizer.name : evt.attendees[0].name;
@@ -96,7 +100,11 @@ export const scheduleSMSReminder = async (
} catch (error) {
console.log(`Error sending SMS with error ${error}`);
}
- } else if (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT && scheduledDate) {
+ } else if (
+ (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT ||
+ triggerEvent === WorkflowTriggerEvents.AFTER_EVENT) &&
+ scheduledDate
+ ) {
// Can only schedule at least 60 minutes in advance and at most 7 days in advance
if (
currentDate.isBefore(scheduledDate.subtract(1, "hour")) &&
diff --git a/packages/prisma/migrations/20221006121954_add_after_event_ends_workflow_trigger/migration.sql b/packages/prisma/migrations/20221006121954_add_after_event_ends_workflow_trigger/migration.sql
new file mode 100644
index 0000000000..ee6197e175
--- /dev/null
+++ b/packages/prisma/migrations/20221006121954_add_after_event_ends_workflow_trigger/migration.sql
@@ -0,0 +1,2 @@
+-- AlterEnum
+ALTER TYPE "WorkflowTriggerEvents" ADD VALUE 'AFTER_EVENT';
diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma
index c70bd81f1d..dc60065494 100644
--- a/packages/prisma/schema.prisma
+++ b/packages/prisma/schema.prisma
@@ -531,6 +531,7 @@ enum WorkflowTriggerEvents {
BEFORE_EVENT
EVENT_CANCELLED
NEW_EVENT
+ AFTER_EVENT
RESCHEDULE_EVENT
}
diff --git a/packages/trpc/server/routers/viewer/workflows.tsx b/packages/trpc/server/routers/viewer/workflows.tsx
index 3f5f924e78..24a90e06a5 100644
--- a/packages/trpc/server/routers/viewer/workflows.tsx
+++ b/packages/trpc/server/routers/viewer/workflows.tsx
@@ -372,7 +372,7 @@ export const workflowsRouter = createProtectedRouter()
let newEventTypes: number[] = [];
if (activeOn.length) {
- if (trigger === WorkflowTriggerEvents.BEFORE_EVENT) {
+ if (trigger === WorkflowTriggerEvents.BEFORE_EVENT || trigger === WorkflowTriggerEvents.AFTER_EVENT) {
newEventTypes = newActiveEventTypes;
}
if (newEventTypes.length > 0) {
@@ -424,7 +424,7 @@ export const workflowsRouter = createProtectedRouter()
: bookingInfo.attendees[0].email;
await scheduleEmailReminder(
bookingInfo,
- WorkflowTriggerEvents.BEFORE_EVENT,
+ trigger,
step.action,
{
time,
@@ -440,7 +440,7 @@ export const workflowsRouter = createProtectedRouter()
await scheduleSMSReminder(
bookingInfo,
step.sendTo || "",
- WorkflowTriggerEvents.BEFORE_EVENT,
+ trigger,
step.action,
{
time,
@@ -536,7 +536,10 @@ export const workflowsRouter = createProtectedRouter()
return eventTypeId;
}
});
- if (eventTypesToUpdateReminders && trigger === WorkflowTriggerEvents.BEFORE_EVENT) {
+ if (
+ eventTypesToUpdateReminders &&
+ (trigger === WorkflowTriggerEvents.BEFORE_EVENT || trigger === WorkflowTriggerEvents.AFTER_EVENT)
+ ) {
const bookingsOfEventTypes = await ctx.prisma.booking.findMany({
where: {
eventTypeId: {
@@ -582,7 +585,7 @@ export const workflowsRouter = createProtectedRouter()
: bookingInfo.attendees[0].email;
await scheduleEmailReminder(
bookingInfo,
- WorkflowTriggerEvents.BEFORE_EVENT,
+ trigger,
newStep.action,
{
time,
@@ -598,7 +601,7 @@ export const workflowsRouter = createProtectedRouter()
await scheduleSMSReminder(
bookingInfo,
newStep.sendTo || "",
- WorkflowTriggerEvents.BEFORE_EVENT,
+ trigger,
newStep.action,
{
time,
@@ -637,7 +640,8 @@ export const workflowsRouter = createProtectedRouter()
data: step,
});
if (
- trigger === WorkflowTriggerEvents.BEFORE_EVENT &&
+ (trigger === WorkflowTriggerEvents.BEFORE_EVENT ||
+ trigger === WorkflowTriggerEvents.AFTER_EVENT) &&
eventTypesToCreateReminders &&
step.action !== WorkflowActions.SMS_ATTENDEE
) {
@@ -701,7 +705,7 @@ export const workflowsRouter = createProtectedRouter()
await scheduleSMSReminder(
bookingInfo,
step.sendTo,
- WorkflowTriggerEvents.BEFORE_EVENT,
+ trigger,
step.action,
{
time,