Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions apps/api/v2/src/ee/bookings/2024-08-13/bookings.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,42 @@ export class BookingsRepository_2024_08_13 {
});
}

async getByUidForCalendarLinks(uid: string) {
const booking = await this.dbRead.prisma.booking.findUnique({
where: { uid },
select: {
startTime: true,
endTime: true,
location: true,
title: true,
metadata: true,
responses: true,
eventTypeId: true,
attendees: {
select: {
bookingSeat: {
select: { data: true },
},
},
},
},
});
if (!booking) {
return null;
}

return {
startTime: booking.startTime,
endTime: booking.endTime,
location: booking.location,
title: booking.title,
responses: booking.responses as Prisma.JsonObject,
metadata: booking.metadata as Prisma.JsonObject | null,
attendees: booking.attendees,
eventTypeId: booking.eventTypeId,
};
}

async getRecurringByUid(uid: string) {
return this.dbRead.prisma.booking.findMany({
where: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ export class BookingsService_2024_08_13 {
}

async getCalendarLinks(bookingUid: string): Promise<CalendarLink[]> {
const booking = await this.bookingsRepository.getByUidWithAttendeesAndUserAndEvent(bookingUid);
const booking = await this.bookingsRepository.getByUidForCalendarLinks(bookingUid);

if (!booking) {
throw new NotFoundException(`Booking with uid ${bookingUid} not found`);
Expand Down
15 changes: 14 additions & 1 deletion apps/web/modules/bookings/views/bookings-single-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,21 @@ export default function Success(props: PageProps) {
const utmParams = bookingInfo.tracking;

const [date, setDate] = useState(dayjs.utc(bookingInfo.startTime));

const calendarLinksBooking = {
startTime: bookingWithParsedMetadata.startTime,
endTime: bookingWithParsedMetadata.endTime,
location: bookingWithParsedMetadata.location,
title: bookingWithParsedMetadata.title,
responses: bookingWithParsedMetadata.responses,
metadata: bookingWithParsedMetadata.metadata,
attendees: bookingWithParsedMetadata.attendees?.map(attendee => ({
bookingSeat: null // No bookingSeat data in this context
})) || []
};

const calendarLinks = getCalendarLinks({
booking: bookingWithParsedMetadata,
booking: calendarLinksBooking,
eventType: eventType,
t,
});
Expand Down
23 changes: 16 additions & 7 deletions packages/features/bookings/lib/getCalendarLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import type { z } from "zod";

import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs";
import type { Prisma } from "@calcom/prisma/client";
import type { nameObjectSchema } from "@calcom/features/eventtypes/lib/eventNaming";
import { getEventName } from "@calcom/features/eventtypes/lib/eventNaming";
import type { Prisma } from "@calcom/prisma/client";
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
import type { RecurringEvent } from "@calcom/types/Calendar";

Expand Down Expand Up @@ -145,8 +145,9 @@ export const getCalendarLinks = ({
endTime: Date;
location: string | null;
title: string;
responses: Prisma.JsonObject;
metadata: Prisma.JsonObject | null;
responses: Prisma.JsonValue;
metadata: Prisma.JsonValue;
attendees?: Array<{ bookingSeat?: { data: Prisma.JsonValue } | null }>;
};
eventType: {
recurringEvent: RecurringEventOrPrismaJsonObject;
Expand All @@ -167,16 +168,24 @@ export const getCalendarLinks = ({
let evtName = eventType.eventName;
const videoCallUrl = bookingMetadataSchema.parse(booking?.metadata || {})?.videoCallUrl ?? null;

if (eventType.isDynamic && booking.responses.title) {
evtName = booking.responses.title as string;
const rawBookingData = booking.attendees?.[0]?.bookingSeat?.data || booking.responses;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When pulling seated booking data we must read bookingSeat.data.responses; using the whole object leaves dynamic titles/attendee fields undefined and breaks calendar link personalization.

Prompt for AI agents
Address the following comment on packages/features/bookings/lib/getCalendarLinks.ts at line 171:

<comment>When pulling seated booking data we must read bookingSeat.data.responses; using the whole object leaves dynamic titles/attendee fields undefined and breaks calendar link personalization.</comment>

<file context>
@@ -167,16 +168,24 @@ export const getCalendarLinks = ({
 
-  if (eventType.isDynamic &amp;&amp; booking.responses.title) {
-    evtName = booking.responses.title as string;
+  const rawBookingData = booking.attendees?.[0]?.bookingSeat?.data || booking.responses;
+  const bookingData = (
+    rawBookingData &amp;&amp; typeof rawBookingData === &quot;object&quot; &amp;&amp; !Array.isArray(rawBookingData)
</file context>
Suggested change
const rawBookingData = booking.attendees?.[0]?.bookingSeat?.data || booking.responses;
const rawBookingData = (booking.attendees?.[0]?.bookingSeat?.data as Prisma.JsonObject | undefined)?.responses || booking.responses;
Fix with Cubic

const bookingData = (
rawBookingData && typeof rawBookingData === "object" && !Array.isArray(rawBookingData)
? rawBookingData
: {}
) as Prisma.JsonObject;

if (eventType.isDynamic && bookingData.title) {
evtName = bookingData.title as string;
}

const eventNameObject = {
attendeeName: booking.responses.name as z.infer<typeof nameObjectSchema> | string,
attendeeName: bookingData.name as z.infer<typeof nameObjectSchema> | string,
eventType: eventType.title,
eventName: evtName,
host: eventType.team?.name || eventType.users[0]?.name || "Nameless",
location: booking.location,
bookingFields: booking.responses,
bookingFields: bookingData,
eventDuration: dayjs(booking.endTime).diff(booking.startTime, "minutes"),
t,
};
Expand Down
Loading