Skip to content

feat(reschedule): check guest availability when host reschedules#28164

Open
ripgtxgt wants to merge 2 commits intocalcom:mainfrom
ripgtxgt:feat/guest-availability-reschedule-16378
Open

feat(reschedule): check guest availability when host reschedules#28164
ripgtxgt wants to merge 2 commits intocalcom:mainfrom
ripgtxgt:feat/guest-availability-reschedule-16378

Conversation

@ripgtxgt
Copy link

Fixes #16378

Summary

When a host reschedules a booking, the available slot picker now filters out time slots that conflict with the guests' (non-host attendees') existing accepted bookings — preventing the host from accidentally double-booking a guest.

How it works

  1. When rescheduleUid is present in getSchedule, look up the original booking's attendees via BookingRepository.
  2. Filter out host emails (booking's user + event-type hosts) to isolate guest-only emails.
  3. Query their accepted bookings in the slot search window, excluding the booking being rescheduled itself.
  4. Pass these as guestBusyTimes through initialData into getUserAvailability, where they are merged into detailedBusyTimes — the same busy-time list that drives slot availability.

Changes (3 files, minimal diff)

File Change
packages/features/bookings/repositories/BookingRepository.ts Add getAcceptedBookingsByAttendeeEmails() — queries bookings where any attendee is in a given email list
packages/trpc/server/routers/viewer/slots/util.ts In calculateHostsAndAvailabilities(): fetch guest busy times when rescheduleUid is present; pass via initialData.guestBusyTimes
packages/features/availability/lib/getUserAvailability.ts Add guestBusyTimes? to GetUserAvailabilityInitialData; spread into detailedBusyTimes

Design decisions

  • Minimal surface area: the new getAcceptedBookingsByAttendeeEmails query is a single prisma.booking.findMany with an attendee email filter. No new services, no new DI tokens.
  • Host-email exclusion: hosts are excluded from the guest list so a host's own calendar isn't counted twice.
  • Excludes the booking being rescheduled: the excludedUid parameter prevents the original booking's time from being treated as a conflict.
  • No schema changes: guestBusyTimes is an optional field on GetUserAvailabilityInitialData, fully backwards-compatible.

Test plan

  • Create a booking with at least one guest (attendee not in the org/team)
  • Have the guest accept a separate booking that overlaps with a slot in the reschedule picker
  • As the host, open the reschedule flow — the conflicting slot should no longer appear as available
  • Slots that do not conflict with any guest booking should remain available
  • Rescheduling a booking with no external guests should behave identically to before

When a host reschedules a booking, the slot picker now filters out time
slots that conflict with the guests' (attendees') existing accepted
bookings — preventing double-booking guests.

Changes:
- BookingRepository: add getAcceptedBookingsByAttendeeEmails() to query
  bookings where any attendee email appears in a given list, within a
  date range, excluding the booking being rescheduled
- AvailableSlotsService.calculateHostsAndAvailabilities(): when
  rescheduleUid is present, look up the original booking's attendees,
  filter out host emails to get guest-only emails, fetch their accepted
  bookings in the slot search window, and pass them as guestBusyTimes
- GetUserAvailabilityInitialData: add optional guestBusyTimes field
- getUserAvailability(): spread guestBusyTimes into detailedBusyTimes so
  guest conflicts are treated as busy time during availability calculation

Fixes calcom#16378
@ripgtxgt ripgtxgt requested a review from a team as a code owner February 25, 2026 10:31
@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Feb 25, 2026
@github-actions github-actions bot added $200 bookings area: bookings, availability, timezones, double booking Medium priority Created by Linear-GitHub Sync ✨ feature New feature or request 💎 Bounty A bounty on Algora.io 🧹 Improvements Improvements to existing features. Mostly UX/UI labels Feb 25, 2026
@graphite-app
Copy link

graphite-app bot commented Feb 25, 2026

Graphite Automations

"Send notification to Community team when bounty PR opened" took an action on this PR • (02/25/26)

2 teammates were notified to this PR based on Keith Williams's automation.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/features/bookings/repositories/BookingRepository.ts">

<violation number="1" location="packages/features/bookings/repositories/BookingRepository.ts:2196">
P2: Guest conflict query only includes bookings fully contained in the window; overlapping bookings that start before or end after are excluded, so conflicts can be missed during reschedule.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Kitress3 pushed a commit to Kitress3/cal.com that referenced this pull request Feb 27, 2026
- Add getAcceptedBookingsByAttendeeEmails() to BookingRepository
- Fetch guest bookings and filter out host emails in slots/util.ts
- Add guestBusyTimes to GetUserAvailabilityInitialData
- Merge guest busy times into detailedBusyTimes

Fixes calcom#16378
/claim calcom#28164
The previous condition (startTime >= windowStart AND endTime <= windowEnd)
only matched bookings fully contained within the search window.  Bookings
that straddle a boundary — e.g. a guest booking that starts before the
rescheduling window begins but ends inside it — were silently dropped,
leaving a gap in conflict detection.

Fix: switch to standard interval-overlap semantics:
  startTime < windowEnd AND endTime > windowStart

This correctly captures every booking whose time range intersects the
window, regardless of whether it extends beyond either edge.

Addresses P2 feedback from cubic review of PR calcom#28164.
@ripgtxgt
Copy link
Author

ripgtxgt commented Mar 1, 2026

@cubic-dev-ai P2 fix applied in commit 36ebaa9470.

The getAcceptedBookingsByAttendeeEmails() query now uses overlap semantics instead of containment:

// Before (containment — missed boundary-straddling bookings):
startTime: { gte: startDate },
endTime:   { lte: endDate },

// After (overlap — catches any booking intersecting the window):
startTime: { lt: endDate },
endTime:   { gt: startDate },

This ensures a guest booking that starts before the reschedule search window (or ends after it) is still treated as a conflict. Ready for re-review.

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Mar 1, 2026

@cubic-dev-ai P2 fix applied in commit 36ebaa9470.

The getAcceptedBookingsByAttendeeEmails() query now uses overlap semantics instead of containment:

...

@ripgtxgt I have started the AI code review. It will take a few minutes to complete.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

Iceshen87 pushed a commit to Iceshen87/cal.com that referenced this pull request Mar 4, 2026
Fixes calcom#28164

When a host reschedules a booking, the available slot picker now filters out time slots that conflict with the guests' (non-host attendees') existing accepted bookings — preventing the host from accidentally double-booking a guest.

How it works:
1. When rescheduleUid is present in getSchedule, look up the original booking's attendees via BookingRepository
2. Filter out host emails (booking's user + event-type hosts) to isolate guest-only emails
3. Query their accepted bookings in the slot search window, excluding the booking being rescheduled itself
4. Pass these as guestBusyTimes through initialData into getUserAvailability, where they are merged into detailedBusyTimes

Changes:
- packages/features/bookings/repositories/BookingRepository.ts: Add getAcceptedBookingsByAttendeeEmails() method
- packages/trpc/server/routers/viewer/slots/util.ts: Fetch guest busy times when rescheduleUid is present
- packages/features/availability/lib/getUserAvailability.ts: Add guestBusyTimes to GetUserAvailabilityInitialData and merge into detailedBusyTimes

Design decisions:
- Minimal surface area: single prisma.booking.findMany query with attendee email filter
- Host-email exclusion: hosts are excluded from the guest list
- Excludes the booking being rescheduled: excludedUid parameter prevents conflicts
- No schema changes: guestBusyTimes is optional, fully backwards-compatible

Testing:
- Syntax validated: ✅ All TypeScript files pass syntax check
- Follows existing patterns for busy time handling

/claim calcom#28164
@Iceshen87
Copy link

✅ PR submitted: #28256

I have implemented the guest availability check for rescheduling scenarios.

Implementation:

When a host reschedules a booking, the system now:

  1. Fetches the original booking's attendees
  2. Filters out host emails to get guest-only emails
  3. Queries their accepted bookings in the search window
  4. Merges guest busy times into the availability calculation

Changes:

  • BookingRepository.ts: Added getAcceptedBookingsByAttendeeEmails() method
  • slots/util.ts: Fetch guest busy times when rescheduleUid is present
  • getUserAvailability.ts: Added guestBusyTimes field and merged into detailedBusyTimes

Testing:

  • ✅ All TypeScript files pass syntax validation
  • ✅ Follows existing busy time handling patterns
  • ✅ Backwards compatible (no schema changes)

Ready for review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bookings area: bookings, availability, timezones, double booking 💎 Bounty A bounty on Algora.io community Created by Linear-GitHub Sync ✨ feature New feature or request 🧹 Improvements Improvements to existing features. Mostly UX/UI Medium priority Created by Linear-GitHub Sync size/M $200

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CAL-4531] Take into account guest's availability when rescheduling

2 participants