* feat: add platform URL support for reschedule and cancel links in workflow emails Co-Authored-By: morgan@cal.com <morgan@cal.com> * feat: pass platform URL data to CalendarEventBuilder in workflow emails Co-Authored-By: morgan@cal.com <morgan@cal.com> * Revert "feat: pass platform URL data to CalendarEventBuilder in workflow emails" This reverts commit 1d4d3623c93cd4eeeef18ffdad0597fe583b6a55. * chore: provide platform metadat to workflow email task * fixup! chore: provide platform metadat to workflow email task * test: add unit tests for platform URL handling in EmailWorkflowService Co-Authored-By: morgan@cal.com <morgan@cal.com> * test: update WorkflowService tests to include platform params in tasker payload Co-Authored-By: morgan@cal.com <morgan@cal.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
100 lines
3.3 KiB
TypeScript
100 lines
3.3 KiB
TypeScript
import { sendCustomWorkflowEmail } from "@calcom/emails/workflow-email-service";
|
|
import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository";
|
|
import { BookingSeatRepository } from "@calcom/features/bookings/repositories/BookingSeatRepository";
|
|
import { CalendarEventBuilder } from "@calcom/features/CalendarEventBuilder";
|
|
import { EmailWorkflowService } from "@calcom/features/ee/workflows/lib/service/EmailWorkflowService";
|
|
import { WorkflowReminderRepository } from "@calcom/features/ee/workflows/repositories/WorkflowReminderRepository";
|
|
import { prisma } from "@calcom/prisma";
|
|
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
|
|
import { z } from "zod";
|
|
|
|
export const ZSendWorkflowEmailsSchemaEager = z.object({
|
|
to: z.array(z.string()),
|
|
subject: z.string(),
|
|
html: z.string(),
|
|
replyTo: z.string().optional(),
|
|
sender: z.string().nullable().optional(),
|
|
attachments: z
|
|
.array(
|
|
z
|
|
.object({
|
|
content: z.string(),
|
|
filename: z.string(),
|
|
})
|
|
.passthrough()
|
|
)
|
|
.optional(),
|
|
});
|
|
|
|
const ZSendWorkflowEmailsSchemaLazy = z.object({
|
|
bookingUid: z.string(),
|
|
workflowReminderId: z.number(),
|
|
platformClientId: z.string().optional(),
|
|
platformRescheduleUrl: z.string().optional(),
|
|
platformCancelUrl: z.string().optional(),
|
|
platformBookingUrl: z.string().optional(),
|
|
});
|
|
|
|
export const ZSendWorkflowEmailsSchema = z.union([
|
|
ZSendWorkflowEmailsSchemaEager,
|
|
ZSendWorkflowEmailsSchemaLazy,
|
|
]);
|
|
|
|
export async function sendWorkflowEmails(payload: string): Promise<void> {
|
|
const mailData = ZSendWorkflowEmailsSchema.parse(JSON.parse(payload));
|
|
|
|
// Generate workflow body to send
|
|
if ("bookingUid" in mailData && "workflowReminderId" in mailData) {
|
|
const bookingRepository = new BookingRepository(prisma);
|
|
const booking = await bookingRepository.getBookingForCalEventBuilderFromUid(mailData.bookingUid);
|
|
|
|
if (!booking) {
|
|
throw new Error("Booking not found");
|
|
}
|
|
|
|
const bookingMetadata = bookingMetadataSchema.parse(booking.metadata || {});
|
|
|
|
const calendarEvent = (
|
|
await CalendarEventBuilder.fromBooking(booking, {
|
|
platformClientId: mailData.platformClientId ?? bookingMetadata?.platformClientId,
|
|
platformRescheduleUrl: mailData.platformRescheduleUrl,
|
|
platformCancelUrl: mailData.platformCancelUrl,
|
|
platformBookingUrl: mailData.platformBookingUrl,
|
|
})
|
|
).build();
|
|
|
|
if (!calendarEvent) {
|
|
throw new Error("Calendar event could not be built");
|
|
}
|
|
|
|
// Check if videoCallUrl exists in booking metadata and add it to evt.metadata
|
|
const metadata = bookingMetadata?.videoCallUrl
|
|
? {
|
|
videoCallUrl: bookingMetadata.videoCallUrl,
|
|
}
|
|
: undefined;
|
|
|
|
const evtWithMetadata = { ...calendarEvent, metadata };
|
|
|
|
const workflowReminderRepository = new WorkflowReminderRepository(prisma);
|
|
const bookingSeatRepository = new BookingSeatRepository(prisma);
|
|
const emailWorkflowService = new EmailWorkflowService(workflowReminderRepository, bookingSeatRepository);
|
|
|
|
await emailWorkflowService.handleSendEmailWorkflowTask({
|
|
evt: evtWithMetadata,
|
|
workflowReminderId: mailData.workflowReminderId,
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
await Promise.all(
|
|
mailData.to.map((to) =>
|
|
sendCustomWorkflowEmail({
|
|
...mailData,
|
|
to,
|
|
})
|
|
)
|
|
);
|
|
}
|