Skip to content

Commit 14c3265

Browse files
committed
Handle more dry-run cases
1 parent ec920eb commit 14c3265

File tree

11 files changed

+116
-50
lines changed

11 files changed

+116
-50
lines changed

packages/features/bookings/lib/handleConfirmation.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ export async function handleConfirmation(args: {
8888
const scheduleResult = await eventManager.create(evt);
8989
const results = scheduleResult.results;
9090
const metadata: AdditionalInformation = {};
91-
9291
const workflows = await getAllWorkflowsFromEventType(eventType, booking.userId);
9392

9493
if (results.length > 0 && results.every((res) => !res.success)) {
@@ -338,14 +337,14 @@ export async function handleConfirmation(args: {
338337
const isFirstBooking = index === 0;
339338

340339
if (!eventTypeMetadata?.disableStandardEmails?.all?.attendee) {
341-
await scheduleMandatoryReminder(
342-
evtOfBooking,
340+
await scheduleMandatoryReminder({
341+
evt: evtOfBooking,
343342
workflows,
344-
false,
345-
!!updatedBookings[index].eventType?.owner?.hideBranding,
346-
evt.attendeeSeatId,
347-
!emailsEnabled && Boolean(platformClientParams?.platformClientId)
348-
);
343+
requiresConfirmation: false,
344+
hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding,
345+
seatReferenceUid: evt.attendeeSeatId,
346+
isPlatformNoEmail: !emailsEnabled && Boolean(platformClientParams?.platformClientId),
347+
});
349348
}
350349

351350
await scheduleWorkflowReminders({

packages/features/bookings/lib/handleNewBooking.ts

+34-15
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,7 @@ async function handler(
10961096
responses,
10971097
workflows,
10981098
rescheduledBy: reqBody.rescheduledBy,
1099+
isDryRun,
10991100
});
11001101

11011102
if (newBooking) {
@@ -1764,15 +1765,16 @@ async function handler(
17641765

17651766
// Convert type of eventTypePaymentAppCredential to appId: EventTypeAppList
17661767
if (!booking.user) booking.user = organizerUser;
1767-
const payment = await handlePayment(
1768+
const payment = await handlePayment({
17681769
evt,
1769-
eventType,
1770-
eventTypePaymentAppCredential as IEventTypePaymentCredentialType,
1770+
selectedEventType: eventType,
1771+
paymentAppCredentials: eventTypePaymentAppCredential as IEventTypePaymentCredentialType,
17711772
booking,
1772-
fullName,
1773+
bookerName: fullName,
17731774
bookerEmail,
1774-
bookerPhoneNumber
1775-
);
1775+
bookerPhoneNumber,
1776+
isDryRun,
1777+
});
17761778
const subscriberOptionsPaymentInitiated: GetSubscriberOptions = {
17771779
userId: triggerForUser ? organizerUser.id : null,
17781780
eventTypeId,
@@ -1788,6 +1790,7 @@ async function handler(
17881790
...webhookData,
17891791
paymentId: payment?.id,
17901792
},
1793+
isDryRun,
17911794
});
17921795

17931796
req.statusCode = 201;
@@ -1830,6 +1833,7 @@ async function handler(
18301833
//delete all scheduled triggers for meeting ended and meeting started of booking
18311834
deleteWebhookScheduledTriggerPromise = deleteWebhookScheduledTriggers({
18321835
booking: originalRescheduledBooking,
1836+
isDryRun,
18331837
});
18341838
}
18351839

@@ -1841,6 +1845,7 @@ async function handler(
18411845
subscriberUrl: subscriber.subscriberUrl,
18421846
subscriber,
18431847
triggerEvent: WebhookTriggerEvents.MEETING_ENDED,
1848+
isDryRun,
18441849
})
18451850
);
18461851
}
@@ -1852,6 +1857,7 @@ async function handler(
18521857
subscriberUrl: subscriber.subscriberUrl,
18531858
subscriber,
18541859
triggerEvent: WebhookTriggerEvents.MEETING_STARTED,
1860+
isDryRun,
18551861
})
18561862
);
18571863
}
@@ -1865,13 +1871,23 @@ async function handler(
18651871
});
18661872

18671873
// Send Webhook call if hooked to BOOKING_CREATED & BOOKING_RESCHEDULED
1868-
await monitorCallbackAsync(handleWebhookTrigger, { subscriberOptions, eventTrigger, webhookData });
1874+
await monitorCallbackAsync(handleWebhookTrigger, {
1875+
subscriberOptions,
1876+
eventTrigger,
1877+
webhookData,
1878+
isDryRun,
1879+
});
18691880
} else {
18701881
// if eventType requires confirmation we will trigger the BOOKING REQUESTED Webhook
18711882
const eventTrigger: WebhookTriggerEvents = WebhookTriggerEvents.BOOKING_REQUESTED;
18721883
subscriberOptions.triggerEvent = eventTrigger;
18731884
webhookData.status = "PENDING";
1874-
await monitorCallbackAsync(handleWebhookTrigger, { subscriberOptions, eventTrigger, webhookData });
1885+
await monitorCallbackAsync(handleWebhookTrigger, {
1886+
subscriberOptions,
1887+
eventTrigger,
1888+
webhookData,
1889+
isDryRun,
1890+
});
18751891
}
18761892

18771893
try {
@@ -1917,14 +1933,15 @@ async function handler(
19171933
};
19181934

19191935
if (!eventType.metadata?.disableStandardEmails?.all?.attendee) {
1920-
await scheduleMandatoryReminder(
1921-
evtWithMetadata,
1936+
await scheduleMandatoryReminder({
1937+
evt: evtWithMetadata,
19221938
workflows,
1923-
!isConfirmedByDefault,
1924-
!!eventType.owner?.hideBranding,
1925-
evt.attendeeSeatId,
1926-
noEmail && Boolean(platformClientId)
1927-
);
1939+
requiresConfirmation: !isConfirmedByDefault,
1940+
hideBranding: !!eventType.owner?.hideBranding,
1941+
seatReferenceUid: evt.attendeeSeatId,
1942+
isPlatformNoEmail: noEmail && Boolean(platformClientId),
1943+
isDryRun,
1944+
});
19281945
}
19291946

19301947
try {
@@ -1937,6 +1954,7 @@ async function handler(
19371954
isFirstRecurringEvent: req.body.allRecurringDates ? req.body.isFirstRecurringSlot : undefined,
19381955
hideBranding: !!eventType.owner?.hideBranding,
19391956
seatReferenceUid: evt.attendeeSeatId,
1957+
isDryRun,
19401958
});
19411959
} catch (error) {
19421960
loggerWithEventDetails.error("Error while scheduling workflow reminders", JSON.stringify({ error }));
@@ -1951,6 +1969,7 @@ async function handler(
19511969
eventTypeId,
19521970
teamId,
19531971
orgId,
1972+
isDryRun,
19541973
});
19551974
}
19561975
} catch (error) {

packages/features/bookings/lib/handleNewBooking/scheduleNoShowTriggers.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,22 @@ type ScheduleNoShowTriggersArgs = {
1414
teamId?: number | null;
1515
orgId?: number | null;
1616
oAuthClientId?: string | null;
17+
isDryRun?: boolean;
1718
};
1819

1920
export const scheduleNoShowTriggers = async (args: ScheduleNoShowTriggersArgs) => {
20-
const { booking, triggerForUser, organizerUser, eventTypeId, teamId, orgId, oAuthClientId } = args;
21+
const {
22+
booking,
23+
triggerForUser,
24+
organizerUser,
25+
eventTypeId,
26+
teamId,
27+
orgId,
28+
oAuthClientId,
29+
isDryRun = false,
30+
} = args;
31+
32+
if (isDryRun) return;
2133

2234
// Add task for automatic no show in cal video
2335
const noShowPromises: Promise<any>[] = [];

packages/features/bookings/lib/handleSeats/create/createNewSeat.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,15 @@ const createNewSeat = async (
185185
throw new HttpError({ statusCode: 400, message: ErrorCode.MissingPaymentAppId });
186186
}
187187

188-
const payment = await handlePayment(
188+
const payment = await handlePayment({
189189
evt,
190-
eventType,
191-
eventTypePaymentAppCredential as IEventTypePaymentCredentialType,
192-
seatedBooking,
193-
fullName,
190+
selectedEventType: eventType,
191+
paymentAppCredentials: eventTypePaymentAppCredential as IEventTypePaymentCredentialType,
192+
booking: seatedBooking,
193+
bookerName: fullName,
194194
bookerEmail,
195-
bookerPhoneNumber
196-
);
195+
bookerPhoneNumber,
196+
});
197197

198198
resultBooking = { ...foundBooking };
199199
resultBooking["message"] = "Payment required";

packages/features/bookings/lib/handleSeats/handleSeats.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ const handleSeats = async (newSeatedBookingObject: NewSeatedBookingObject) => {
3232
evt,
3333
workflows,
3434
rescheduledBy,
35+
isDryRun = false,
3536
} = newSeatedBookingObject;
36-
37+
// TODO: We could allow doing more things to support good dry run for seats
38+
if (isDryRun) return;
3739
const loggerWithEventDetails = createLoggerWithEventDetails(eventType.id, reqBodyUser, eventType.slug);
3840

3941
let resultBooking: HandleSeatsResultBooking = null;
@@ -124,6 +126,7 @@ const handleSeats = async (newSeatedBookingObject: NewSeatedBookingObject) => {
124126
isFirstRecurringEvent: true,
125127
emailAttendeeSendToOverride: bookerEmail,
126128
seatReferenceUid: evt.attendeeSeatId,
129+
isDryRun,
127130
});
128131
} catch (error) {
129132
loggerWithEventDetails.error("Error while scheduling workflow reminders", JSON.stringify({ error }));
@@ -149,7 +152,7 @@ const handleSeats = async (newSeatedBookingObject: NewSeatedBookingObject) => {
149152
rescheduledBy,
150153
};
151154

152-
await handleWebhookTrigger({ subscriberOptions, eventTrigger, webhookData });
155+
await handleWebhookTrigger({ subscriberOptions, eventTrigger, webhookData, isDryRun });
153156
}
154157

155158
return resultBooking;

packages/features/bookings/lib/handleSeats/types.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export type NewSeatedBookingObject = {
4343
responses: z.infer<ReturnType<typeof getBookingDataSchema>>["responses"] | null;
4444
rescheduledBy?: string;
4545
workflows: Workflow[];
46+
isDryRun?: boolean;
4647
};
4748

4849
export type RescheduleSeatedBookingObject = NewSeatedBookingObject & { rescheduleUid: string };

packages/features/bookings/lib/handleWebhookTrigger.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ export async function handleWebhookTrigger(args: {
99
subscriberOptions: GetSubscriberOptions;
1010
eventTrigger: string;
1111
webhookData: WebhookPayloadType;
12+
isDryRun?: boolean;
1213
}) {
1314
try {
15+
if (args.isDryRun) return;
1416
const subscribers = await getWebhooks(args.subscriberOptions);
1517

1618
const promises = subscribers.map((sub) =>

packages/features/ee/workflows/lib/reminders/reminderScheduler.ts

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export interface ScheduleWorkflowRemindersArgs extends ProcessWorkflowStepParams
3737
isNotConfirmed?: boolean;
3838
isRescheduleEvent?: boolean;
3939
isFirstRecurringEvent?: boolean;
40+
isDryRun?: boolean;
4041
}
4142

4243
const processWorkflowStep = async (
@@ -159,7 +160,9 @@ export const scheduleWorkflowReminders = async (args: ScheduleWorkflowRemindersA
159160
emailAttendeeSendToOverride = "",
160161
hideBranding,
161162
seatReferenceUid,
163+
isDryRun = false,
162164
} = args;
165+
if (isDryRun) return;
163166
if (isNotConfirmed || !workflows.length) return;
164167

165168
for (const workflow of workflows) {

packages/features/ee/workflows/lib/reminders/scheduleMandatoryReminder.ts

+18-8
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,24 @@ const log = logger.getSubLogger({ prefix: ["[scheduleMandatoryReminder]"] });
1111

1212
export type NewBookingEventType = Awaited<ReturnType<typeof getDefaultEvent>> | getEventTypeResponse;
1313

14-
export async function scheduleMandatoryReminder(
15-
evt: ExtendedCalendarEvent,
16-
workflows: Workflow[],
17-
requiresConfirmation: boolean,
18-
hideBranding: boolean,
19-
seatReferenceUid: string | undefined,
20-
isPlatformNoEmail = false
21-
) {
14+
export async function scheduleMandatoryReminder({
15+
evt,
16+
workflows,
17+
requiresConfirmation,
18+
hideBranding,
19+
seatReferenceUid,
20+
isPlatformNoEmail = false,
21+
isDryRun = false,
22+
}: {
23+
evt: ExtendedCalendarEvent;
24+
workflows: Workflow[];
25+
requiresConfirmation: boolean;
26+
hideBranding: boolean;
27+
seatReferenceUid: string | undefined;
28+
isPlatformNoEmail?: boolean;
29+
isDryRun?: boolean;
30+
}) {
31+
if (isDryRun) return;
2232
if (isPlatformNoEmail) return;
2333
try {
2434
const hasExistingWorkflow = workflows.some((workflow) => {

packages/features/webhooks/lib/scheduleTrigger.ts

+6
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,15 @@ export async function scheduleTrigger({
246246
subscriberUrl,
247247
subscriber,
248248
triggerEvent,
249+
isDryRun = false,
249250
}: {
250251
booking: { id: number; endTime: Date; startTime: Date };
251252
subscriberUrl: string;
252253
subscriber: { id: string; appId: string | null };
253254
triggerEvent: WebhookTriggerEvents;
255+
isDryRun?: boolean;
254256
}) {
257+
if (isDryRun) return;
255258
try {
256259
const payload = JSON.stringify({ triggerEvent, ...booking });
257260

@@ -285,14 +288,17 @@ export async function deleteWebhookScheduledTriggers({
285288
webhookId,
286289
userId,
287290
teamId,
291+
isDryRun = false,
288292
}: {
289293
booking?: { id: number; uid: string };
290294
appId?: string | null;
291295
triggerEvent?: WebhookTriggerEvents;
292296
webhookId?: string;
293297
userId?: number;
294298
teamId?: number;
299+
isDryRun?: boolean;
295300
}) {
301+
if (isDryRun) return;
296302
try {
297303
if (appId && (userId || teamId)) {
298304
const where: Prisma.BookingWhereInput = {};

packages/lib/payment/handlePayment.ts

+20-9
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,39 @@ import type { CompleteEventType } from "@calcom/prisma/zod";
66
import type { CalendarEvent } from "@calcom/types/Calendar";
77
import type { IAbstractPaymentService, PaymentApp } from "@calcom/types/PaymentService";
88

9-
const handlePayment = async (
10-
evt: CalendarEvent,
11-
selectedEventType: Pick<CompleteEventType, "metadata" | "title">,
9+
const handlePayment = async ({
10+
evt,
11+
selectedEventType,
12+
paymentAppCredentials,
13+
booking,
14+
bookerName,
15+
bookerEmail,
16+
bookerPhoneNumber,
17+
isDryRun = false,
18+
}: {
19+
evt: CalendarEvent;
20+
selectedEventType: Pick<CompleteEventType, "metadata" | "title">;
1221
paymentAppCredentials: {
1322
key: Prisma.JsonValue;
1423
appId: EventTypeAppsList;
1524
app: {
1625
dirName: string;
1726
categories: AppCategories[];
1827
} | null;
19-
},
28+
};
2029
booking: {
2130
user: { email: string | null; name: string | null; timeZone: string; username: string | null } | null;
2231
id: number;
2332
userId: number | null;
2433
startTime: { toISOString: () => string };
2534
uid: string;
26-
},
27-
bookerName: string,
28-
bookerEmail: string,
29-
bookerPhoneNumber?: string | null
30-
) => {
35+
};
36+
bookerName: string;
37+
bookerEmail: string;
38+
bookerPhoneNumber?: string | null;
39+
isDryRun?: boolean;
40+
}) => {
41+
if (isDryRun) return null;
3142
const paymentApp = (await appStore[
3243
paymentAppCredentials?.app?.dirName as keyof typeof appStore
3344
]?.()) as PaymentApp;

0 commit comments

Comments
 (0)