refactor: v2 OAuth webhooks & workflows (#17959)
* refactor: handleMarkNoShow OAuth webhook handling * refactor: confirm / decline booking OAuth webhook handling * refactor: pass oauth client to calendar event * refactor: pass oauth params * fix import * fix tests * chore: bump libraries * chore: bump libraries * chore: republish platform libraries * chore: republish platform libraries * fix: use replexica key in v2 and unit test CI * lock file * fixup! Merge branch 'main' into lauris/cal-4807-platform-refactor-oauth-webhooks * Revert "fix: use replexica key in v2 and unit test CI" This reverts commit 0bd6c364535f9e11a4d1497a6bd8909885562080. --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Morgan Vernay <morgan@cal.com>
This commit is contained in:
co-authored by
Morgan
Morgan Vernay
parent
b92db55380
commit
e2938ac39a
@@ -29,7 +29,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.63",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.67",
|
||||
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
|
||||
+8
-1
@@ -34,6 +34,7 @@ import {
|
||||
OrganizerCancelledEmail,
|
||||
AttendeeCancelledEmail,
|
||||
OrganizerReassignedEmail,
|
||||
AttendeeUpdatedEmail,
|
||||
} from "@calcom/platform-libraries";
|
||||
import {
|
||||
CreateBookingInput_2024_08_13,
|
||||
@@ -61,10 +62,12 @@ jest
|
||||
jest
|
||||
.spyOn(OrganizerCancelledEmail.prototype, "getHtml")
|
||||
.mockImplementation(() => Promise.resolve("<p>email</p>"));
|
||||
|
||||
jest
|
||||
.spyOn(OrganizerReassignedEmail.prototype, "getHtml")
|
||||
.mockImplementation(() => Promise.resolve("<p>email</p>"));
|
||||
jest
|
||||
.spyOn(AttendeeUpdatedEmail.prototype, "getHtml")
|
||||
.mockImplementation(() => Promise.resolve("<p>email</p>"));
|
||||
|
||||
type EmailSetup = {
|
||||
team: Team;
|
||||
@@ -681,6 +684,7 @@ describe("Bookings Endpoints 2024-08-13 team emails", () => {
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(AttendeeCancelledEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(OrganizerScheduledEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(AttendeeUpdatedEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
emailsDisabledSetup.roundRobinEventType.currentHostId = reassignToId;
|
||||
});
|
||||
});
|
||||
@@ -697,6 +701,7 @@ describe("Bookings Endpoints 2024-08-13 team emails", () => {
|
||||
expect(AttendeeCancelledEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(OrganizerScheduledEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(OrganizerReassignedEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(AttendeeUpdatedEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -898,6 +903,7 @@ describe("Bookings Endpoints 2024-08-13 team emails", () => {
|
||||
expect(responseBody.data).toBeDefined();
|
||||
expect(AttendeeCancelledEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(OrganizerScheduledEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
expect(AttendeeUpdatedEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
emailsDisabledSetup.roundRobinEventType.currentHostId = reassignToId;
|
||||
});
|
||||
});
|
||||
@@ -914,6 +920,7 @@ describe("Bookings Endpoints 2024-08-13 team emails", () => {
|
||||
expect(AttendeeCancelledEmail.prototype.getHtml).not.toHaveBeenCalled();
|
||||
expect(OrganizerScheduledEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
expect(OrganizerReassignedEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
expect(AttendeeUpdatedEmail.prototype.getHtml).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -363,12 +363,17 @@ export class BookingsService_2024_08_13 {
|
||||
|
||||
async markAbsent(bookingUid: string, bookingOwnerId: number, body: MarkAbsentBookingInput_2024_08_13) {
|
||||
const bodyTransformed = this.inputService.transformInputMarkAbsentBooking(body);
|
||||
const bookingBefore = await this.bookingsRepository.getByUid(bookingUid);
|
||||
const platformClientParams = bookingBefore?.eventTypeId
|
||||
? await this.inputService.getOAuthClientParams(bookingBefore.eventTypeId)
|
||||
: undefined;
|
||||
|
||||
await handleMarkNoShow({
|
||||
bookingUid,
|
||||
attendees: bodyTransformed.attendees,
|
||||
noShowHost: bodyTransformed.noShowHost,
|
||||
userId: bookingOwnerId,
|
||||
platformClientParams,
|
||||
});
|
||||
|
||||
const booking = await this.bookingsRepository.getByUidWithAttendeesAndUserAndEvent(bookingUid);
|
||||
@@ -423,7 +428,11 @@ export class BookingsService_2024_08_13 {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
const emailsEnabled = booking.eventTypeId ? await this.getEmailsEnabled(booking.eventTypeId) : true;
|
||||
const platformClientParams = booking.eventTypeId
|
||||
? await this.inputService.getOAuthClientParams(booking.eventTypeId)
|
||||
: undefined;
|
||||
|
||||
const emailsEnabled = platformClientParams ? platformClientParams.arePlatformEmailsEnabled : true;
|
||||
|
||||
const profile = this.usersService.getUserMainProfile(requestUser);
|
||||
|
||||
@@ -431,6 +440,7 @@ export class BookingsService_2024_08_13 {
|
||||
bookingId: booking.id,
|
||||
orgId: profile?.organizationId || null,
|
||||
emailsEnabled,
|
||||
platformClientParams,
|
||||
});
|
||||
|
||||
const reassigned = await this.bookingsRepository.getByUidWithUser(bookingUid);
|
||||
@@ -441,12 +451,6 @@ export class BookingsService_2024_08_13 {
|
||||
return this.outputService.getOutputReassignedBooking(reassigned);
|
||||
}
|
||||
|
||||
async getEmailsEnabled(eventTypeId: number) {
|
||||
const oAuthParams = await this.inputService.getOAuthClientParams(eventTypeId);
|
||||
const emailsEnabled = oAuthParams ? oAuthParams.arePlatformEmailsEnabled : true;
|
||||
return emailsEnabled;
|
||||
}
|
||||
|
||||
async reassignBookingToUser(
|
||||
bookingUid: string,
|
||||
newUserId: number,
|
||||
@@ -463,7 +467,11 @@ export class BookingsService_2024_08_13 {
|
||||
throw new NotFoundException(`User with id=${newUserId} was not found in the database`);
|
||||
}
|
||||
|
||||
const emailsEnabled = booking.eventTypeId ? await this.getEmailsEnabled(booking.eventTypeId) : true;
|
||||
const platformClientParams = booking.eventTypeId
|
||||
? await this.inputService.getOAuthClientParams(booking.eventTypeId)
|
||||
: undefined;
|
||||
|
||||
const emailsEnabled = platformClientParams ? platformClientParams.arePlatformEmailsEnabled : true;
|
||||
|
||||
const profile = this.usersService.getUserMainProfile(user);
|
||||
|
||||
@@ -474,6 +482,7 @@ export class BookingsService_2024_08_13 {
|
||||
reassignReason: body.reason,
|
||||
reassignedById,
|
||||
emailsEnabled,
|
||||
platformClientParams,
|
||||
});
|
||||
|
||||
return this.outputService.getOutputReassignedBooking(reassigned);
|
||||
@@ -485,7 +494,11 @@ export class BookingsService_2024_08_13 {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
const emailsEnabled = booking.eventTypeId ? await this.getEmailsEnabled(booking.eventTypeId) : true;
|
||||
const platformClientParams = booking.eventTypeId
|
||||
? await this.inputService.getOAuthClientParams(booking.eventTypeId)
|
||||
: undefined;
|
||||
|
||||
const emailsEnabled = platformClientParams ? platformClientParams.arePlatformEmailsEnabled : true;
|
||||
|
||||
await confirmBookingHandler({
|
||||
ctx: {
|
||||
@@ -496,6 +509,7 @@ export class BookingsService_2024_08_13 {
|
||||
confirmed: true,
|
||||
recurringEventId: booking.recurringEventId,
|
||||
emailsEnabled,
|
||||
platformClientParams,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -508,7 +522,11 @@ export class BookingsService_2024_08_13 {
|
||||
throw new NotFoundException(`Booking with uid=${bookingUid} was not found in the database`);
|
||||
}
|
||||
|
||||
const emailsEnabled = booking.eventTypeId ? await this.getEmailsEnabled(booking.eventTypeId) : true;
|
||||
const platformClientParams = booking.eventTypeId
|
||||
? await this.inputService.getOAuthClientParams(booking.eventTypeId)
|
||||
: undefined;
|
||||
|
||||
const emailsEnabled = platformClientParams ? platformClientParams.arePlatformEmailsEnabled : true;
|
||||
|
||||
await confirmBookingHandler({
|
||||
ctx: {
|
||||
@@ -520,6 +538,7 @@ export class BookingsService_2024_08_13 {
|
||||
recurringEventId: booking.recurringEventId,
|
||||
reason,
|
||||
emailsEnabled,
|
||||
platformClientParams,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -24,10 +24,10 @@ import { withNextAuth } from "test/utils/withNextAuth";
|
||||
|
||||
import { PlatformOAuthClient, Team, Webhook } from "@calcom/prisma/client";
|
||||
|
||||
describe("EventTypes WebhooksController (e2e)", () => {
|
||||
describe("OAuth client WebhooksController (e2e)", () => {
|
||||
let app: INestApplication;
|
||||
const userEmail = "event-types-webhook-controller-e2e@api.com";
|
||||
const otherUserEmail = "other-event-types-webhook-controller-e2e@api.com";
|
||||
const userEmail = "oauth-client-webhook-controller-e2e@api.com";
|
||||
const otherUserEmail = "other-oauth-client-webhook-controller-e2e@api.com";
|
||||
let user: UserWithProfile;
|
||||
let otherUser: UserWithProfile;
|
||||
let oAuthClient: PlatformOAuthClient;
|
||||
|
||||
@@ -23,6 +23,7 @@ import { safeStringify } from "@calcom/lib/safeStringify";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import type { SchedulingType } from "@calcom/prisma/enums";
|
||||
import { BookingStatus, WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import type { PlatformClientParams } from "@calcom/prisma/zod-utils";
|
||||
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { getAllWorkflowsFromEventType } from "@calcom/trpc/server/routers/viewer/workflows/util";
|
||||
import type { AdditionalInformation, CalendarEvent } from "@calcom/types/Calendar";
|
||||
@@ -68,8 +69,19 @@ export async function handleConfirmation(args: {
|
||||
};
|
||||
paid?: boolean;
|
||||
emailsEnabled?: boolean;
|
||||
platformClientParams?: PlatformClientParams;
|
||||
}) {
|
||||
const { user, evt, recurringEventId, prisma, bookingId, booking, paid, emailsEnabled = true } = args;
|
||||
const {
|
||||
user,
|
||||
evt,
|
||||
recurringEventId,
|
||||
prisma,
|
||||
bookingId,
|
||||
booking,
|
||||
paid,
|
||||
emailsEnabled = true,
|
||||
platformClientParams,
|
||||
} = args;
|
||||
const eventType = booking.eventType;
|
||||
const eventTypeMetadata = EventTypeMetaDataSchema.parse(eventType?.metadata || {});
|
||||
const eventManager = new EventManager(user, eventTypeMetadata?.apps);
|
||||
@@ -355,6 +367,7 @@ export async function handleConfirmation(args: {
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_CREATED,
|
||||
teamId,
|
||||
orgId,
|
||||
oAuthClientId: platformClientParams?.platformClientId,
|
||||
});
|
||||
const subscribersMeetingStarted = await getWebhooks({
|
||||
userId,
|
||||
@@ -362,6 +375,7 @@ export async function handleConfirmation(args: {
|
||||
triggerEvent: WebhookTriggerEvents.MEETING_STARTED,
|
||||
teamId: eventType?.teamId,
|
||||
orgId,
|
||||
oAuthClientId: platformClientParams?.platformClientId,
|
||||
});
|
||||
const subscribersMeetingEnded = await getWebhooks({
|
||||
userId,
|
||||
@@ -369,6 +383,7 @@ export async function handleConfirmation(args: {
|
||||
triggerEvent: WebhookTriggerEvents.MEETING_ENDED,
|
||||
teamId: eventType?.teamId,
|
||||
orgId,
|
||||
oAuthClientId: platformClientParams?.platformClientId,
|
||||
});
|
||||
|
||||
const scheduleTriggerPromises: Promise<unknown>[] = [];
|
||||
@@ -410,6 +425,7 @@ export async function handleConfirmation(args: {
|
||||
eventTypeId: booking.eventTypeId,
|
||||
teamId,
|
||||
orgId,
|
||||
oAuthClientId: platformClientParams?.platformClientId,
|
||||
});
|
||||
|
||||
const eventTypeInfo: EventTypeInfo = {
|
||||
@@ -429,6 +445,7 @@ export async function handleConfirmation(args: {
|
||||
status: "ACCEPTED",
|
||||
smsReminderNumber: booking.smsReminderNumber || undefined,
|
||||
metadata: meetingUrl ? { videoCallUrl: meetingUrl } : undefined,
|
||||
...(platformClientParams ? platformClientParams : {}),
|
||||
};
|
||||
|
||||
const promises = subscribersBookingCreated.map((sub) =>
|
||||
@@ -440,7 +457,7 @@ export async function handleConfirmation(args: {
|
||||
payload
|
||||
).catch((e) => {
|
||||
log.error(
|
||||
`Error executing webhook for event: ${WebhookTriggerEvents.BOOKING_CREATED}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}`,
|
||||
`Error executing webhook for event: ${WebhookTriggerEvents.BOOKING_CREATED}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}, platformClientId: ${platformClientParams?.platformClientId}`,
|
||||
safeStringify(e)
|
||||
);
|
||||
})
|
||||
@@ -456,6 +473,7 @@ export async function handleConfirmation(args: {
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_PAID,
|
||||
teamId: eventType?.teamId,
|
||||
orgId,
|
||||
oAuthClientId: platformClientParams?.platformClientId,
|
||||
});
|
||||
const bookingWithPayment = await prisma.booking.findFirst({
|
||||
where: {
|
||||
|
||||
@@ -65,6 +65,7 @@ import { WorkflowRepository } from "@calcom/lib/server/repository/workflow";
|
||||
import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { BookingStatus, SchedulingType, WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import type { PlatformClientParams } from "@calcom/prisma/zod-utils";
|
||||
import { userMetadata as userMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { getAllWorkflowsFromEventType } from "@calcom/trpc/server/routers/viewer/workflows/util";
|
||||
import type { AdditionalInformation, AppsStatus, CalendarEvent, Person } from "@calcom/types/Calendar";
|
||||
@@ -339,14 +340,10 @@ function buildTroubleshooterData({
|
||||
}
|
||||
|
||||
async function handler(
|
||||
req: NextApiRequest & {
|
||||
userId?: number | undefined;
|
||||
platformClientId?: string;
|
||||
platformRescheduleUrl?: string;
|
||||
platformCancelUrl?: string;
|
||||
platformBookingUrl?: string;
|
||||
platformBookingLocation?: string;
|
||||
},
|
||||
req: NextApiRequest &
|
||||
PlatformClientParams & {
|
||||
userId?: number | undefined;
|
||||
},
|
||||
bookingDataSchemaGetter: BookingDataSchemaGetter = getBookingDataSchema
|
||||
) {
|
||||
const {
|
||||
|
||||
@@ -13,10 +13,11 @@ type ScheduleNoShowTriggersArgs = {
|
||||
eventTypeId: number | null;
|
||||
teamId?: number | null;
|
||||
orgId?: number | null;
|
||||
oAuthClientId?: string | null;
|
||||
};
|
||||
|
||||
export const scheduleNoShowTriggers = async (args: ScheduleNoShowTriggersArgs) => {
|
||||
const { booking, triggerForUser, organizerUser, eventTypeId, teamId, orgId } = args;
|
||||
const { booking, triggerForUser, organizerUser, eventTypeId, teamId, orgId, oAuthClientId } = args;
|
||||
|
||||
// Add task for automatic no show in cal video
|
||||
const noShowPromises: Promise<any>[] = [];
|
||||
@@ -27,6 +28,7 @@ export const scheduleNoShowTriggers = async (args: ScheduleNoShowTriggersArgs) =
|
||||
triggerEvent: WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW,
|
||||
teamId,
|
||||
orgId,
|
||||
oAuthClientId,
|
||||
});
|
||||
|
||||
noShowPromises.push(
|
||||
@@ -56,6 +58,7 @@ export const scheduleNoShowTriggers = async (args: ScheduleNoShowTriggersArgs) =
|
||||
triggerEvent: WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW,
|
||||
teamId,
|
||||
orgId,
|
||||
oAuthClientId,
|
||||
});
|
||||
|
||||
noShowPromises.push(
|
||||
|
||||
@@ -28,7 +28,7 @@ import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { WorkflowActions, WorkflowMethods, WorkflowTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { userMetadata as userMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeMetadata, PlatformClientParams } from "@calcom/prisma/zod-utils";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { handleRescheduleEventManager } from "./handleRescheduleEventManager";
|
||||
@@ -49,6 +49,7 @@ export const roundRobinManualReassignment = async ({
|
||||
reassignReason,
|
||||
reassignedById,
|
||||
emailsEnabled = true,
|
||||
platformClientParams,
|
||||
}: {
|
||||
bookingId: number;
|
||||
newUserId: number;
|
||||
@@ -56,6 +57,7 @@ export const roundRobinManualReassignment = async ({
|
||||
reassignReason?: string;
|
||||
reassignedById: number;
|
||||
emailsEnabled?: boolean;
|
||||
platformClientParams?: PlatformClientParams;
|
||||
}) => {
|
||||
const roundRobinReassignLogger = logger.getSubLogger({
|
||||
prefix: ["roundRobinManualReassign", `${bookingId}`],
|
||||
@@ -264,6 +266,7 @@ export const roundRobinManualReassignment = async ({
|
||||
booking,
|
||||
}),
|
||||
location: bookingLocation,
|
||||
...(platformClientParams ? platformClientParams : {}),
|
||||
};
|
||||
|
||||
const credentials = await prisma.credential.findMany({
|
||||
|
||||
@@ -30,7 +30,7 @@ import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { WorkflowActions, WorkflowMethods, WorkflowTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { userMetadata as userMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeMetadata, PlatformClientParams } from "@calcom/prisma/zod-utils";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { handleRescheduleEventManager } from "./handleRescheduleEventManager";
|
||||
@@ -42,10 +42,12 @@ export const roundRobinReassignment = async ({
|
||||
bookingId,
|
||||
orgId,
|
||||
emailsEnabled = true,
|
||||
platformClientParams,
|
||||
}: {
|
||||
bookingId: number;
|
||||
orgId: number | null;
|
||||
emailsEnabled?: boolean;
|
||||
platformClientParams?: PlatformClientParams;
|
||||
}) => {
|
||||
const roundRobinReassignLogger = logger.getSubLogger({
|
||||
prefix: ["roundRobinReassign", `${bookingId}`],
|
||||
@@ -294,6 +296,7 @@ export const roundRobinReassignment = async ({
|
||||
booking,
|
||||
}),
|
||||
location: bookingLocation,
|
||||
...(platformClientParams ? platformClientParams : {}),
|
||||
};
|
||||
|
||||
const credentials = await prisma.credential.findMany({
|
||||
|
||||
@@ -8,6 +8,7 @@ import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import { BookingRepository } from "@calcom/lib/server/repository/booking";
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import { WebhookTriggerEvents } from "@calcom/prisma/client";
|
||||
import type { PlatformClientParams } from "@calcom/prisma/zod-utils";
|
||||
import type { TNoShowInputSchema } from "@calcom/trpc/server/routers/loggedInViewer/markNoShow.schema";
|
||||
|
||||
import handleSendingAttendeeNoShowDataToApps from "./noShow/handleSendingAttendeeNoShowDataToApps";
|
||||
@@ -82,7 +83,12 @@ const handleMarkNoShow = async ({
|
||||
noShowHost,
|
||||
userId,
|
||||
locale,
|
||||
}: TNoShowInputSchema & { userId?: number; locale?: string }) => {
|
||||
platformClientParams,
|
||||
}: TNoShowInputSchema & {
|
||||
userId?: number;
|
||||
locale?: string;
|
||||
platformClientParams?: PlatformClientParams;
|
||||
}) => {
|
||||
const responsePayload = new ResponsePayload();
|
||||
const t = await getTranslation(locale ?? "en", "common");
|
||||
|
||||
@@ -94,13 +100,17 @@ const handleMarkNoShow = async ({
|
||||
|
||||
const payload = await buildResultPayload(bookingUid, attendeeEmails, attendees, t);
|
||||
|
||||
const { webhooks, bookingId } = await getWebhooksService(bookingUid);
|
||||
const { webhooks, bookingId } = await getWebhooksService(
|
||||
bookingUid,
|
||||
platformClientParams?.platformClientId
|
||||
);
|
||||
|
||||
await webhooks.sendPayload({
|
||||
...payload,
|
||||
/** We send webhook message pre-translated, on client we already handle this */
|
||||
bookingUid,
|
||||
bookingId,
|
||||
...(platformClientParams ? platformClientParams : {}),
|
||||
});
|
||||
|
||||
responsePayload.setAttendees(payload.attendees);
|
||||
@@ -179,7 +189,7 @@ const updateAttendees = async (
|
||||
.map((x) => ({ email: x.email, noShow: x.noShow }));
|
||||
};
|
||||
|
||||
const getWebhooksService = async (bookingUid: string) => {
|
||||
const getWebhooksService = async (bookingUid: string, platformClientId?: string) => {
|
||||
const booking = await prisma.booking.findUnique({
|
||||
where: { uid: bookingUid },
|
||||
select: {
|
||||
@@ -204,6 +214,7 @@ const getWebhooksService = async (bookingUid: string) => {
|
||||
eventTypeId: booking?.eventType?.id,
|
||||
orgId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_NO_SHOW_UPDATED,
|
||||
oAuthClientId: platformClientId,
|
||||
});
|
||||
|
||||
return { webhooks, bookingId: booking?.id };
|
||||
|
||||
@@ -276,12 +276,23 @@ export const requiredCustomInputSchema = z.union([
|
||||
|
||||
export type BookingCreateBody = z.input<typeof bookingCreateBodySchema>;
|
||||
|
||||
const PlatformClientParamsSchema = z.object({
|
||||
platformClientId: z.string().optional(),
|
||||
platformRescheduleUrl: z.string().nullable().optional(),
|
||||
platformCancelUrl: z.string().nullable().optional(),
|
||||
platformBookingUrl: z.string().nullable().optional(),
|
||||
platformBookingLocation: z.string().optional(),
|
||||
});
|
||||
|
||||
export type PlatformClientParams = z.infer<typeof PlatformClientParamsSchema>;
|
||||
|
||||
export const bookingConfirmPatchBodySchema = z.object({
|
||||
bookingId: z.number(),
|
||||
confirmed: z.boolean(),
|
||||
recurringEventId: z.string().optional(),
|
||||
reason: z.string().optional(),
|
||||
emailsEnabled: z.boolean().default(true),
|
||||
platformClientParams: PlatformClientParamsSchema.optional(),
|
||||
});
|
||||
|
||||
// `responses` is merged with it during handleNewBooking call because `responses` schema is dynamic and depends on eventType
|
||||
|
||||
@@ -8,6 +8,7 @@ import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventR
|
||||
import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation";
|
||||
import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhookTrigger";
|
||||
import { workflowSelect } from "@calcom/features/ee/workflows/lib/getAllWorkflows";
|
||||
import type { GetSubscriberOptions } from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
import type { EventPayloadType, EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload";
|
||||
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
|
||||
import { getBookerBaseUrl } from "@calcom/lib/getBookerUrl/server";
|
||||
@@ -41,7 +42,14 @@ type ConfirmOptions = {
|
||||
|
||||
export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => {
|
||||
const { user } = ctx;
|
||||
const { bookingId, recurringEventId, reason: rejectionReason, confirmed, emailsEnabled } = input;
|
||||
const {
|
||||
bookingId,
|
||||
recurringEventId,
|
||||
reason: rejectionReason,
|
||||
confirmed,
|
||||
emailsEnabled,
|
||||
platformClientParams,
|
||||
} = input;
|
||||
|
||||
const tOrganizer = await getTranslation(user.locale ?? "en", "common");
|
||||
|
||||
@@ -214,6 +222,7 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => {
|
||||
members: [],
|
||||
}
|
||||
: undefined,
|
||||
...(platformClientParams ? platformClientParams : {}),
|
||||
};
|
||||
|
||||
const recurringEvent = parseRecurringEvent(booking.eventType?.recurringEvent);
|
||||
@@ -270,6 +279,7 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => {
|
||||
bookingId,
|
||||
booking,
|
||||
emailsEnabled,
|
||||
platformClientParams,
|
||||
});
|
||||
} else {
|
||||
evt.rejectionReason = rejectionReason;
|
||||
@@ -383,12 +393,13 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => {
|
||||
const orgId = await getOrgIdFromMemberOrTeamId({ memberId: booking.userId, teamId });
|
||||
|
||||
// send BOOKING_REJECTED webhooks
|
||||
const subscriberOptions = {
|
||||
const subscriberOptions: GetSubscriberOptions = {
|
||||
userId: booking.userId,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
triggerEvent: WebhookTriggerEvents.BOOKING_REJECTED,
|
||||
teamId,
|
||||
orgId,
|
||||
oAuthClientId: platformClientParams?.platformClientId,
|
||||
};
|
||||
const eventTrigger: WebhookTriggerEvents = WebhookTriggerEvents.BOOKING_REJECTED;
|
||||
const eventTypeInfo: EventTypeInfo = {
|
||||
|
||||
Reference in New Issue
Block a user