Skip to content

fix(reschedule): take into account guest's availability when host reschedules#28371

Closed
CharlesWong wants to merge 4 commits intocalcom:mainfrom
CharlesWong:fix/guest-availability-on-reschedule
Closed

fix(reschedule): take into account guest's availability when host reschedules#28371
CharlesWong wants to merge 4 commits intocalcom:mainfrom
CharlesWong:fix/guest-availability-on-reschedule

Conversation

@CharlesWong
Copy link
Copy Markdown

Problem

When a host reschedules a booking, Cal.com does not check the guest's availability, allowing the host to pick times when the guest is unavailable.

This is because the person who booked the meeting may or may not be a Cal.com user, so we previously didn't check their availability. However, since we have the attendee's email, we can look them up and — if they're a Cal.com user — only show slots that work for both parties.

Solution

When the host initiates a reschedule (rescheduleUid is present in the getSchedule call), this PR:

  1. Looks up the original booking by uid to retrieve attendee emails
  2. For each attendee, checks whether they are a Cal.com user via the Users table
  3. If the attendee is a Cal.com user and not already a host on the event, fetches their accepted bookings in the requested time range as busy times
  4. Filters available time slots to exclude those that conflict with the guest's bookings

If the attendee is not a Cal.com user, the existing behavior is preserved (no availability check is done).

The check is non-fatal: if the guest lookup fails for any reason (e.g. DB error), slot calculation proceeds normally so scheduling is not blocked.

Closes #16378

Changes

  • packages/trpc/server/routers/viewer/slots/util.ts: Added private method _getGuestBusyTimesForReschedule that looks up attendee availability, and a call to it in _getAvailableSlots when rescheduleUid is present
  • packages/trpc/server/routers/viewer/slots/getGuestBusyTimesForReschedule.test.ts: Unit tests covering all key scenarios

Test scenarios

  • Original booking not found → returns empty (no change to existing behavior)
  • Booking has no attendees → returns empty
  • Attendee is not a Cal.com user → returns empty (external guest, no check)
  • Attendee is already a host on the event → skipped (not double-counted)
  • Attendee is a Cal.com user → their bookings are returned as busy times and slots are filtered
  • The booking being rescheduled itself is excluded from guest busy times (so the current slot stays available)
  • Multiple Cal.com guests → all are checked and their busy times are aggregated

calcom#16378)

When a host reschedules a booking, Cal.com previously did not check the
guest's availability, allowing the host to pick times when the guest
(if a Cal.com user) had conflicting bookings.

This fix:
- Looks up attendee emails in the Users table during getSchedule calls
  that have a rescheduleUid present
- If an attendee is found to be a Cal.com user (and is not already a host
  on the event), fetches their existing bookings as busy times
- Filters available time slots to exclude those that conflict with the
  guest's bookings
- Preserves existing behavior when the guest is not a Cal.com user
- Non-fatal: if the guest lookup fails, slot calculation proceeds normally

Tests added for all key scenarios:
- Booking not found → no change
- No attendees → no change
- Attendee is not a Cal.com user → no change (external guest)
- Attendee IS a host → no double-counting
- Attendee is a Cal.com user → their bookings block slots
- The booking being rescheduled is excluded from guest busy times
- Multiple Cal.com guests → all are checked

Closes calcom#16378
@CharlesWong CharlesWong requested a review from a team as a code owner March 11, 2026 16:50
@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Mar 11, 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 Mar 11, 2026
@graphite-app
Copy link
Copy Markdown

graphite-app bot commented Mar 11, 2026

Graphite Automations

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

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

Copy link
Copy Markdown
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.

2 issues found across 2 files

Prompt for AI agents (unresolved 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/trpc/server/routers/viewer/slots/util.ts">

<violation number="1" location="packages/trpc/server/routers/viewer/slots/util.ts:275">
P1: Custom agent: **Avoid Logging Sensitive Information**

Remove attendee email addresses from debug logs; logging raw emails exposes PII and violates the sensitive-logging rule.</violation>

<violation number="2" location="packages/trpc/server/routers/viewer/slots/util.ts:279">
P2: New reschedule guest-availability logic introduces serial N+1 DB queries by fetching each attendee’s user and bookings inside a loop instead of batching.</violation>
</file>

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

…alcom#28371)

- Replace raw email addresses in debug logs with masked versions (e.g. j***@example.com)
  to comply with PII handling guidelines
- Add UserRepository.findManyByEmails() for batch user lookup
- Replace per-attendee findByEmail() calls in _getGuestBusyTimesForReschedule()
  with a single findManyByEmails() call, storing results in a Map for O(1) lookup
- Update unit tests to use the new findManyByEmails mock
Copy link
Copy Markdown
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 (changes from recent commits).

Prompt for AI agents (unresolved 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/users/repositories/UserRepository.ts">

<violation number="1" location="packages/features/users/repositories/UserRepository.ts:285">
P2: findManyByEmails only matches users.email, so attendees who booked with a verified secondary email won’t be recognized as Cal.com users and their busy times won’t be enforced during rescheduling.</violation>
</file>

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

coderabbitai review: findManyByEmails() only checks users.email (primary).
Attendees who booked using a verified secondary Cal.com email are not found,
so their busy times are silently skipped during host-reschedule availability
checks.

Add UserRepository.findManyByEmailsIncludingSecondary() that queries both
primary and verified secondary emails (secondaryEmail table, emailVerified
not null). Use it in _getGuestBusyTimesForReschedule to catch all Cal.com
users regardless of which email address they used when booking.
Copy link
Copy Markdown
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 2 files (changes from recent commits).

Prompt for AI agents (unresolved 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/trpc/server/routers/viewer/slots/util.ts">

<violation number="1" location="packages/trpc/server/routers/viewer/slots/util.ts:261">
P2: Secondary-email support is incomplete: attendees matched via secondary email are still keyed/queried by primary email, so alias attendees and alias-based attendee bookings can be missed.</violation>
</file>

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

@CharlesWong
Copy link
Copy Markdown
Author

Good catch from cubic (identified by cubic) — the guestUserByEmail map is keyed by u.email (primary email), so an attendee who booked with a secondary alias (e.g. alias@example.com) won't be found in the map even though findManyByEmailsIncludingSecondary returns their user record.

Fixing this by building the lookup map with every known email for each user (primary + verified secondaries) rather than only the primary. This way guestUserByEmail.get("alias@example.com") returns the correct user whose primary email is different.

…okup

findManyByEmailsIncludingSecondary now returns { users, byEmail } where
byEmail is keyed by every matched email (primary + verified secondary).
This fixes the case where an attendee booked with an alias/secondary
address: the guestUserByEmail map lookup now correctly finds their user
record even when the booking email differs from their primary Cal.com email.

Updated tests to use the new API and added a regression test for the
secondary-email alias case (identified by cubic review).
@CharlesWong
Copy link
Copy Markdown
Author

Fixed in edf27ff.

findManyByEmailsIncludingSecondary now returns { users, byEmail } instead of a plain array, where byEmail is a Map<email, user> keyed by every matched email — both the user's primary email and any secondary/alias email that was in the lookup list. The call site in _getGuestBusyTimesForReschedule now destructures { byEmail: guestUserByEmail } directly, so guestUserByEmail.get(aliasEmail) correctly returns the user even when they booked with a secondary address.

Also added a regression test (should match attendee by secondary/alias email) that exercises this exact path.

@CharlesWong
Copy link
Copy Markdown
Author

This also covers #25346: when a host reschedules, attendee emails are matched against Cal.com users and their availability/busy times are included in slot calculation if they have an account.

/claim #25346

Copy link
Copy Markdown
Member

@romitg2 romitg2 left a comment

Choose a reason for hiding this comment

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

Thank you for your work, we've decided to move with other PR.

@romitg2 romitg2 closed this Mar 12, 2026
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/XL $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