fix: reschedule flow is broken for seated booking#23987
Conversation
WalkthroughBookingListItem now finds a userSeat by matching booking.seatsReferences attendees to the current user and sets isAttendee; getSeatReferenceUid returns only userSeat?.referenceUid (no fallback). BookingActionContext now includes isAttendee and bookingActions conditionally include seatReferenceUid in generated links only when isAttendee is true. getServerSideProps for the reschedule route prefers a provided seatReferenceUid over bookingUid. The viewer bookings handler removed the Attendee.email = user.email filter from SeatsReferences. E2E tests for rescheduling seated bookings were added. Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
| label: t("reschedule_booking"), | ||
| href: `/reschedule/${booking.uid}${ | ||
| booking.seatsReferences.length ? `?seatReferenceUid=${getSeatReferenceUid()}` : "" | ||
| booking.seatsReferences.length && isAttendee ? `?seatReferenceUid=${getSeatReferenceUid()}` : "" |
There was a problem hiding this comment.
If the currentUser is a host or admin/pwner don't include seatRefuid
| if (!booking.seatsReferences[0]) { | ||
| return undefined; | ||
| } | ||
| return booking.seatsReferences[0].referenceUid; |
There was a problem hiding this comment.
It was always returning the first attendee's seat
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/lib/reschedule/[uid]/getServerSideProps.ts (1)
89-90: Narrow Prisma selection for booking.user.Selecting
user: truefetches all columns. Onlyidis needed forenrichUserWithItsProfile. Reduce surface per our guideline “only select what you need”.Apply:
- user: true, + user: { + select: { id: true }, + },
🧹 Nitpick comments (3)
apps/web/lib/reschedule/[uid]/getServerSideProps.ts (1)
148-173: Access control for seated bookings without seatReferenceUid looks right; tiny polish.Use
.some(...)for boolean intent instead of.find(...)+ truthiness.- const userIsHost = booking?.eventType.hosts.find((host) => { - if (host.user.id === userId) return true; - }); + const userIsHost = booking?.eventType.hosts.some((host) => host.user.id === userId);Please confirm there’s no code path where a non‑host/owner without a valid
seatReferenceUidshould be allowed through.apps/web/components/booking/bookingActions.ts (1)
66-74: Follow-up: cancel action still appends seatReferenceUid unconditionally for seated events.This relies on
getSeatReferenceUid()returning a string; see bug in BookingListItem fallback that can yield an object. Once fixed, consider mirroring the attendee-gate here if product wants hosts to cancel entire booking rather than a seat.apps/web/components/booking/BookingListItem.tsx (1)
187-188: Make attendee detection case-insensitive and explicit.Email comparisons should be case-insensitive. Also prefer
.some()for intent.- const isAttendee = !!booking.attendees.find((attendee) => attendee.email === userEmail); + const isAttendee = + !!userEmail && + booking.attendees.some((a) => a.email?.toLowerCase() === userEmail.toLowerCase());
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
apps/web/components/booking/BookingListItem.tsx(3 hunks)apps/web/components/booking/bookingActions.ts(3 hunks)apps/web/lib/reschedule/[uid]/getServerSideProps.ts(2 hunks)apps/web/playwright/booking-seats.e2e.ts(1 hunks)packages/trpc/server/routers/viewer/bookings/get.handler.ts(0 hunks)
💤 Files with no reviewable changes (1)
- packages/trpc/server/routers/viewer/bookings/get.handler.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
apps/web/components/booking/bookingActions.tsapps/web/lib/reschedule/[uid]/getServerSideProps.tsapps/web/playwright/booking-seats.e2e.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
apps/web/components/booking/bookingActions.tsapps/web/components/booking/BookingListItem.tsxapps/web/lib/reschedule/[uid]/getServerSideProps.tsapps/web/playwright/booking-seats.e2e.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
apps/web/components/booking/bookingActions.tsapps/web/components/booking/BookingListItem.tsxapps/web/lib/reschedule/[uid]/getServerSideProps.tsapps/web/playwright/booking-seats.e2e.ts
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Always use
t()for text localization in frontend code; direct text embedding should trigger a warning
Files:
apps/web/components/booking/BookingListItem.tsx
🧠 Learnings (6)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.
Applied to files:
apps/web/lib/reschedule/[uid]/getServerSideProps.ts
📚 Learning: 2025-08-20T17:34:35.004Z
Learnt from: mdm317
PR: calcom/cal.com#23221
File: packages/features/schedules/components/NewScheduleButton.tsx:1-1
Timestamp: 2025-08-20T17:34:35.004Z
Learning: In the Cal.com codebase, server actions like `revalidateAvailabilityList()` from `app/(use-page-wrapper)/(main-nav)/availability/actions` are imported and called directly in client components within mutation `onSuccess` callbacks. This pattern is consistently used across availability-related components (both in availability-view.tsx for updates and NewScheduleButton.tsx for creates) to ensure the availability list cache is fresh after mutations.
Applied to files:
apps/web/lib/reschedule/[uid]/getServerSideProps.ts
📚 Learning: 2025-08-19T09:47:49.478Z
Learnt from: eunjae-lee
PR: calcom/cal.com#23166
File: packages/prisma/migrations/20250818151914_routing_form_response_denormalized_backfill2/migration.sql:65-66
Timestamp: 2025-08-19T09:47:49.478Z
Learning: The Booking table has a unique constraint and index on the uid column (defined as `uid String unique` in schema.prisma), so JOINs on Booking.uid have optimal performance and don't require additional indexing.
Applied to files:
apps/web/lib/reschedule/[uid]/getServerSideProps.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.
Applied to files:
apps/web/playwright/booking-seats.e2e.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.
Applied to files:
apps/web/playwright/booking-seats.e2e.ts
🧬 Code graph analysis (1)
apps/web/playwright/booking-seats.e2e.ts (1)
apps/web/playwright/lib/testUtils.ts (3)
createUserWithSeatedEventAndAttendees(373-391)selectFirstAvailableTimeSlotNextMonth(109-117)confirmReschedule(510-514)
🔇 Additional comments (5)
apps/web/lib/reschedule/[uid]/getServerSideProps.ts (1)
42-42: Good: prefer seatReferenceUid when present.This fixes the seated flow by resolving the booking via seat when provided.
apps/web/components/booking/bookingActions.ts (1)
100-118: Gate seatReferenceUid on attendee status for reschedule — good.Prevents hosts from leaking attendee seat refs in reschedule links.
apps/web/playwright/booking-seats.e2e.ts (2)
461-507: Test: host reschedule keeps booking uid — nice coverage.Asserts rescheduleUid equals booking.uid from /upcoming. Looks good.
509-583: Test: attendee-specific reschedule uses correct seatReferenceUid and pre-fills — solid.Deterministic ordering with
orderBy: { id: "asc" }avoids flakes.Consider adding a negative test for a host cancel path ensuring no
[object Object]leaks inseatReferenceUid(ties to fix in BookingListItem).apps/web/components/booking/BookingListItem.tsx (1)
255-260: Propagating isAttendee into action context — good.This enables correct gating in bookingActions.
E2E results are ready! |
emrysal
left a comment
There was a problem hiding this comment.
Let's get this merged, happy with this.
* fix: reschedule flow is broken for seated booking * Update BookingListItem.tsx * Update * tweak
What does this PR do?
Found that the reschedule flow for seated events is broken when trying to reschedule from the
/upcoming: Page not found when an attendee tries to reschedule and When the host tries to reschedule, the rescheduleUid is set to the first attendee’s seatRefUid