Skip to content

feat: allow rescheduling unconfirmed bookings without bypassing confirmation#28926

Open
SinghaAnirban005 wants to merge 4 commits into
calcom:mainfrom
SinghaAnirban005:feat/schedule
Open

feat: allow rescheduling unconfirmed bookings without bypassing confirmation#28926
SinghaAnirban005 wants to merge 4 commits into
calcom:mainfrom
SinghaAnirban005:feat/schedule

Conversation

@SinghaAnirban005
Copy link
Copy Markdown
Contributor

@SinghaAnirban005 SinghaAnirban005 commented Apr 18, 2026

What does this PR do?

Organizers of event types that require confirmation are currently blocked from rescheduling a PENDING booking. The restriction exists to prevent a naive reschedule from producing an ACCEPTED booking silently bypassing the confirmation workflow.

This PR ensures that the organizer can now reschedule a PENDING booking but the resulting booking inherits PENDING status. The confirmation requirement is fully preserved only the proposed time changes. Both the organizer and attendee receive a notification that the time has changed and that the booking still awaits confirmation.

Video Demo (if applicable):

Screencast.from.2026-04-19.02-29-35.webm

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs if this PR makes changes that would require a documentation change. N/A
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

@github-actions github-actions Bot added bookings area: bookings, availability, timezones, double booking Low priority Created by Linear-GitHub Sync ✨ feature New feature or request 🙋🏻‍♂️help wanted Help from the community is appreciated labels Apr 18, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Welcome to Cal.diy, @SinghaAnirban005! Thanks for opening this pull request.

A few things to keep in mind:

  • This is Cal.diy, not Cal.com. Cal.diy is a community-driven, fully open-source fork of Cal.com licensed under MIT. Your changes here will be part of Cal.diy — they will not be deployed to the Cal.com production app.
  • Please review our Contributing Guidelines if you haven't already.
  • Make sure your PR title follows the Conventional Commits format.

A maintainer will review your PR soon. Thanks for contributing!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

📝 Walkthrough

Walkthrough

The PR adds pending-reschedule handling across UI, booking, and email subsystems. UI edit-action logic and action-disable rules now account for an isPending state. Two new email templates for attendee and organizer pending reschedules were introduced and the email manager dispatches them when the original booking was pending. Booking email/SMS handler, RegularBookingService, and confirmation-flag computation were updated to propagate the original rescheduled booking and alter confirmation/email flows for PENDING originals. No public API signatures changed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: allowing rescheduling of unconfirmed (PENDING) bookings while preserving the confirmation workflow.
Description check ✅ Passed The description clearly explains the problem, solution, and impact, relating directly to the changeset implementing pending booking reschedule functionality.
Linked Issues check ✅ Passed The PR addresses issue #8885 by enabling organizers to reschedule PENDING bookings while preserving their PENDING status and confirmation requirements, fully meeting the stated requirements.
Out of Scope Changes check ✅ Passed All changes focus on pending booking reschedule functionality: email templates, booking actions, confirmation logic, and i18n strings are all directly related to the PR objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share
Review rate limit: 4/8 reviews remaining, refill in 23 minutes and 36 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/emails/email-manager.ts`:
- Around line 295-309: The pending-reschedule branch bypasses privacy and
recipient controls, logs to console, and sends raw calEvent to attendees while
skipping team-member host notifications; update the branch so it follows the
same reschedule email path as normal reschedules: remove console.log calls,
honor host/attendee email-disable settings before sending, use the scrubbed
payload (call hideCalendarNotes(calEvent, recipient) or the existing scrubber
used for regular reschedules) when constructing AttendeePendingRescheduledEmail
and OrganizerPendingRescheduledEmail, and trigger the same team-member host
notification logic used in the non-pending reschedule flow (reuse the existing
reschedule notification helper or functions) rather than sending directly from
this branch.

In `@packages/emails/templates/attendee-pending-rescheduled-email.ts`:
- Around line 17-28: Update the subject and text-body translation keys to use
pending-specific copy and add the corresponding strings to
packages/i18n/locales/en/common.json; specifically replace the subject call
using
this.attendee.language.translate("event_type_has_been_rescheduled_on_time_date",
{...}) with a new pending-specific key (e.g.
"event_type_pending_has_been_rescheduled_on_time_date") and replace the
getTextBody keys ("event_has_been_rescheduled",
"emailed_you_and_any_other_attendees") with pending variants (e.g.
"pending_event_has_been_rescheduled", "pending_booking_remains_unconfirmed") so
the attendee sees that the booking is still unconfirmed; make the same changes
for the other occurrence referenced (lines 32-37) and ensure the new keys are
added to packages/i18n/locales/en/common.json.

In `@packages/emails/templates/organizer-pending-rescheduled-email.ts`:
- Around line 19-32: The organizer email currently uses the standard rescheduled
subject/body; change it to a pending-specific variant by using a pending
translation key in this.calEvent.organizer.language.translate (e.g., replace
"event_type_has_been_rescheduled_on_time_date" with a pending key like
"event_type_pending_has_been_rescheduled_on_time_date"), and render
pending-specific HTML/text by either passing a pending flag into getHtml (e.g.,
{ ...this.calEvent, attendeeSeatId: undefined, pending: true }) or calling a
dedicated method (e.g., getPendingHtml) and using getTextBody with a pending key
(e.g., "event_pending_has_been_rescheduled"); add the new translation strings to
packages/i18n/locales/en/common.json matching the keys you choose.

In `@packages/features/bookings/lib/service/RegularBookingService.ts`:
- Around line 2197-2207: The pending-reschedule email payload sent in the
non-dry-run branch omits rescheduleReason, so
BookingEmailSmsHandler._handleRequested won't receive it; update the
emailsAndSmsHandler.send call (the branch guarded by isDryRun that sends action
BookingActionMap.requested) to include rescheduleReason inside the data object
alongside evt, eventType, attendees, additionalNotes, and
originalRescheduledBooking so the handler can use the user-provided reason.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 288105a3-3548-4da0-8deb-7e03b33309b5

📥 Commits

Reviewing files that changed from the base of the PR and between 9efd0e6 and 7d2a522.

📒 Files selected for processing (7)
  • apps/web/components/booking/actions/bookingActions.ts
  • packages/emails/email-manager.ts
  • packages/emails/templates/attendee-pending-rescheduled-email.ts
  • packages/emails/templates/organizer-pending-rescheduled-email.ts
  • packages/features/bookings/lib/BookingEmailSmsHandler.ts
  • packages/features/bookings/lib/handleNewBooking/getRequiresConfirmationFlags.ts
  • packages/features/bookings/lib/service/RegularBookingService.ts

Comment thread packages/emails/email-manager.ts Outdated
Comment thread packages/emails/templates/attendee-pending-rescheduled-email.ts Outdated
Comment thread packages/emails/templates/organizer-pending-rescheduled-email.ts Outdated
Comment thread packages/features/bookings/lib/service/RegularBookingService.ts
@github-actions
Copy link
Copy Markdown
Contributor

This PR has been marked as stale due to inactivity. If you're still working on it or need any help, please let us know or update the PR to keep it active.

@github-actions github-actions Bot added the Stale label Apr 27, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/components/booking/actions/bookingActions.ts (1)

109-113: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't key the organizer bypass to the single booking.user.

This file already handles round-robin and managed-child bookings, but isUserOrganizer only returns true when the logged-in user matches booking.user.id. That means other valid organizers on team bookings can still hit the minimum-notice block, so the new pending-reschedule flow won't work consistently there.

Suggested fix
-      const isUserOrganizer =
-     !isAttendee &&
-     booking.loggedInUser?.userId &&
-     booking.user?.id &&
-     booking.loggedInUser.userId === booking.user.id;
+      const isUserOrganizer = !isAttendee;
If there is a stricter permission flag available upstream, use that instead of comparing against the single assignee.

Also applies to: 244-253

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/components/booking/actions/bookingActions.ts` around lines 109 -
113, The current organizer-bypass logic wrongly uses booking.user (see
isUserOrganizer) which only matches the single assignee; update isUserOrganizer
to detect whether the current user is an organizer via the collective
organizer/hosts info or a proper permission flag instead of comparing to
booking.user.id. Specifically, replace the single-assignee check in
isUserOrganizer with a check against the event-level organizer/hosts list (e.g.,
hostGroups/members, booking.organizers or booking.organizerIds) or, if available
from upstream, use a stricter flag such as
booking.userIsOrganizer/booking.hasOrganizerPermission; apply the same change
where similar logic appears (the block around lines 244-253 using booking.user)
so all round-robin and managed-child booking flows honor real organizer
membership/permissions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@apps/web/components/booking/actions/bookingActions.ts`:
- Around line 109-113: The current organizer-bypass logic wrongly uses
booking.user (see isUserOrganizer) which only matches the single assignee;
update isUserOrganizer to detect whether the current user is an organizer via
the collective organizer/hosts info or a proper permission flag instead of
comparing to booking.user.id. Specifically, replace the single-assignee check in
isUserOrganizer with a check against the event-level organizer/hosts list (e.g.,
hostGroups/members, booking.organizers or booking.organizerIds) or, if available
from upstream, use a stricter flag such as
booking.userIsOrganizer/booking.hasOrganizerPermission; apply the same change
where similar logic appears (the block around lines 244-253 using booking.user)
so all round-robin and managed-child booking flows honor real organizer
membership/permissions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 99d09406-aa53-4f57-be28-11a258f888e5

📥 Commits

Reviewing files that changed from the base of the PR and between cb095f1 and 91f52fd.

📒 Files selected for processing (8)
  • apps/web/components/booking/actions/bookingActions.ts
  • packages/emails/email-manager.ts
  • packages/emails/templates/attendee-pending-rescheduled-email.ts
  • packages/emails/templates/organizer-pending-rescheduled-email.ts
  • packages/features/bookings/lib/BookingEmailSmsHandler.ts
  • packages/features/bookings/lib/handleNewBooking/getRequiresConfirmationFlags.ts
  • packages/features/bookings/lib/service/RegularBookingService.ts
  • packages/i18n/locales/en/common.json
✅ Files skipped from review due to trivial changes (3)
  • packages/emails/templates/attendee-pending-rescheduled-email.ts
  • packages/i18n/locales/en/common.json
  • packages/features/bookings/lib/handleNewBooking/getRequiresConfirmationFlags.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/emails/templates/organizer-pending-rescheduled-email.ts
  • packages/features/bookings/lib/BookingEmailSmsHandler.ts
  • packages/emails/email-manager.ts
  • packages/features/bookings/lib/service/RegularBookingService.ts

@github-actions github-actions Bot removed the Stale label May 4, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This PR has been marked as stale due to inactivity. If you're still working on it or need any help, please let us know or update the PR to keep it active.

@github-actions github-actions Bot added the Stale label May 11, 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 ✨ feature New feature or request 🙋🏻‍♂️help wanted Help from the community is appreciated Low priority Created by Linear-GitHub Sync size/L Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reschedule before confirming

1 participant