Skip to content

Commit 82d3c43

Browse files
CarinaWolliCarinaWollijoeauyeungzomars
authored
cancel and schedule reminders when workflow activated/deactivated on event type (#8757)
* add switches to advanced even type settings * only show switches when workflow is enabled * check in event type update handler if user is allowed to disable standard emails * don't send emails if disabled * remove reminders when workflow is deactivated on event type * make sure emails can't be disabled if no workflow exist * send workflow emails to all attendees * code clean up * add translations * always send to all attendees when scheduling reminders * schedule reminders if event type gets activated on workflow * schedule reminders (commented code) * change text * schedule reminders for all attendees not just first one --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: zomars <zomars@me.com>
1 parent 492b4d3 commit 82d3c43

File tree

2 files changed

+136
-4
lines changed

2 files changed

+136
-4
lines changed

packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts

+134-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
1+
import {
2+
deleteScheduledEmailReminder,
3+
scheduleEmailReminder,
4+
} from "@calcom/features/ee/workflows/lib/reminders/emailReminderManager";
5+
import {
6+
deleteScheduledSMSReminder,
7+
scheduleSMSReminder,
8+
} from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager";
9+
import { SENDER_ID, SENDER_NAME } from "@calcom/lib/constants";
110
import { prisma } from "@calcom/prisma";
2-
import { MembershipRole, WorkflowActions } from "@calcom/prisma/enums";
11+
import { BookingStatus } from "@calcom/prisma/client";
12+
import { MembershipRole, WorkflowActions, WorkflowMethods } from "@calcom/prisma/enums";
313
import type { TrpcSessionUser } from "@calcom/trpc/server/trpc";
414

515
import { TRPCError } from "@trpc/server";
@@ -17,7 +27,7 @@ type ActivateEventTypeOptions = {
1727
export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventTypeOptions) => {
1828
const { eventTypeId, workflowId } = input;
1929

20-
// Check that vent type belong to the user or team
30+
// Check that event type belong to the user or team
2131
const userEventType = await prisma.eventType.findFirst({
2232
where: {
2333
id: eventTypeId,
@@ -76,6 +86,35 @@ export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventType
7686
});
7787

7888
if (isActive) {
89+
// disable workflow for this event type & delete all reminders
90+
const remindersToDelete = await prisma.workflowReminder.findMany({
91+
where: {
92+
booking: {
93+
eventTypeId: eventTypeId,
94+
userId: ctx.user.id,
95+
},
96+
workflowStepId: {
97+
in: eventTypeWorkflow.steps.map((step) => {
98+
return step.id;
99+
}),
100+
},
101+
},
102+
select: {
103+
id: true,
104+
referenceId: true,
105+
method: true,
106+
scheduled: true,
107+
},
108+
});
109+
110+
remindersToDelete.forEach((reminder) => {
111+
if (reminder.method === WorkflowMethods.EMAIL) {
112+
deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
113+
} else if (reminder.method === WorkflowMethods.SMS) {
114+
deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
115+
}
116+
});
117+
79118
await prisma.workflowsOnEventTypes.deleteMany({
80119
where: {
81120
workflowId,
@@ -88,6 +127,99 @@ export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventType
88127
eventTypeId,
89128
});
90129
} else {
130+
// activate workflow and schedule reminders for existing bookings
131+
132+
const bookingsForReminders = await prisma.booking.findMany({
133+
where: {
134+
eventTypeId: eventTypeId,
135+
status: BookingStatus.ACCEPTED,
136+
startTime: {
137+
gte: new Date(),
138+
},
139+
},
140+
include: {
141+
attendees: true,
142+
eventType: true,
143+
user: true,
144+
},
145+
});
146+
147+
for (const booking of bookingsForReminders) {
148+
const bookingInfo = {
149+
uid: booking.uid,
150+
attendees: booking.attendees.map((attendee) => {
151+
return {
152+
name: attendee.name,
153+
email: attendee.email,
154+
timeZone: attendee.timeZone,
155+
language: { locale: attendee.locale || "" },
156+
};
157+
}),
158+
organizer: booking.user
159+
? {
160+
name: booking.user.name || "",
161+
email: booking.user.email,
162+
timeZone: booking.user.timeZone,
163+
language: { locale: booking.user.locale || "" },
164+
}
165+
: { name: "", email: "", timeZone: "", language: { locale: "" } },
166+
startTime: booking.startTime.toISOString(),
167+
endTime: booking.endTime.toISOString(),
168+
title: booking.title,
169+
language: { locale: booking?.user?.locale || "" },
170+
eventType: {
171+
slug: booking.eventType?.slug,
172+
},
173+
};
174+
for (const step of eventTypeWorkflow.steps) {
175+
if (step.action === WorkflowActions.EMAIL_ATTENDEE || step.action === WorkflowActions.EMAIL_HOST) {
176+
let sendTo: string[] = [];
177+
178+
switch (step.action) {
179+
case WorkflowActions.EMAIL_HOST:
180+
sendTo = [bookingInfo.organizer?.email];
181+
break;
182+
case WorkflowActions.EMAIL_ATTENDEE:
183+
sendTo = bookingInfo.attendees.map((attendee) => attendee.email);
184+
break;
185+
}
186+
187+
await scheduleEmailReminder(
188+
bookingInfo,
189+
eventTypeWorkflow.trigger,
190+
step.action,
191+
{
192+
time: eventTypeWorkflow.time,
193+
timeUnit: eventTypeWorkflow.timeUnit,
194+
},
195+
sendTo,
196+
step.emailSubject || "",
197+
step.reminderBody || "",
198+
step.id,
199+
step.template,
200+
step.sender || SENDER_NAME
201+
);
202+
} else if (step.action === WorkflowActions.SMS_NUMBER && step.sendTo) {
203+
await scheduleSMSReminder(
204+
bookingInfo,
205+
step.sendTo,
206+
eventTypeWorkflow.trigger,
207+
step.action,
208+
{
209+
time: eventTypeWorkflow.time,
210+
timeUnit: eventTypeWorkflow.timeUnit,
211+
},
212+
step.reminderBody || "",
213+
step.id,
214+
step.template,
215+
step.sender || SENDER_ID,
216+
booking.userId,
217+
eventTypeWorkflow.teamId
218+
);
219+
}
220+
}
221+
}
222+
91223
await prisma.workflowsOnEventTypes.create({
92224
data: {
93225
workflowId,

packages/trpc/server/routers/viewer/workflows/update.handler.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
532532
user: true,
533533
},
534534
});
535-
bookingsForReminders.forEach(async (booking) => {
535+
for (const booking of bookingsForReminders) {
536536
const bookingInfo = {
537537
uid: booking.uid,
538538
attendees: booking.attendees.map((attendee) => {
@@ -611,7 +611,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
611611
userWorkflow.teamId
612612
);
613613
}
614-
});
614+
}
615615
}
616616
}
617617
});

0 commit comments

Comments
 (0)