feat: add 5 new workflow triggers for booking events#23068
Conversation
- Add BOOKING_REJECTED, BOOKING_REQUESTED, BOOKING_PAYMENT_INITIATED, BOOKING_PAID, BOOKING_NO_SHOW_UPDATED to WorkflowTriggerEvents enum
- Update workflow constants to include new trigger options
- Implement workflow trigger logic for booking rejected and requested events
- Add translations for new workflow triggers following {enum}_trigger format
- Generate updated Prisma types for new schema changes
Co-Authored-By: amit@cal.com <samit91848@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
WalkthroughAdds five booking-related workflow triggers across the stack: Prisma enum + migration, workflow constants and immediate-trigger set, API DTOs/Swagger schemas, UI localization keys, WorkflowService scheduling helpers, and plumbing in booking/payment/no-show/reject/request flows to collect workflows and call WorkflowService scheduling methods. Tests, Playwright fixtures, and e2e tests were extended to assert the new trigger-driven workflows and email expectations. Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
✨ Finishing Touches
🧪 Generate 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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
- Add WorkflowTriggerEvents import to handleNewBooking.ts - Implement workflow trigger logic for BOOKING_REQUESTED in else block - Filter workflows by BOOKING_REQUESTED trigger and call scheduleWorkflowReminders - Use proper calendar event object construction without type casting - Add error handling for workflow reminder scheduling Co-Authored-By: amit@cal.com <samit91848@gmail.com>
…manager.devin.ai/proxy/github.com/calcom/cal.com into devin/1755107037-add-workflow-triggers
- Add proper database includes for user information in handleConfirmation.ts - Fix ExtendedCalendarEvent type structure with correct hosts mapping - Add missing properties to calendar event objects in handleMarkNoShow.ts - Ensure all workflow triggers follow proper type patterns Co-Authored-By: amit@cal.com <samit91848@gmail.com>
- Add workflow configurations for BOOKING_REQUESTED and BOOKING_PAYMENT_INITIATED in fresh-booking.test.ts - Add workflow configuration for BOOKING_REJECTED in confirm.handler.test.ts - Enable previously skipped confirm.handler.test.ts - Remove workflow test assertions temporarily until triggers are fully functional - Maintain webhook test coverage while adding workflow test infrastructure Co-Authored-By: amit@cal.com <samit91848@gmail.com>
….handler.test.ts - Import mockSuccessfulVideoMeetingCreation from bookingScenario utils - Add mock call to BOOKING_REJECTED workflow test case - Resolves ReferenceError that was causing unit test CI failure Co-Authored-By: amit@cal.com <samit91848@gmail.com>
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (08/18/25)1 reviewer was added to this PR based on Keith Williams's automation. |
There was a problem hiding this comment.
Actionable comments posted: 6
🔭 Outside diff range comments (3)
packages/trpc/server/routers/viewer/bookings/confirm.handler.ts (1)
406-409: Bug: message string always resolves to “confirmed”
const message =Booking ${confirmed}? "confirmed" : "rejected";always yields a truthy non-empty string. It should check the boolean directly.Apply this diff:
- const message = `Booking ${confirmed}` ? "confirmed" : "rejected"; + const message = confirmed ? "confirmed" : "rejected";packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts (2)
2253-2259: Align PENDING booking test description with actual workflow assertionThe test description states it “Should trigger BOOKING_REQUESTED workflow,” but the assertion calls
expectWorkflowToBeNotTriggered…. Please choose one of the following fixes for each occurrence (at lines 2253–2259, 2294–2300, and 2359–2361):• Update the description to reflect the current behavior (no workflow trigger):
- 3. Should trigger BOOKING_REQUESTED workflow + 3. Should not trigger BOOKING_REQUESTED workflow• Or update the assertion to expect a trigger if that’s the intended behavior:
- expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails }); + expectWorkflowToBeTriggered({ workflow: "BOOKING_REQUESTED", emailsToReceive: [organizer.email], emails });
2116-2122: Align test description with actual workflow behaviorThe test description lists “Should trigger BOOKING_REQUESTED workflow” (step 4), but the code asserts
expectWorkflowToBeNotTriggered. Please resolve this mismatch by choosing one of the following:Option A: If the workflow should fire immediately, update the assertion:
- expectWorkflowToBeNotTriggered({ emailsToReceive: [organizer.email], emails }); + expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });Option B: If the workflow is only scheduled (not dispatched immediately), update the test description to reflect that (e.g. “Should schedule BOOKING_REQUESTED workflow” or remove step 4).
Affected locations:
- packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts
• Lines 2116–2122
• Lines 2158–2165
• Lines 2230–2231
🧹 Nitpick comments (12)
packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.ts (1)
29-29: Test name mentions “workflow” but no workflow assertions are madeThe test only verifies the webhook was fired. Either add assertions for workflow scheduling or stick to a webhook-only description to avoid misleading expectations.
Apply one of the following diffs:
Option A — revert the title to match current assertions:
- test("Should trigger BOOKING_CANCELLED webhook and workflow", async () => { + test("Should trigger BOOKING_CANCELLED webhook", async () => {Option B — add a TODO to remind adding workflow assertions later:
- test("Should trigger BOOKING_CANCELLED webhook and workflow", async () => { + test("Should trigger BOOKING_CANCELLED webhook and workflow", async () => { + // TODO: Add assertions verifying workflow reminders are scheduled for EVENT_CANCELLEDpackages/features/handleMarkNoShow.ts (1)
170-174: Prefer undefined over null for optional valuesscheduleWorkflowReminders typically treats missing values as undefined. Passing null can force downstream null-checks.
Apply this diff:
- await scheduleWorkflowReminders({ - workflows: workflowsToTriggerForNoShow, - smsReminderNumber: null, - calendarEvent: calendarEvent as any, - }); + await scheduleWorkflowReminders({ + workflows: workflowsToTriggerForNoShow, + smsReminderNumber: undefined, + calendarEvent: calendarEvent as any, + });packages/features/bookings/lib/handleConfirmation.ts (1)
576-581: Pass user context to workflow fetch and avoid shadowingworkflows.
- Provide
booking.userIdtogetAllWorkflowsFromEventTypeso org scoping is computed correctly.- Avoid reusing the
workflowsname already declared earlier in this function; use a distinct name to reduce confusion.- const workflows = await getAllWorkflowsFromEventType(bookingEventType); - const workflowsToTriggerForPaid = workflows.filter( + const allWorkflows = await getAllWorkflowsFromEventType(bookingEventType, booking.userId); + const workflowsToTriggerForPaid = allWorkflows.filter( (workflow) => workflow.trigger === WorkflowTriggerEvents.BOOKING_PAID );packages/trpc/server/routers/viewer/bookings/confirm.handler.test.ts (2)
26-119: Scenario includes a workflow but the test doesn’t assert workflow behavior.The first test adds a BOOKING_REJECTED workflow to the scenario even though it validates a successful confirmation. It’s unnecessary noise and can slow tests.
- workflows: [ - { - userId: organizer.id, - trigger: "BOOKING_REJECTED", - action: "EMAIL_HOST", - template: "REMINDER", - activeOn: [1], - }, - ], + // No workflows needed for this test + workflows: [],
121-204: Assert that BOOKING_REJECTED workflow scheduling is invoked.You verify the booking status is REJECTED, but don’t assert workflow scheduling. Add a spy to ensure
scheduleWorkflowRemindersis called.@@ -import { describe, it, beforeEach, vi, expect } from "vitest"; +import { describe, it, beforeEach, vi, expect } from "vitest"; +import * as reminderScheduler from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler"; @@ it("should trigger BOOKING_REJECTED workflow when booking is rejected", async () => { + const scheduleSpy = vi + .spyOn(reminderScheduler, "scheduleWorkflowReminders") + // ensure it doesn't actually run anything heavy + .mockResolvedValue(undefined as unknown as Promise<unknown>); @@ const res = await confirmHandler({ ctx, input: { bookingId: 101, confirmed: false, reason: "Testing rejection" }, }); expect(res?.status).toBe(BookingStatus.REJECTED); + expect(scheduleSpy).toHaveBeenCalled(); });packages/features/bookings/lib/handleBookingRequested.ts (2)
102-121: Avoid unsafe type assertion forbookerUrl; provide a safe fallback.Replace
as stringwith a nullish-coalescing fallback to keep the payload consistent without assertions.- calendarEvent: { - ...evt, - bookerUrl: evt.bookerUrl as string, + calendarEvent: { + ...evt, + bookerUrl: evt.bookerUrl ?? "", eventType: { slug: evt.type, hosts: booking.eventType?.hosts, schedulingType: evt.schedulingType, }, },
115-118: Confirmevt.typeis the slug expected by workflows.If
CalendarEvent.typeis not guaranteed to be the event type slug, consider passing the canonical slug if available or updatingCalendarEventconstruction upstream to include it. Current usage suggests it is the slug, but worth a double-check for consistency.packages/trpc/server/routers/viewer/bookings/confirm.handler.ts (1)
74-114: Minimize selected Prisma fields on eventType.ownerYou’re selecting the full
ownerobject while only usingowner.hideBranding. Reduce the selection to what’s needed to avoid pulling unnecessary PII into a tRPC handler.Apply this diff:
- owner: true, + owner: { + select: { + hideBranding: true, + }, + },packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts (2)
2996-2999: Missing assertion for BOOKING_REQUESTED workflow after payment (requiresConfirmation: true)The description says it “Should trigger BOOKING_REQUESTED workflow” after successful payment, but there’s no assertion verifying that. Consider adding it to avoid regressions.
Apply this diff after the BOOKING_REQUESTED webhook assertion:
+ // Verify BOOKING_REQUESTED workflow triggered after payment for requiresConfirmation + expectWorkflowToBeTriggered({ emailsToReceive: [organizer.email], emails });Also applies to: 3038-3050, 3161-3169
10-46: Prefer enum constants over raw strings for workflow trigger values in testsUsing
WorkflowTriggerEventsminimizes typos and keeps tests aligned with enum changes.Apply this diff:
-import { - CreationSource, WatchlistSeverity, WatchlistType -} from "@calcom/prisma/enums"; +import { + CreationSource, + WatchlistSeverity, + WatchlistType, + WorkflowTriggerEvents, +} from "@calcom/prisma/enums";And replace trigger strings in workflows:
- trigger: "BOOKING_REQUESTED", + trigger: WorkflowTriggerEvents.BOOKING_REQUESTED,- trigger: "BOOKING_PAYMENT_INITIATED", + trigger: WorkflowTriggerEvents.BOOKING_PAYMENT_INITIATED,Also applies to: 2158-2165, 2870-2875, 3038-3050
packages/features/bookings/lib/handleNewBooking.ts (2)
2208-2245: BOOKING_PAYMENT_INITIATED scheduling: solid gating, add stronger error logging and dedupe helperThe try/catch and payload composition look correct. Two improvements:
- Log an actionable error message/stack (use getErrorFromUnknown for consistency elsewhere in this file).
- DRY: Extract a small helper to build the
calendarEventForWorkflowobject reused here and below.Apply this diff for logging:
- } catch (error) { - loggerWithEventDetails.error( - "Error while scheduling workflow reminders for booking payment initiated", - JSON.stringify({ error }) - ); - } + } catch (error) { + const err = getErrorFromUnknown(error); + loggerWithEventDetails.error( + "Error while scheduling workflow reminders for booking payment initiated", + err.message + ); + }Optional helper to eliminate duplication (outside this range, e.g., near other helpers):
function buildWorkflowCalendarEvent(evt: CalendarEvent, params: { rescheduleReason?: string | null; metadata?: unknown; eventType: { slug: string; schedulingType: SchedulingType | null; hosts: unknown }; bookerUrl: string; }) { const { rescheduleReason, metadata, eventType, bookerUrl } = params; return { ...evt, rescheduleReason, metadata, eventType, bookerUrl, }; }Then use:
const calendarEventForWorkflow = buildWorkflowCalendarEvent(evt, { rescheduleReason, metadata, eventType: { slug: eventType.slug, schedulingType: eventType.schedulingType, hosts: eventType.hosts }, bookerUrl, });
2346-2383: BOOKING_REQUESTED scheduling: same improvements as aboveGreat to see parity with the payment path. Suggest using
getErrorFromUnknownand the same helper for building the calendar event to keep logs clear and reduce duplication.Apply this diff for logging:
- } catch (error) { - loggerWithEventDetails.error( - "Error while scheduling workflow reminders for booking requested", - JSON.stringify({ error }) - ); - } + } catch (error) { + const err = getErrorFromUnknown(error); + loggerWithEventDetails.error( + "Error while scheduling workflow reminders for booking requested", + err.message + ); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (13)
apps/web/public/static/locales/en/common.json(1 hunks)packages/features/bookings/lib/handleBookingRequested.ts(3 hunks)packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.ts(1 hunks)packages/features/bookings/lib/handleConfirmation.ts(2 hunks)packages/features/bookings/lib/handleNewBooking.ts(3 hunks)packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts(8 hunks)packages/features/ee/workflows/lib/constants.ts(1 hunks)packages/features/handleMarkNoShow.ts(2 hunks)packages/lib/payment/getBooking.ts(1 hunks)packages/prisma/migrations/20250813182504_adding_booking_triggers_to_workflows/migration.sql(1 hunks)packages/prisma/schema.prisma(1 hunks)packages/trpc/server/routers/viewer/bookings/confirm.handler.test.ts(3 hunks)packages/trpc/server/routers/viewer/bookings/confirm.handler.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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:
packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.tspackages/features/ee/workflows/lib/constants.tspackages/trpc/server/routers/viewer/bookings/confirm.handler.test.tspackages/lib/payment/getBooking.tspackages/features/bookings/lib/handleBookingRequested.tspackages/features/handleMarkNoShow.tspackages/features/bookings/lib/handleConfirmation.tspackages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.tspackages/trpc/server/routers/viewer/bookings/confirm.handler.tspackages/features/bookings/lib/handleNewBooking.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:
packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.tspackages/features/ee/workflows/lib/constants.tspackages/trpc/server/routers/viewer/bookings/confirm.handler.test.tspackages/lib/payment/getBooking.tspackages/features/bookings/lib/handleBookingRequested.tspackages/features/handleMarkNoShow.tspackages/features/bookings/lib/handleConfirmation.tspackages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.tspackages/trpc/server/routers/viewer/bookings/confirm.handler.tspackages/features/bookings/lib/handleNewBooking.ts
🧬 Code Graph Analysis (6)
packages/trpc/server/routers/viewer/bookings/confirm.handler.test.ts (1)
apps/web/test/utils/bookingScenario/bookingScenario.ts (6)
getOrganizer(1496-1552)TestData(1215-1487)getDate(1069-1116)createBookingScenario(954-985)getScenarioData(1554-1640)mockSuccessfulVideoMeetingCreation(2022-2040)
packages/features/bookings/lib/handleBookingRequested.ts (2)
packages/trpc/server/routers/viewer/workflows/util.ts (1)
getAllWorkflowsFromEventType(814-859)packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
scheduleWorkflowReminders(379-382)
packages/features/handleMarkNoShow.ts (3)
packages/trpc/server/routers/viewer/workflows/util.ts (1)
getAllWorkflowsFromEventType(814-859)packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
scheduleWorkflowReminders(379-382)apps/api/v2/src/lib/logger.bridge.ts (1)
error(77-79)
packages/features/bookings/lib/handleConfirmation.ts (3)
packages/trpc/server/routers/viewer/workflows/util.ts (1)
getAllWorkflowsFromEventType(814-859)packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
scheduleWorkflowReminders(379-382)apps/api/v2/src/lib/logger.bridge.ts (1)
error(77-79)
packages/trpc/server/routers/viewer/bookings/confirm.handler.ts (2)
packages/trpc/server/routers/viewer/workflows/util.ts (1)
getAllWorkflowsFromEventType(814-859)packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
scheduleWorkflowReminders(379-382)
packages/features/bookings/lib/handleNewBooking.ts (2)
packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
scheduleWorkflowReminders(379-382)apps/api/v2/src/lib/logger.bridge.ts (1)
error(77-79)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: apply-labels-from-issue
🔇 Additional comments (14)
packages/lib/payment/getBooking.ts (1)
41-54: Good addition: host contact surfaces for workflowsSelecting host user email and their destinationCalendar.primaryEmail looks correct and follows “select-only” guidance. This will help populate host recipients for workflow reminders without over-fetching.
If this function is hot in your perf profile, consider confirming that we really need hosts for all call sites of getBooking; if not, we could gate this selection behind a flag to avoid unnecessary joins.
packages/prisma/schema.prisma (1)
1337-1341: Enum extensions align with PR objectivesNew workflow trigger values (BOOKING_REJECTED, BOOKING_REQUESTED, BOOKING_PAYMENT_INITIATED, BOOKING_PAID, BOOKING_NO_SHOW_UPDATED) look consistent and in parity with the rest of the implementation.
Confirm that all constants/UI locales/filters are wired to these enum values (constants.ts, locales, and filter UIs). The PR summary indicates they are, so this is a quick double-check.
packages/features/handleMarkNoShow.ts (3)
3-3: Scheduling import is correct and consistent with existing patternsImporting scheduleWorkflowReminders from the wrapped entry point keeps telemetry aligned with other call sites.
11-11: Enums import LGTMImporting WorkflowTriggerEvents is required for filtering; no concerns.
15-15: Correct utility selectionReusing getAllWorkflowsFromEventType keeps this flow consistent with other booking-trigger paths.
packages/prisma/migrations/20250813182504_adding_booking_triggers_to_workflows/migration.sql (1)
9-13: Multiple enum ADD VALUEs in one migration: check Postgres version in target envsPostgreSQL <= 11 can’t add several enum values safely in a single migration step. You’ve noted this in comments; ensure deployment targets are on a compatible version or be ready to split into separate migrations if needed.
If you need to support older PG versions, split this migration into five sequential ones or wrap each ADD VALUE in a DO $$ ... EXCEPTION WHEN duplicate_object THEN NULL; END $$ block (outside Prisma’s migration generator).
packages/features/bookings/lib/handleConfirmation.ts (2)
25-25: Import looks correct and scoped to new trigger usage.Bringing
WorkflowTriggerEventsinto this module is appropriate for the added BOOKING_PAID path.
600-607: LGTM: BOOKING_PAID workflow scheduling path is robust.
- Good construction of
calendarEventForWorkflowwith hosts and booker URL fallback.- Wrapped in try/catch so booking flow isn’t interrupted.
packages/features/ee/workflows/lib/constants.ts (1)
11-15: Trigger constants extension looks good.Adding the five booking-related triggers to
WORKFLOW_TRIGGER_EVENTSaligns with schema and UI changes and keeps the enum in sync.apps/web/public/static/locales/en/common.json (1)
1774-1779: Locale keys added for new triggers: good coverage and naming.Keys map cleanly to the new workflow triggers and match existing phrasing style in this file.
packages/features/bookings/lib/handleBookingRequested.ts (1)
29-41: Extending eventType typing with hosts is appropriate.The added optional
hostsshape matches what downstream workflow reminders expect.packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts (1)
2830-2834: Paid event tests: trigger sequencing looks correct (initiated → not triggered → paid → triggered)The additions for BOOKING_PAYMENT_INITIATED look consistent: you assert not triggered before payment, then triggered after payment. Good coverage.
Also applies to: 2870-2875, 2953-2956, 2977-2987
packages/features/bookings/lib/handleNewBooking.ts (2)
79-84: Import of WorkflowTriggerEvents looks goodPulling the enum into this module is appropriate for the new scheduling branches.
2446-2462: Double-scheduling risk: confirm generic scheduling does not re-fire trigger-specific workflowsYou now schedule specific workflows for BOOKING_PAYMENT_INITIATED/BOOKING_REQUESTED earlier, and then schedule all workflows here. If
scheduleWorkflowRemindersdoesn’t internally filter by trigger, these could be double-scheduled.If needed, I can help add a guard, e.g., pass an explicit
allowedTriggersset into this final call or filterworkflowshere to exclude the ones already scheduled for this request context.
| const workflows = await getAllWorkflowsFromEventType(booking.eventType); | ||
| const workflowsToTriggerForRejected = workflows.filter( | ||
| (workflow) => workflow.trigger === WorkflowTriggerEvents.BOOKING_REJECTED | ||
| ); | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Pass userId to workflow fetch to include user-scoped workflows
getAllWorkflowsFromEventType supports a userId to merge user/team/org workflows. Omitting it here may skip user-scoped workflows for the booking owner.
Apply this diff:
- const workflows = await getAllWorkflowsFromEventType(booking.eventType);
+ const workflows = await getAllWorkflowsFromEventType(booking.eventType, booking.userId);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const workflows = await getAllWorkflowsFromEventType(booking.eventType); | |
| const workflowsToTriggerForRejected = workflows.filter( | |
| (workflow) => workflow.trigger === WorkflowTriggerEvents.BOOKING_REJECTED | |
| ); | |
| const workflows = await getAllWorkflowsFromEventType( | |
| booking.eventType, | |
| booking.userId | |
| ); | |
| const workflowsToTriggerForRejected = workflows.filter( | |
| (workflow) => workflow.trigger === WorkflowTriggerEvents.BOOKING_REJECTED | |
| ); |
🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/bookings/confirm.handler.ts around lines
384-388, getAllWorkflowsFromEventType is being called with only
booking.eventType which omits user-scoped workflows; pass the booking owner's
user id as the second argument (e.g., booking.userId or booking.ownerId
depending on the booking shape) so the call becomes
getAllWorkflowsFromEventType(booking.eventType, <bookingUserId>), ensuring you
supply the correct property and handle its presence if optional.
packages/trpc/server/routers/viewer/bookings/confirm.handler.ts
Outdated
Show resolved
Hide resolved
…ing booking trigger events - Extract complex conditional logic into helper functions (isImmediateTrigger, isTimeBased, shouldProcessWorkflow) - Add missing workflow trigger events with immediate execution logic - Update test workflows to use different actions (EMAIL_ATTENDEE, SMS_ATTENDEE) for better differentiation - Fix translation function mock in confirm.handler.test.ts using mockNoTranslations utility - Maintain existing functionality while improving code maintainability Co-Authored-By: amit@cal.com <samit91848@gmail.com>
…manager.devin.ai/proxy/github.com/calcom/cal.com into devin/1755107037-add-workflow-triggers
| destinationCalendar?: | ||
| | { | ||
| primaryEmail: string | null; | ||
| } | ||
| | null | ||
| | undefined; |
There was a problem hiding this comment.
? and undefined — duplicate
| | undefined; | ||
| }; | ||
| }[] | ||
| | undefined; |
| calendarEvent: evtOfBooking, | ||
| isFirstRecurringEvent: isFirstBooking, | ||
| hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding, | ||
| isConfirmedByDefault: true, |
There was a problem hiding this comment.
just making sure if this condition holds for all cases here
There was a problem hiding this comment.
Yes. This flow is reached when user accepts a booking that requires confirmation
| hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding, | ||
| isConfirmedByDefault: true, | ||
| isNormalBookingOrFirstRecurringSlot: isFirstBooking, | ||
| isRescheduleEvent: false, |
There was a problem hiding this comment.
Yes. This flow is reached when user accepts a booking that requires confirmation. No flow with reschedule reach here at all
| } catch (error) { | ||
| loggerWithEventDetails.error( | ||
| "Error while scheduling workflow reminders for booking payment initiated", | ||
| JSON.stringify({ error }) |
There was a problem hiding this comment.
any particular reason for using JSON function instead of safeStringify here?
There was a problem hiding this comment.
Not sure why but I just followed what was done previously
cal.com/packages/features/bookings/lib/handleNewBooking.ts
Lines 2409 to 2424 in b052c2e
| destinationCalendar: booking.destinationCalendar | ||
| ? [booking.destinationCalendar] | ||
| : booking.user?.destinationCalendar | ||
| ? [booking.user?.destinationCalendar] | ||
| : [], |
There was a problem hiding this comment.
let's compute this logic above calendarEvent declaration for better readability
| ? { | ||
| name: booking.eventType.team.name, | ||
| id: booking.eventType.team.id, | ||
| members: [], |
There was a problem hiding this comment.
Yes. This is how it is done in other places as well
cal.com/packages/trpc/server/routers/viewer/bookings/confirm.handler.ts
Lines 235 to 241 in b052c2e
| ...(parsedMetadata.success && parsedMetadata.data?.videoCallUrl | ||
| ? { metadata: { videoCallUrl: parsedMetadata.data.videoCallUrl } } | ||
| : {}), |
There was a problem hiding this comment.
same here, let's compute this above
| hideOrganizerEmail: booking.eventType?.hideOrganizerEmail, | ||
| eventTypeId: booking.eventType?.id, | ||
| customReplyToEmail: booking.eventType?.customReplyToEmail, | ||
| team: !!booking.eventType?.team |
| (isNormalBookingOrFirstRecurringSlot | ||
| ? workflow.trigger === WorkflowTriggerEvents.NEW_EVENT | ||
| : false) |
There was a problem hiding this comment.
isNormalBookingOrFirstRecurringSlot && workflow.trigger === WorkflowTriggerEvents.NEW_EVENT
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleSeats/handleSeats.ts (1)
58-69: Replace Prisma include with select (repo guideline: never use include).Use select to fetch only required fields. Also, you access attendee.email later (Line 84), so explicitly select it.
Apply:
select: { uid: true, id: true, - attendees: { include: { bookingSeat: true } }, + attendees: { select: { email: true, bookingSeat: true } }, userId: true, references: true, startTime: true, - user: true, status: true, smsReminderNumber: true, endTime: true, },Optional: drop user if unused here to reduce payload.
🧹 Nitpick comments (3)
packages/features/bookings/lib/handleConfirmation.ts (1)
365-373: Pass seatReferenceUid to keep seat-scoped workflows accurate.If ScheduleWorkflowRemindersArgs supports seatReferenceUid, include it so reminders bind to the attendee seat (multi-seat events).
Apply this diff:
await WorkflowService.scheduleWorkflowsForNewBooking({ workflows, smsReminderNumber: updatedBookings[index].smsReminderNumber, calendarEvent: evtOfBooking, hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding, + seatReferenceUid: evt.attendeeSeatId, isConfirmedByDefault: true, isNormalBookingOrFirstRecurringSlot: isFirstBooking, isRescheduleEvent: false, });If the type does not include seatReferenceUid, ignore this suggestion.
packages/features/bookings/lib/handleSeats/handleSeats.ts (2)
135-136: Improve error logging context without stringifying the Error object.Stringifying may drop stack and non-enumerables. Log the error object as metadata.
- loggerWithEventDetails.error("Error while scheduling workflow reminders", JSON.stringify({ error })); + loggerWithEventDetails.error("Error while scheduling workflow reminders", { error });
164-165: ConverthandleSeatsto a named export
Replace the default export with a named export to improve tree-shaking:-export default handleSeats; +export { handleSeats };Update import sites accordingly:
- In packages/features/bookings/lib/handleNewBooking.ts (line 136), change
import handleSeats from "./handleSeats/handleSeats";→
import { handleSeats } from "./handleSeats/handleSeats";- In packages/features/bookings/lib/handleSeats/test/handleSeats.test.ts, update the spy:
vi.spyOn(handleSeatsModule, "default")→vi.spyOn(handleSeatsModule, "handleSeats")
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
apps/web/public/static/locales/en/common.json(1 hunks)packages/features/bookings/lib/handleBookingRequested.ts(3 hunks)packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.ts(5 hunks)packages/features/bookings/lib/handleConfirmation.ts(3 hunks)packages/features/bookings/lib/handleNewBooking.ts(4 hunks)packages/features/bookings/lib/handleSeats/handleSeats.ts(3 hunks)packages/features/ee/workflows/lib/reminders/emailReminderManager.ts(2 hunks)packages/features/handleMarkNoShow.ts(2 hunks)packages/lib/server/service/workflows.ts(2 hunks)packages/prisma/schema.prisma(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/prisma/schema.prisma
- apps/web/public/static/locales/en/common.json
- packages/features/ee/workflows/lib/reminders/emailReminderManager.ts
- packages/features/handleMarkNoShow.ts
- packages/features/bookings/lib/handleCancelBooking/test/handleCancelBooking.test.ts
- packages/features/bookings/lib/handleBookingRequested.ts
- packages/features/bookings/lib/handleNewBooking.ts
- packages/lib/server/service/workflows.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.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:
packages/features/bookings/lib/handleSeats/handleSeats.tspackages/features/bookings/lib/handleConfirmation.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:
packages/features/bookings/lib/handleSeats/handleSeats.tspackages/features/bookings/lib/handleConfirmation.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:
packages/features/bookings/lib/handleSeats/handleSeats.tspackages/features/bookings/lib/handleConfirmation.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.192Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.
📚 Learning: 2025-08-19T08:45:41.834Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts:167-193
Timestamp: 2025-08-19T08:45:41.834Z
Learning: In calcom/cal.com AI phone call scheduling (aiPhoneCallManager.ts), workflow reminder records are intentionally kept in the database even when task scheduling fails, as they provide valuable debugging information for troubleshooting scheduling issues, per maintainer Udit-takkar in PR #22995.
Applied to files:
packages/features/bookings/lib/handleConfirmation.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.
Applied to files:
packages/features/bookings/lib/handleConfirmation.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.
Applied to files:
packages/features/bookings/lib/handleConfirmation.ts
📚 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:
packages/features/bookings/lib/handleConfirmation.ts
📚 Learning: 2025-07-28T11:50:23.946Z
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : For Prisma queries, only select data you need; never use `include`, always use `select`
Applied to files:
packages/features/bookings/lib/handleConfirmation.ts
📚 Learning: 2025-08-22T16:38:00.225Z
Learnt from: bandhan-majumder
PR: calcom/cal.com#23192
File: packages/lib/server/service/InsightsBookingBaseService.ts:814-816
Timestamp: 2025-08-22T16:38:00.225Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), when filtering for "accepted" bookings in getMembersStatsWithCount(), using `endTime <= now()` in the SQL condition should be avoided as it conflicts with existing date filtering logic. The components already handle completion filtering by setting `endDate: currentTime` in their query parameters, making additional SQL-level endTime filtering unnecessary and potentially problematic.
Applied to files:
packages/features/bookings/lib/handleConfirmation.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.
Applied to files:
packages/features/bookings/lib/handleConfirmation.ts
🧬 Code graph analysis (2)
packages/features/bookings/lib/handleSeats/handleSeats.ts (1)
packages/lib/server/service/workflows.ts (1)
WorkflowService(10-131)
packages/features/bookings/lib/handleConfirmation.ts (1)
packages/lib/server/service/workflows.ts (1)
WorkflowService(10-131)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (6)
packages/features/bookings/lib/handleConfirmation.ts (3)
22-22: Good move: centralize workflow scheduling via WorkflowService.This aligns with the earlier suggestion to keep trigger filtering in the service layer.
25-25: Correct enum import for new triggers.Ensures typed usage of BOOKING_* triggers across the file.
559-585: Guard against empty updatedBookings and align event fields
- Return early when
updatedBookingsis empty to avoid a crash.- Use shorthand for
bookerUrl.- Copy
startTime,endTime, anduidfromupdatedBookings[0].- Use
updatedBookings[0].smsReminderNumberinstead of the old value.- Verify that
getAllWorkflowsFromEventTypereturns workflows forWorkflowTriggerEvents.BOOKING_PAIDon this code path.packages/features/bookings/lib/handleSeats/handleSeats.ts (3)
7-7: Switch to WorkflowService import — LGTM.Importing and centralizing scheduling via WorkflowService is aligned with the new trigger-based flow.
111-113: Service-based scheduling call — LGTM.Passing workflows explicitly and delegating trigger filtering to WorkflowService is correct.
133-133: Potential duplicate NEW_EVENT triggers for seat sign-ups.Hard-coding
isNormalBookingOrFirstRecurringSlot: truemay cause NEW_EVENT workflows to fire for each added seat, not just for the initial booking.Consider:
- isNormalBookingOrFirstRecurringSlot: true, + isNormalBookingOrFirstRecurringSlot: false,Or switch to
WorkflowService.scheduleWorkflowsFilteredByTriggerEventto limit to BEFORE_EVENT/AFTER_EVENT in this path if that matches product intent. Please confirm expected behavior for seat additions.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleSeats/handleSeats.ts (1)
58-66: Prisma: replace nested include with select (guideline).Avoid include; select only needed fields for attendees.
select: { uid: true, id: true, - attendees: { include: { bookingSeat: true } }, + attendees: { select: { email: true, bookingSeat: true } }, userId: true, references: true, startTime: true, user: true, status: true, smsReminderNumber: true, endTime: true, },
♻️ Duplicate comments (1)
packages/features/bookings/lib/handleSeats/handleSeats.ts (1)
130-133: Fix confirmed-by-default flag looks correct.The previous || true bug is resolved; this enables BOOKING_REQUESTED triggers when confirmation is required.
🧹 Nitpick comments (4)
packages/features/bookings/lib/handleSeats/handleSeats.ts (4)
82-89: Guard against invitee[0] undefined and simplify lookup.Prevents potential runtime error when invitee is empty; uses some() for clarity.
- if ( - seatedBooking.attendees.find((attendee) => { - return attendee.email === invitee[0].email; - }) && - dayjs.utc(seatedBooking.startTime).format() === evt.startTime - ) { + const inviteeEmail = invitee?.[0]?.email; + if ( + inviteeEmail && + seatedBooking.attendees.some((attendee) => attendee.email === inviteeEmail) && + dayjs.utc(seatedBooking.startTime).format() === evt.startTime + ) { throw new HttpError({ statusCode: 409, message: ErrorCode.AlreadySignedUpForBooking }); }
110-136: Make scheduling non-blocking and keep error logging.PR summary states scheduling shouldn’t block booking flow; switch to fire-and-forget with .catch.
- try { - await WorkflowService.scheduleWorkflowsForNewBooking({ - workflows: workflows, - smsReminderNumber: smsReminderNumber || null, - calendarEvent: { - ...evt, - uid: seatedBooking.uid, - rescheduleReason, - ...{ - metadata, - eventType: { - slug: eventType.slug, - schedulingType: eventType.schedulingType, - hosts: eventType.hosts, - }, - }, - }, - emailAttendeeSendToOverride: bookerEmail, - seatReferenceUid: resultBooking?.seatReferenceUid, - isDryRun, - isConfirmedByDefault: !evt.requiresConfirmation, - isRescheduleEvent: !!rescheduleUid, - isNormalBookingOrFirstRecurringSlot: true, - }); - } catch (error) { - loggerWithEventDetails.error("Error while scheduling workflow reminders", JSON.stringify({ error })); - } + void WorkflowService.scheduleWorkflowsForNewBooking({ + workflows, + smsReminderNumber: smsReminderNumber || null, + calendarEvent: { + ...evt, + uid: seatedBooking.uid, + rescheduleReason, + ...{ + metadata, + eventType: { + slug: eventType.slug, + schedulingType: eventType.schedulingType, + hosts: eventType.hosts, + }, + }, + }, + emailAttendeeSendToOverride: bookerEmail, + seatReferenceUid: resultBooking?.seatReferenceUid, + isDryRun, + isConfirmedByDefault: !evt.requiresConfirmation, + isRescheduleEvent: !!rescheduleUid, + isNormalBookingOrFirstRecurringSlot: true, + }).catch((error) => { + loggerWithEventDetails.error({ err: error }, "Error while scheduling workflow reminders"); + });
111-114: Nit: use property shorthand.Minor cleanup for workflows.
- workflows: workflows, + workflows,
164-164: Prefer named export over default (repo guideline).Switching to named export improves tree-shaking and refactors; consider as a follow-up to avoid churn.
-export default handleSeats; +export { handleSeats };
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
packages/features/bookings/lib/handleSeats/handleSeats.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.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:
packages/features/bookings/lib/handleSeats/handleSeats.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:
packages/features/bookings/lib/handleSeats/handleSeats.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:
packages/features/bookings/lib/handleSeats/handleSeats.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: anglerfishlyy
PR: calcom/cal.com#0
File: :0-0
Timestamp: 2025-08-27T16:39:38.192Z
Learning: anglerfishlyy successfully implemented CAL-3076 email invitation feature for Cal.com team event-types in PR #23312. The feature allows inviting people via email directly from assignment flow, with automatic team invitation if email doesn't belong to existing team member. Implementation includes Host type modifications (userId?: number, email?: string, isPending?: boolean), CheckedTeamSelect component updates with CreatableSelect, TRPC schema validation with zod email validation, and integration with existing teamInvite system.
🧬 Code graph analysis (1)
packages/features/bookings/lib/handleSeats/handleSeats.ts (1)
packages/lib/server/service/workflows.ts (1)
WorkflowService(10-131)
🔇 Additional comments (1)
packages/features/bookings/lib/handleSeats/handleSeats.ts (1)
7-7: Good move: centralize scheduling via WorkflowService.Importing and using WorkflowService improves cohesion and reduces duplication.
fixes #23051
Refactor _scheduleWorkflowReminders and add new booking workflow triggers
Summary
This PR addresses three main objectives:
_scheduleWorkflowRemindersfunction for better readability and maintainability by extracting complex conditional logic into helper functionsBOOKING_REQUESTED,BOOKING_REJECTED,BOOKING_PAYMENT_INITIATED,BOOKING_PAID,BOOKING_NO_SHOW_UPDATED) with immediate execution logicKey Changes:
{trigger}_triggerformat_scheduleWorkflowRemindersinto three helper functions:scheduleWorkflowReminderscalls in booking handlers where new triggers should fireEMAIL_ATTENDEE,SMS_ATTENDEE) for better differentiation and fixed translation mocking issuesReview & Testing Checklist for Human
NEW_EVENT,RESCHEDULE_EVENT,BEFORE_EVENT,AFTER_EVENT) still work exactly as before, especially edge cases with reschedule and recurring eventsRecommended Test Plan: Create a test event type with workflows configured for each new trigger, then go through the complete booking lifecycle (request → payment → confirmation/rejection → no-show) to verify workflows fire at each stage.
Diagram
%%{ init : { "theme" : "default" }}%% graph TD Schema["packages/prisma/schema.prisma<br/>WorkflowTriggerEvents enum"]:::major-edit Constants["packages/features/ee/workflows/lib/constants.ts<br/>WORKFLOW_TRIGGER_EVENTS"]:::major-edit Translations["apps/web/public/static/locales/en/common.json<br/>New trigger translations"]:::minor-edit ReminderScheduler["packages/features/ee/workflows/lib/reminders/reminderScheduler.ts<br/>_scheduleWorkflowReminders function"]:::major-edit HandleNewBooking["packages/features/bookings/lib/handleNewBooking.ts<br/>BOOKING_REQUESTED, BOOKING_PAYMENT_INITIATED"]:::minor-edit HandleConfirmation["packages/features/bookings/lib/handleConfirmation.ts<br/>BOOKING_PAID"]:::minor-edit ConfirmHandler["packages/trpc/server/routers/viewer/bookings/confirm.handler.ts<br/>BOOKING_REJECTED"]:::minor-edit HandleNoShow["packages/features/handleMarkNoShow.ts<br/>BOOKING_NO_SHOW_UPDATED"]:::minor-edit TestFiles["Test files<br/>fresh-booking.test.ts, confirm.handler.test.ts"]:::minor-edit Schema --> Constants Schema --> ReminderScheduler Constants --> ReminderScheduler HandleNewBooking --> ReminderScheduler HandleConfirmation --> ReminderScheduler ConfirmHandler --> ReminderScheduler HandleNoShow --> ReminderScheduler ReminderScheduler --> TestFiles subgraph Legend L1[Major Edit]:::major-edit L2[Minor Edit]:::minor-edit L3[Context/No Edit]:::context end classDef major-edit fill:#90EE90 classDef minor-edit fill:#87CEEB classDef context fill:#FFFFFFNotes
as anytype casting as requested by the usermockNoTranslations()utility to fix translation function mocking in testsNEW_EVENT,EVENT_CANCELLED,RESCHEDULE_EVENT)Session Details: Requested by Amit (@Amit91848) from Cal.com
Devin Session: https://app.devin.ai/sessions/92648f09e04c4ebaa979267d8cb005ac