Delay workflow email cancellation in sendgrid for all case (#7647)
* don't use immediate email cancellation in any case * use continue --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com>
This commit is contained in:
co-authored by
CarinaWolli
parent
4e8653cf4e
commit
d50473468a
@@ -1147,7 +1147,7 @@ async function handler(
|
||||
// cancel workflow reminders from previous rescheduled booking
|
||||
originalRescheduledBooking.workflowReminders.forEach((reminder) => {
|
||||
if (reminder.method === WorkflowMethods.EMAIL) {
|
||||
deleteScheduledEmailReminder(reminder.id, reminder.referenceId, true);
|
||||
deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
|
||||
} else if (reminder.method === WorkflowMethods.SMS) {
|
||||
deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { defaultHandler } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { Prisma, WorkflowReminder } from "@calcom/prisma/client";
|
||||
import type { Prisma, WorkflowReminder } from "@calcom/prisma/client";
|
||||
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import customTemplate, { VariablesType } from "../lib/reminders/templates/customTemplate";
|
||||
import type { VariablesType } from "../lib/reminders/templates/customTemplate";
|
||||
import customTemplate from "../lib/reminders/templates/customTemplate";
|
||||
import emailReminderTemplate from "../lib/reminders/templates/emailReminderTemplate";
|
||||
|
||||
const sendgridAPIKey = process.env.SENDGRID_API_KEY as string;
|
||||
@@ -103,15 +104,18 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
for (const reminder of unscheduledReminders) {
|
||||
if (!reminder.workflowStep || !reminder.booking) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
let sendTo;
|
||||
|
||||
switch (reminder.workflowStep.action) {
|
||||
case WorkflowActions.EMAIL_HOST:
|
||||
sendTo = reminder.booking?.user?.email;
|
||||
sendTo = reminder.booking.user?.email;
|
||||
break;
|
||||
case WorkflowActions.EMAIL_ATTENDEE:
|
||||
sendTo = reminder.booking?.attendees[0].email;
|
||||
sendTo = reminder.booking.attendees[0].email;
|
||||
break;
|
||||
case WorkflowActions.EMAIL_ADDRESS:
|
||||
sendTo = reminder.workflowStep.sendTo;
|
||||
@@ -119,24 +123,24 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
const name =
|
||||
reminder.workflowStep.action === WorkflowActions.EMAIL_ATTENDEE
|
||||
? reminder.booking?.attendees[0].name
|
||||
: reminder.booking?.user?.name;
|
||||
? 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;
|
||||
? 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;
|
||||
? 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;
|
||||
? reminder.booking.attendees[0].locale
|
||||
: reminder.booking.user?.locale;
|
||||
|
||||
let emailContent = {
|
||||
emailSubject: reminder.workflowStep.emailSubject || "",
|
||||
@@ -149,9 +153,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
switch (reminder.workflowStep.template) {
|
||||
case WorkflowTemplates.REMINDER:
|
||||
emailContent = emailReminderTemplate(
|
||||
reminder.booking?.startTime.toISOString() || "",
|
||||
reminder.booking?.endTime.toISOString() || "",
|
||||
reminder.booking?.eventType?.title || "",
|
||||
reminder.booking.startTime.toISOString() || "",
|
||||
reminder.booking.endTime.toISOString() || "",
|
||||
reminder.booking.eventType?.title || "",
|
||||
timeZone || "",
|
||||
attendeeName || "",
|
||||
name || ""
|
||||
@@ -160,16 +164,16 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
case WorkflowTemplates.CUSTOM:
|
||||
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),
|
||||
eventTime: dayjs(reminder.booking?.startTime).tz(timeZone),
|
||||
organizerName: reminder.booking.user?.name || "",
|
||||
attendeeName: reminder.booking.attendees[0].name,
|
||||
attendeeEmail: reminder.booking.attendees[0].email,
|
||||
eventDate: dayjs(reminder.booking.startTime).tz(timeZone),
|
||||
eventTime: dayjs(reminder.booking.startTime).tz(timeZone),
|
||||
timeZone: timeZone,
|
||||
location: reminder.booking?.location || "",
|
||||
additionalNotes: reminder.booking?.description,
|
||||
customInputs: reminder.booking?.customInputs,
|
||||
meetingUrl: bookingMetadataSchema.parse(reminder.booking?.metadata || {})?.videoCallUrl,
|
||||
location: reminder.booking.location || "",
|
||||
additionalNotes: reminder.booking.description,
|
||||
customInputs: reminder.booking.customInputs,
|
||||
meetingUrl: bookingMetadataSchema.parse(reminder.booking.metadata || {})?.videoCallUrl,
|
||||
};
|
||||
const emailSubject = await customTemplate(
|
||||
reminder.workflowStep.emailSubject || "",
|
||||
@@ -204,7 +208,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
html: emailContent.emailBody.html,
|
||||
batchId: batchId,
|
||||
sendAt: dayjs(reminder.scheduledDate).unix(),
|
||||
replyTo: reminder.booking?.user?.email || senderEmail,
|
||||
replyTo: reminder.booking.user?.email || senderEmail,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { getSenderId } from "../lib/alphanumericSenderIdSupport";
|
||||
import * as twilio from "../lib/reminders/smsProviders/twilioProvider";
|
||||
import customTemplate, { VariablesType } from "../lib/reminders/templates/customTemplate";
|
||||
import type { VariablesType } from "../lib/reminders/templates/customTemplate";
|
||||
import customTemplate from "../lib/reminders/templates/customTemplate";
|
||||
import smsReminderTemplate from "../lib/reminders/templates/smsReminderTemplate";
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -53,6 +54,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (!unscheduledReminders.length) res.json({ ok: true });
|
||||
|
||||
for (const reminder of unscheduledReminders) {
|
||||
if (!reminder.workflowStep || !reminder.booking) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const sendTo =
|
||||
reminder.workflowStep.action === WorkflowActions.SMS_NUMBER
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import {
|
||||
TimeUnit,
|
||||
WorkflowTriggerEvents,
|
||||
WorkflowTemplates,
|
||||
WorkflowActions,
|
||||
WorkflowMethods,
|
||||
} from "@prisma/client";
|
||||
import type { TimeUnit } from "@prisma/client";
|
||||
import { WorkflowTriggerEvents, WorkflowTemplates, WorkflowActions, WorkflowMethods } from "@prisma/client";
|
||||
import client from "@sendgrid/client";
|
||||
import sgMail from "@sendgrid/mail";
|
||||
|
||||
@@ -12,8 +7,9 @@ import dayjs from "@calcom/dayjs";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { BookingInfo, timeUnitLowerCase } from "./smsReminderManager";
|
||||
import customTemplate, { VariablesType } from "./templates/customTemplate";
|
||||
import type { BookingInfo, timeUnitLowerCase } from "./smsReminderManager";
|
||||
import type { VariablesType } from "./templates/customTemplate";
|
||||
import customTemplate from "./templates/customTemplate";
|
||||
import emailReminderTemplate from "./templates/emailReminderTemplate";
|
||||
|
||||
let sendgridAPIKey, senderEmail: string;
|
||||
@@ -194,11 +190,7 @@ export const scheduleEmailReminder = async (
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteScheduledEmailReminder = async (
|
||||
reminderId: number,
|
||||
referenceId: string | null,
|
||||
immediateDelete?: boolean
|
||||
) => {
|
||||
export const deleteScheduledEmailReminder = async (reminderId: number, referenceId: string | null) => {
|
||||
try {
|
||||
if (!referenceId) {
|
||||
await prisma.workflowReminder.delete({
|
||||
@@ -210,18 +202,6 @@ export const deleteScheduledEmailReminder = async (
|
||||
return;
|
||||
}
|
||||
|
||||
if (immediateDelete) {
|
||||
await client.request({
|
||||
url: "/v3/user/scheduled_sends",
|
||||
method: "POST",
|
||||
body: {
|
||||
batch_id: referenceId,
|
||||
status: "cancel",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await prisma.workflowReminder.update({
|
||||
where: {
|
||||
id: reminderId,
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "WorkflowReminder" DROP CONSTRAINT "WorkflowReminder_bookingUid_fkey";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "WorkflowReminder" DROP CONSTRAINT "WorkflowReminder_workflowStepId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "WorkflowReminder" ALTER COLUMN "bookingUid" DROP NOT NULL,
|
||||
ALTER COLUMN "workflowStepId" DROP NOT NULL;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "WorkflowReminder" ADD CONSTRAINT "WorkflowReminder_bookingUid_fkey" FOREIGN KEY ("bookingUid") REFERENCES "Booking"("uid") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "WorkflowReminder" ADD CONSTRAINT "WorkflowReminder_workflowStepId_fkey" FOREIGN KEY ("workflowStepId") REFERENCES "WorkflowStep"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -642,14 +642,14 @@ enum TimeUnit {
|
||||
|
||||
model WorkflowReminder {
|
||||
id Int @id @default(autoincrement())
|
||||
bookingUid String
|
||||
booking Booking? @relation(fields: [bookingUid], references: [uid], onDelete: Cascade)
|
||||
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], onDelete: Cascade)
|
||||
workflowStepId Int?
|
||||
workflowStep WorkflowStep? @relation(fields: [workflowStepId], references: [id])
|
||||
cancelled Boolean?
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@ export const workflowsRouter = router({
|
||||
//cancel workflow reminders of deleted workflow
|
||||
scheduledReminders.forEach((reminder) => {
|
||||
if (reminder.method === WorkflowMethods.EMAIL) {
|
||||
deleteScheduledEmailReminder(reminder.id, reminder.referenceId, true);
|
||||
deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
|
||||
} else if (reminder.method === WorkflowMethods.SMS) {
|
||||
deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
|
||||
}
|
||||
@@ -736,7 +736,7 @@ export const workflowsRouter = router({
|
||||
if (remindersFromStep.length > 0) {
|
||||
remindersFromStep.forEach((reminder) => {
|
||||
if (reminder.method === WorkflowMethods.EMAIL) {
|
||||
deleteScheduledEmailReminder(reminder.id, reminder.referenceId, true);
|
||||
deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
|
||||
} else if (reminder.method === WorkflowMethods.SMS) {
|
||||
deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user