From 688541923be52f0fe8b9951972b0297411244206 Mon Sep 17 00:00:00 2001 From: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Date: Thu, 15 Dec 2022 22:43:07 +0100 Subject: [PATCH] Save meeting url to metadata of bookings and add it to webhook payload (#5773) * small design fix for time unit select * save video cal url to booking in metaData * save video url when bookings are confirmed * fix e2e tests * remove not needed waitForNavigation * add metadata to booking created webhook payload * add migration * fix type error * adjust e2e tests * add bookingMetadataSchema * add missing change from merge * add new line to expected test result * update snapshot * fix e2e tests * Update confirm.ts Co-authored-by: CarinaWolli Co-authored-by: zomars --- apps/web/playwright/webhook.e2e.ts | 1 + .../webhookResponse--calcom-web.txt | 2 +- .../features/bookings/lib/handleNewBooking.ts | 13 ++++++++++--- .../components/TimeTimeUnitInput.tsx | 2 +- .../lib/server/queries/bookings/confirm.ts | 19 ++++++++++++------- packages/lib/test/builder.ts | 1 + .../migration.sql | 2 ++ packages/prisma/schema.prisma | 2 ++ packages/prisma/zod-utils.ts | 6 ++++++ 9 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 packages/prisma/migrations/20221129125935_add_metadata_to_booking/migration.sql diff --git a/apps/web/playwright/webhook.e2e.ts b/apps/web/playwright/webhook.e2e.ts index cf1c64b3f0..9c48421222 100644 --- a/apps/web/playwright/webhook.e2e.ts +++ b/apps/web/playwright/webhook.e2e.ts @@ -67,6 +67,7 @@ test("add webhook & test that creating an event triggers a webhook call", async body.payload.eventTypeId = dynamic; body.payload.videoCallData = dynamic; body.payload.appsStatus = dynamic; + body.payload.metadata.videoCallUrl = dynamic; // if we change the shape of our webhooks, we can simply update this by clicking `u` // console.log("BODY", body); diff --git a/apps/web/playwright/webhook.e2e.ts-snapshots/webhookResponse--calcom-web.txt b/apps/web/playwright/webhook.e2e.ts-snapshots/webhookResponse--calcom-web.txt index df45e9df6d..18700cb784 100644 --- a/apps/web/playwright/webhook.e2e.ts-snapshots/webhookResponse--calcom-web.txt +++ b/apps/web/playwright/webhook.e2e.ts-snapshots/webhookResponse--calcom-web.txt @@ -1 +1 @@ -{"triggerEvent":"BOOKING_CREATED","createdAt":"[redacted/dynamic]","payload":{"type":"30 min","title":"30 min between Nameless and Test Testson","description":"","additionalNotes":"","customInputs":{},"startTime":"[redacted/dynamic]","endTime":"[redacted/dynamic]","organizer":{"name":"Nameless","email":"[redacted/dynamic]","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"},"attendees":[{"email":"test@example.com","name":"Test Testson","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"}],"location":"[redacted/dynamic]","destinationCalendar":null,"hideCalendarNotes":false,"requiresConfirmation":"[redacted/dynamic]","eventTypeId":"[redacted/dynamic]","seatsShowAttendees":false,"uid":"[redacted/dynamic]","videoCallData":"[redacted/dynamic]","appsStatus":"[redacted/dynamic]","eventTitle":"30 min","eventDescription":null,"price":0,"currency":"usd","length":30,"bookingId":"[redacted/dynamic]","metadata":{},"status":"ACCEPTED","additionalInformation":"[redacted/dynamic]"}} \ No newline at end of file +{"triggerEvent":"BOOKING_CREATED","createdAt":"[redacted/dynamic]","payload":{"type":"30 min","title":"30 min between Nameless and Test Testson","description":"","additionalNotes":"","customInputs":{},"startTime":"[redacted/dynamic]","endTime":"[redacted/dynamic]","organizer":{"name":"Nameless","email":"[redacted/dynamic]","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"},"attendees":[{"email":"test@example.com","name":"Test Testson","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"}],"location":"[redacted/dynamic]","destinationCalendar":null,"hideCalendarNotes":false,"requiresConfirmation":"[redacted/dynamic]","eventTypeId":"[redacted/dynamic]","seatsShowAttendees":false,"uid":"[redacted/dynamic]","videoCallData":"[redacted/dynamic]","appsStatus":"[redacted/dynamic]","eventTitle":"30 min","eventDescription":null,"price":0,"currency":"usd","length":30,"bookingId":"[redacted/dynamic]","metadata":{"videoCallUrl":"[redacted/dynamic]"},"status":"ACCEPTED","additionalInformation":"[redacted/dynamic]"}} \ No newline at end of file diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index 438d6a69e5..880fc4dc24 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -835,6 +835,8 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { evt.appsStatus = Object.values(calcAppsStatus); } + let videoCallUrl; + if (originalRescheduledBooking?.uid) { // Use EventManager to conditionally use all needed integrations. const updateManager = await eventManager.reschedule( @@ -869,9 +871,9 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { metadata.conferenceData = updatedEvent.conferenceData; metadata.entryPoints = updatedEvent.entryPoints; handleAppsStatus(results, booking); + videoCallUrl = metadata.hangoutLink || videoCallUrl; } } - if (noEmail !== true) { await sendRescheduledEmails({ ...evt, @@ -893,6 +895,9 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { results = createManager.results; referencesToCreate = createManager.referencesToCreate; + + videoCallUrl = evt.videoCallData && evt.videoCallData.url ? evt.videoCallData.url : null; + if (results.length > 0 && results.every((res) => !res.success)) { const error = { errorCode: "BookingCreatingMeetingFailed", @@ -909,6 +914,7 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { metadata.conferenceData = results[0].createdEvent?.conferenceData; metadata.entryPoints = results[0].createdEvent?.entryPoints; handleAppsStatus(results, booking); + videoCallUrl = metadata.hangoutLink || videoCallUrl; } if (noEmail !== true) { await sendScheduledEmails({ @@ -945,7 +951,7 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { } log.debug(`Booking ${organizerUser.username} completed`); - + const metadata = videoCallUrl ? { videoCallUrl } : undefined; if (isConfirmedByDefault) { const eventTrigger: WebhookTriggerEvents = rescheduleUid ? WebhookTriggerEvents.BOOKING_RESCHEDULED @@ -1001,7 +1007,7 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { ...eventTypeInfo, bookingId, rescheduleUid, - metadata: reqBody.metadata, + metadata: { ...metadata, ...reqBody.metadata }, eventTypeId, status: "ACCEPTED", smsReminderNumber: booking?.smsReminderNumber || undefined, @@ -1043,6 +1049,7 @@ async function handler(req: NextApiRequest & { userId?: number | undefined }) { uid: booking.uid, }, data: { + metadata, references: { createMany: { data: referencesToCreate, diff --git a/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx b/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx index 411d588535..b9a0a01e71 100644 --- a/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx +++ b/packages/features/ee/workflows/components/TimeTimeUnitInput.tsx @@ -42,7 +42,7 @@ export const TimeTimeUnitInput = (props: Props) => {