Skip to content

Commit 33eee8d

Browse files
authored
fix: Email reminder issue with seated event (calcom#26136)
* fix emailworkflow reminder attendee * update
1 parent f5b9b6b commit 33eee8d

2 files changed

Lines changed: 61 additions & 28 deletions

File tree

packages/features/ee/workflows/api/scheduleEmailReminders.ts

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { v4 as uuidv4 } from "uuid";
88
import dayjs from "@calcom/dayjs";
99
import generateIcsString from "@calcom/emails/lib/generateIcsString";
1010
import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses";
11+
import { BookingSeatRepository } from "@calcom/features/bookings/repositories/BookingSeatRepository";
1112
import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer";
1213
import logger from "@calcom/lib/logger";
1314
import { safeStringify } from "@calcom/lib/safeStringify";
@@ -121,6 +122,18 @@ export async function handler(req: NextRequest) {
121122
}
122123
const referenceUid = reminder.uuid ?? uuidv4();
123124

125+
// For seated events, get the correct attendee based on seatReferenceId
126+
let targetAttendee = reminder.booking?.attendees[0];
127+
if (reminder.seatReferenceId) {
128+
const bookingSeatRepository = new BookingSeatRepository(prisma);
129+
const seatAttendeeData = await bookingSeatRepository.getByReferenceUidWithAttendeeDetails(
130+
reminder.seatReferenceId
131+
);
132+
if (seatAttendeeData?.attendee) {
133+
targetAttendee = seatAttendeeData.attendee;
134+
}
135+
}
136+
124137
if (!reminder.isMandatoryReminder && reminder.workflowStep) {
125138
try {
126139
let sendTo;
@@ -143,31 +156,31 @@ export async function handler(req: NextRequest) {
143156
}
144157
break;
145158
case WorkflowActions.EMAIL_ATTENDEE:
146-
sendTo = reminder.booking.attendees[0].email;
159+
sendTo = targetAttendee?.email;
147160
break;
148161
case WorkflowActions.EMAIL_ADDRESS:
149162
sendTo = reminder.workflowStep.sendTo;
150163
}
151164

152165
const name =
153166
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
154-
? reminder.booking.attendees[0].name
167+
? targetAttendee?.name
155168
: reminder.booking.user?.name;
156169

157170
const attendeeName =
158171
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
159172
? reminder.booking.user?.name
160-
: reminder.booking.attendees[0].name;
173+
: targetAttendee?.name;
161174

162175
const timeZone =
163176
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
164-
? reminder.booking.attendees[0].timeZone
177+
? targetAttendee?.timeZone
165178
: reminder.booking.user?.timeZone;
166179

167180
const locale =
168181
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE ||
169182
reminder.workflowStep.action === WorkflowActions.SMS_ATTENDEE
170-
? reminder.booking.attendees[0].locale
183+
? targetAttendee?.locale
171184
: reminder.booking.user?.locale;
172185

173186
let emailContent = {
@@ -199,16 +212,16 @@ export async function handler(req: NextRequest) {
199212

200213
const recipientEmail = getWorkflowRecipientEmail({
201214
action: reminder.workflowStep.action || WorkflowActions.EMAIL_ADDRESS,
202-
attendeeEmail: reminder.booking.attendees[0].email,
215+
attendeeEmail: targetAttendee?.email,
203216
organizerEmail: reminder.booking.user?.email,
204217
sendToEmail: reminder.workflowStep.sendTo,
205218
});
206219

207220
const variables: VariablesType = {
208221
eventName: reminder.booking.eventType?.title || "",
209222
organizerName: reminder.booking.user?.name || "",
210-
attendeeName: reminder.booking.attendees[0].name,
211-
attendeeEmail: reminder.booking.attendees[0].email,
223+
attendeeName: targetAttendee?.name || "",
224+
attendeeEmail: targetAttendee?.email || "",
212225
eventDate: dayjs(reminder.booking.startTime).tz(timeZone),
213226
eventEndTime: dayjs(reminder.booking?.endTime).tz(timeZone),
214227
timeZone: timeZone,
@@ -224,13 +237,9 @@ export async function handler(req: NextRequest) {
224237
}`,
225238
ratingUrl: `${bookerUrl}/booking/${reminder.booking.uid}?rating`,
226239
noShowUrl: `${bookerUrl}/booking/${reminder.booking.uid}?noShow=true`,
227-
attendeeTimezone: reminder.booking.attendees[0].timeZone,
228-
eventTimeInAttendeeTimezone: dayjs(reminder.booking.startTime).tz(
229-
reminder.booking.attendees[0].timeZone
230-
),
231-
eventEndTimeInAttendeeTimezone: dayjs(reminder.booking?.endTime).tz(
232-
reminder.booking.attendees[0].timeZone
233-
),
240+
attendeeTimezone: targetAttendee?.timeZone,
241+
eventTimeInAttendeeTimezone: dayjs(reminder.booking.startTime).tz(targetAttendee?.timeZone),
242+
eventEndTimeInAttendeeTimezone: dayjs(reminder.booking?.endTime).tz(targetAttendee?.timeZone),
234243
};
235244
const emailLocale = locale || "en";
236245
const brandingDisabled = reminder.booking.eventType?.team
@@ -408,10 +417,10 @@ export async function handler(req: NextRequest) {
408417
}
409418
} else if (reminder.isMandatoryReminder) {
410419
try {
411-
const sendTo = reminder.booking.attendees[0].email;
412-
const name = reminder.booking.attendees[0].name;
420+
const sendTo = targetAttendee?.email;
421+
const name = targetAttendee?.name;
413422
const attendeeName = reminder.booking.user?.name;
414-
const timeZone = reminder.booking.attendees[0].timeZone;
423+
const timeZone = targetAttendee?.timeZone;
415424

416425
let emailContent = {
417426
emailSubject: "",

packages/features/ee/workflows/lib/service/EmailWorkflowService.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,37 @@ export class EmailWorkflowService {
283283
timeZone = evt.organizer.timeZone;
284284
break;
285285
case WorkflowActions.EMAIL_ATTENDEE: {
286-
// check if first attendee of sendTo is present in the attendees list, if not take the evt attendee
287-
const attendeeEmailToBeUsedInMailFromEvt = evt.attendees.find(
288-
(attendee) => attendee.email === sendTo[0]
289-
);
290-
attendeeToBeUsedInMail = attendeeEmailToBeUsedInMailFromEvt
291-
? attendeeEmailToBeUsedInMailFromEvt
292-
: evt.attendees[0];
286+
// For seated events, get the correct attendee based on seatReferenceUid
287+
if (seatReferenceUid) {
288+
const seatAttendeeData = await this.bookingSeatRepository.getByReferenceUidWithAttendeeDetails(
289+
seatReferenceUid
290+
);
291+
if (seatAttendeeData?.attendee) {
292+
const nameParts = seatAttendeeData.attendee.name.split(" ").map((part: string) => part.trim());
293+
const firstName = nameParts[0];
294+
const lastName = nameParts.slice(1).join(" ");
295+
attendeeToBeUsedInMail = {
296+
name: seatAttendeeData.attendee.name,
297+
firstName,
298+
lastName: lastName || undefined,
299+
email: seatAttendeeData.attendee.email,
300+
phoneNumber: seatAttendeeData.attendee.phoneNumber || null,
301+
timeZone: seatAttendeeData.attendee.timeZone,
302+
language: { locale: seatAttendeeData.attendee.locale || "en" },
303+
};
304+
} else {
305+
// Fallback to first attendee if seat attendee not found
306+
attendeeToBeUsedInMail = evt.attendees[0];
307+
}
308+
} else {
309+
// For non-seated events, check if first attendee of sendTo is present in the attendees list, if not take the evt attendee
310+
const attendeeEmailToBeUsedInMailFromEvt = evt.attendees.find(
311+
(attendee) => attendee.email === sendTo[0]
312+
);
313+
attendeeToBeUsedInMail = attendeeEmailToBeUsedInMailFromEvt
314+
? attendeeEmailToBeUsedInMailFromEvt
315+
: evt.attendees[0];
316+
}
293317
name = attendeeToBeUsedInMail.name;
294318
attendeeName = evt.organizer.name;
295319
timeZone = attendeeToBeUsedInMail.timeZone;
@@ -350,9 +374,9 @@ export class EmailWorkflowService {
350374
rescheduleReason: evt.rescheduleReason,
351375
ratingUrl: `${bookerUrl}/booking/${evt.uid}?rating`,
352376
noShowUrl: `${bookerUrl}/booking/${evt.uid}?noShow=true`,
353-
attendeeTimezone: evt.attendees[0].timeZone,
354-
eventTimeInAttendeeTimezone: dayjs(startTime).tz(evt.attendees[0].timeZone),
355-
eventEndTimeInAttendeeTimezone: dayjs(endTime).tz(evt.attendees[0].timeZone),
377+
attendeeTimezone: attendeeToBeUsedInMail.timeZone,
378+
eventTimeInAttendeeTimezone: dayjs(startTime).tz(attendeeToBeUsedInMail.timeZone),
379+
eventEndTimeInAttendeeTimezone: dayjs(endTime).tz(attendeeToBeUsedInMail.timeZone),
356380
};
357381

358382
const locale = isEmailAttendeeAction

0 commit comments

Comments
 (0)