cc
3862
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5242e419d9 |
feat: Calendar Sync (#24124)
* feat: calendar cache and sync - wip * Add env.example * refactor on CalendarCacheEventService * remove test console.log * Fix type checks errors * chore: remove pt comment * add route.ts * chore: fix tests * Improve cache impl * chore: update recurring event id * chore: small improvements * calendar cache improvements * Fix remove dynamic imports * Add cleanup stale cache * Fix tests * add event update * type fixes * feat: add comprehensive tests for new calendar subscription API routes - Add tests for /api/cron/calendar-subscriptions-cleanup route (9 tests) - Add tests for /api/cron/calendar-subscriptions route (10 tests) - Add tests for /api/webhooks/calendar-subscription/[provider] route (11 tests) - Add missing feature flags for calendar-subscription-cache and calendar-subscription-sync - All 30 tests pass with comprehensive coverage of authentication, feature flags, error handling, and service instantiation Tests cover: - Authentication scenarios (API key validation, Bearer tokens, query parameters) - Feature flag combinations (cache/sync enabled/disabled states) - Success and error handling (including non-Error exceptions) - Service instantiation with proper dependency injection - Provider validation for webhook endpoints Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * feat: add comprehensive tests for calendar subscription services, repositories, and adapters - Add unit tests for CalendarSubscriptionService with subscription, webhook, and event processing - Add unit tests for CalendarCacheEventService with cache operations and cleanup - Add unit tests for CalendarSyncService with Cal.com event filtering and booking operations - Add unit tests for CalendarCacheEventRepository with CRUD operations - Add unit tests for SelectedCalendarRepository with calendar selection management - Add unit tests for GoogleCalendarSubscriptionAdapter with subscription and event fetching - Add unit tests for Office365CalendarSubscriptionAdapter with placeholder implementation - Add unit tests for AdaptersFactory with provider management and adapter creation - Fix lint issues by removing explicit 'any' type casting and unused variables - All tests follow Cal.com conventions using Vitest framework with proper mocking Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix: improve calendar-subscriptions-cleanup test performance by adding missing mocks - Add comprehensive mocks for defaultResponderForAppDir, logger, performance monitoring, and Sentry - Fix slow test execution (933ms -> <100ms) caused by missing dependency mocks - Ensure consistent test performance across different environments Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * Fix tests * Fix tests * type fix * Fix coderabbit comments * Fix types * Fix test * Update apps/web/app/api/cron/calendar-subscriptions/route.ts Co-authored-by: Alex van Andel <me@alexvanandel.com> * Fixes by first review * feat: add database migrations for calendar cache and sync fields - Add CalendarCacheEventStatus enum with confirmed, tentative, cancelled values - Add new fields to SelectedCalendar: channelId, channelKind, channelResourceId, channelResourceUri, channelExpiration, syncSubscribedAt, syncToken, syncedAt, syncErrorAt, syncErrorCount - Create CalendarCacheEvent table with foreign key to SelectedCalendar - Add necessary indexes and constraints for performance and data integrity Fixes database schema issues causing e2e test failures with 'column does not exist' errors. Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * only google-calendar for now * docs: add Calendar Cache and Sync feature documentation - Add comprehensive feature overview and motivation - Document feature flags with SQL examples - Include SQL examples for enabling features for users and teams - Reference technical documentation files Addresses PR #23876 documentation requirements Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * docs: update calendar subscription README with comprehensive documentation - Undo incorrect changes to main README.md - Update packages/features/calendar-subscription/README.md with: - Feature overview and motivation - Environment variables section - Complete feature flags documentation with SQL examples - SQL examples for enabling features for users and teams - Detailed architecture documentation Addresses PR #23876 documentation requirements Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix docs * Fix test to available calendars * Fix test to available calendars * add migration and sync boilerplate * fix typo * remove double log * sync boilerplate * remove console.log * only subscribe for google calendar * adjust for 3 months fetch * only subscribe for teams that have feature enabled * adjust tests * chore: safe increment error count Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * calendar sync * test: add comprehensive tests for CalendarSyncService - Add comprehensive test coverage for CalendarSyncService methods - Test handleEvents, cancelBooking, and rescheduleBooking functionality - Cover edge cases like missing UIDs, malformed UIDs, and error handling - Fix dynamic import usage in CalendarSyncService to use .default - Remove invalid properties from handleNewBooking call to fix type errors Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix: add skipCalendarSyncTaskCreation flag to handleCancelBooking to prevent infinite loops - Add skipCalendarSyncTaskCreation field to bookingCancelSchema in zod-utils.ts - Update handleCancelBooking to skip EventManager.cancelEvent when flag is true - Update CalendarSyncService.cancelBooking to pass skipCalendarSyncTaskCreation: true - Update CalendarSyncService.rescheduleBooking to pass skipCalendarSyncTaskCreation: true - Update tests to verify the flags are passed correctly This prevents infinite loops when calendar events are cancelled/rescheduled from external calendars (Google/Office365) which trigger webhooks to Cal.com, which would otherwise try to update the external calendar again. Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * refactor: rename flag to skipCalendarSyncTaskCancellation and use static imports - Rename skipCalendarSyncTaskCreation to skipCalendarSyncTaskCancellation in handleCancelBooking - Convert dynamic imports to static imports in CalendarSyncService - Update tests to use vi.hoisted for proper mock hoisting with static imports Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * feat: add error handling and static import for handleNewBooking - Create index.ts entry point for handleNewBooking directory - Add try-catch error handling to cancelBooking and rescheduleBooking - Log errors but don't block calendar sync operations - Update tests to verify errors are caught and logged, not thrown Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * refactor: use RegularBookingService directly and fix safeStringify usage - Remove handleNewBooking/index.ts and call getRegularBookingService().createBooking() directly in CalendarSyncService - Fix safeStringify usage: apply to error itself, not wrapper object - Update tests to mock getRegularBookingService instead of handleNewBooking Addresses PR comments from Volnei and Cubic-dev-ai Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix: restore handleNewBooking/index.ts and fix bookingData structure for calendar sync - Restore handleNewBooking/index.ts as entry point for static imports - Fix CalendarSyncService.rescheduleBooking to use correct bookingData structure with required fields (eventTypeId, start, end, timeZone, language, metadata) - Use rescheduleUid to indicate this is a reschedule operation - Fix safeStringify usage in error logging (wrap only the error, not the whole object) - Update tests to match new bookingData structure Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * refactor: address PR comments - use RegularBookingService directly, remove unnecessary flags, fix booking reference update - Remove handleNewBooking/index.ts wrapper and use getRegularBookingService().createBooking() directly in CalendarSyncService - Remove allRemainingBookings and cancelSubsequentBookings flags from cancelBooking (only cancel the specific booking, not the entire series) - Move bookingReference update outside skipCalendarSyncTaskCancellation block for data consistency - Update tests to match new implementation Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * chore: remove unnecessary comment from zod-utils.ts Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * feat: add Sentry metrics telemetry and fix null assertions in CalendarSyncService Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix: use dynamic import for getRegularBookingService to avoid RAQB import in server context Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * fix: use dynamic import for findTeamMembersMatchingAttributeLogic to avoid RAQB import in server context Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com> * improve booking update * add more tests and edge cases * fix: add required actionSource and Sentry mocks to calendar sync Add actionSource: "SYSTEM" to handleCancelBooking call after it became required, and mock @sentry/nextjs in test files. --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
5d65a0f091 |
fix: hide cal branding for orgs/teams (#27643)
* fix: hide branding for teams * fix: remove unused organizationId and username fields from profiles select Addresses Cubic AI review feedback (confidence 9/10) to select only the profile fields that are actually used. The organizationId and username fields were fetched but never referenced in this function. Co-Authored-By: unknown <> * fix: unit tests * fix: add prisma named export to test mock Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * Add tests: packages/features/profile/lib/hideBranding.test.ts Generated by Paragon from proposal for PR #27643 * chore: implement cubic feedback * fix: merge conflicts * fix: unit tests * fixup * refactor: implement DI pattern for event type service * fix: atoms build --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
4081d11fbe |
feat: workflow auto translation (#27087)
* feat: workflow auto translation * tests: add unit tests * refactor: tests and workflow * fix: type err * fix: type err * fix: remove redundant index on WorkflowStepTranslation The @@index on [workflowStepId, field, targetLocale] duplicates the @@unique constraint on the same columns. A unique index already provides efficient lookups, so the separate @@index adds storage overhead and write latency without benefit. Addresses Cubic AI review feedback (confidence 9/10). Co-Authored-By: unknown <> * fix: correct locale mapping when translation API returns null Map translations with their corresponding locales before filtering to preserve correct locale-to-translation associations. Previously, filtering out null translations would reindex the array, causing incorrect locale mappings when any translation in the batch failed. Also fixes pre-existing lint warnings: - Move exports to end of file - Add explicit return type to processTranslations - Replace ternary with if-else for upsertMany selection Co-Authored-By: udit@cal.com <udit222001@gmail.com> * fix: address review feedback for workflow auto-translation - Add change detection before creating translation tasks - Rename userLocale to sourceLocale in task props for clarity - Show source language in UI with new translation key - Extract SUPPORTED_LOCALES to shared translationConstants.ts - Fix locale mapping bug in translateEventTypeData.ts - Add WhatsApp translation support - Abstract translation lookup into shared translationLookup.ts helper - Restore if-else readability for SCANNING_WORKFLOW_STEPS Co-authored-by: Udit Takkar <udit.takkar@cal.com> Co-Authored-By: unknown <> * fix: update test to use sourceLocale instead of userLocale Co-Authored-By: unknown <> * refactor: feedback * fix: handle first time * fix: tests * fix: tests * fix: address Cubic AI review feedback (confidence 9/10 issues) - WhatsApp translation: Apply variable substitution using getSMSMessageWithVariables and clear contentSid when using translated body to ensure Twilio uses the translated text instead of the original template - update.handler.ts: Change sourceLocale assignment from ?? to || for consistency with tasker payload behavior (line 481) - ITranslationService.ts: Rename methods from plural to singular naming: - getWorkflowStepTranslations -> getWorkflowStepTranslation - getEventTypeTranslations -> getEventTypeTranslation Updated all call sites and tests accordingly Co-Authored-By: unknown <> * fix: address Cubic AI review feedback (confidence 9/10+ issues) - Fix getSMSMessageWithVariables to handle WHATSAPP_ATTENDEE action for locale and timezone (confidence 9/10) - Remove WhatsApp translation feature that set contentSid to undefined since Twilio ignores body parameter for WhatsApp and requires pre-approved Message Templates (confidence 10/10) Co-Authored-By: unknown <> * fix: translatio * Add tests: packages/features/eventTypeTranslation/repositories/EventTypeTranslationRepository.test.ts Generated by Paragon from proposal for PR #27087 * Add tests: packages/features/tasker/tasks/translateWorkflowStepData.test.ts Generated by Paragon from proposal for PR #27087 * chore: nit * chore: verfied atg * fix: set sourceLocale for new steps, add shouldDirty to checkbox, remove spec docs - Set sourceLocale fallback in addedSteps mapping to fix stale detection mismatch - Add { shouldDirty: true } to autoTranslateEnabled checkbox onChange - Remove specs/workflow-translation/ directory (planning docs, not for repo) Co-authored-by: Udit Takkar <udit.07.takkar@gmail.com> Co-Authored-By: unknown <> * chore: add specs back * fix: type error * fix: type error * fix: type err * fix: tests * refactor: feedback * fix: type err * refactor --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <udit.takkar@cal.com> Co-authored-by: Udit Takkar <udit.07.takkar@gmail.com> |
||
|
|
f883dee084 |
perf: improve getTotalBookingDuration query (#27383)
* perf: improve getTotalBookingDuration query * perf: improve getTotalBookingDuration query * test: add unit tests for getTotalBookingDurationForUsers and yearly duration pre-fetching Co-Authored-By: udit@cal.com <udit222001@gmail.com> * fix: integration tests * fix: update tests * fix: use vi.stubEnv instead of direct process.env modification for test isolation Replace direct deletion of process.env variables with vi.stubEnv() to ensure automatic restoration after tests, preventing flaky tests and side effects in parallel execution. Issue identified by Cubic AI (confidence: 9/10) Co-Authored-By: unknown <> * chore: add log * refactor: imports --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
e3a9f54ba5 |
feat: Configure cancellation reason (#26872)
* feat: Configure cancellation reason * fix: use enums * tests: add unit tests * fix: type error * chore: remove duplicate dialog * fix: type erro * refator: improvements * refator: improvements --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
9855176948 |
refactor: Remove all TrpcSessionUser usages in @calcom/features (#27853)
* sessionUser in features * update sessionMiddleware * update * format changes * update import paths * fix * fix ts errors * refactor * fix * fix * fix * fix * rename * rename * rename * use error with code objs |
||
|
|
48cbb94af2 |
feat: add webhook trigger when routing form fallback route is hit (#27588)
* feat: add no users found fallback action for routing forms - Add NoUsersFoundFallbackActionType enum with CustomPageMessage and ExternalRedirectUrl options - Add noUsersFoundFallbackAction field to zodNonRouterRoute schema - Add NoUsersFoundFallback UI component in RouteBuilder for configuring fallback action - Update handleResponse to return noUsersFoundFallbackAction when no team members match - Add i18n translation keys for new UI strings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: change fallback to use same action options as main route - Replace noUsersFoundFallbackAction with fallbackAction that has same structure as main action - Add action dropdown and input fields to fallback attributes query builder section - Support Event redirect, External URL, and Custom page options in fallback - Remove separate NoUsersFoundFallback toggle component - Update handleResponse to return fallbackAction Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: ensure fallbackAction type is always defined in onChange handlers Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add guards for route.fallbackAction in onChange handlers Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: only return fallbackAction when no users are found Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: restructure fallback section to mirror main route structure Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: ensure backwards compatibility for existing routes with fallbackAttributesQueryValue Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: initialize fallbackAction with main event type for backwards compatibility Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: include fallbackAction in getRoutesToSave to persist changes Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use fallbackAction in getRoutedUrl when no team members found Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use i18n for fallback label and add tests for fallback action Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: do not trigger fallback action when CRM contact owner is found Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: prioritize fallbackAction over fallbackAttributesQueryValue When a route has a fallbackAction configured, skip the fallbackAttributesQueryValue to ensure the fallbackAction is triggered when no team members are found. This maintains backwards compatibility by only using fallbackAttributesQueryValue when fallbackAction is not set. Also treats teamMemberIdsMatchingAttributeLogic being null (routing couldn't run, e.g., missing orgId) the same as an empty array for the purpose of triggering the fallbackAction. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract RouteActionSelector shared component for action selection UI Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add i18n string for default custom page message Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add webhook trigger when routing form fallback route is hit - Add ROUTING_FORM_FALLBACK_HIT to WebhookTriggerEvents enum in Prisma schema - Add new trigger to routing-forms webhook triggers in constants - Add translation string for the new webhook trigger - Implement triggerFallbackWebhook function in formSubmissionUtils.ts - Call webhook trigger from handleResponse.ts when fallback action is used Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove webhook object from error log to avoid exposing secrets Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * revert: remove webhook trigger changes (to be moved to separate PR) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add webhook trigger when routing form fallback route is hit - Add ROUTING_FORM_FALLBACK_HIT to WebhookTriggerEvents enum in Prisma schema - Add new trigger to routing-forms webhook triggers in constants - Add translation string for the new webhook trigger - Implement triggerFallbackWebhook function in formSubmissionUtils.ts - Call webhook trigger from handleResponse.ts when fallback action is used Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove webhook object from error log to avoid exposing secrets Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add ROUTING_FORM_FALLBACK_HIT to PayloadBuilderFactory trigger mapping Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * style: apply biome formatting fixes Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: restore removed comments in RouteBuilder Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: add prisma migration for ROUTING_FORM_FALLBACK_HIT enum value Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add ROUTING_FORM_FALLBACK_HIT to FormTriggerEvents type union Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add test coverage for triggerFallbackWebhook function Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: consolidate fallback webhook firing with form submission webhooks Move ROUTING_FORM_FALLBACK_HIT webhooks into the same Promise.all() batch as FORM_SUBMITTED / FORM_SUBMITTED_NO_EVENT, eliminating redundant getWebhooks/getWebhookTargetEntity/getOrgIdFromMemberOrTeamId calls. - Add fallbackAction parameter to _onFormSubmission and onSubmissionOfFormResponse - Remove triggerFallbackWebhook function and all its usages/imports - Move getFallbackAction() earlier in handleResponse.ts and pass result through - Update all tests to verify batched webhook behavior Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add UI option for trigger * feat: persist fallbackAction on queued form responses When a routing form response is queued, the fallbackAction determined during routing is now stored on the QueuedFormResponse record. When the queued response is later converted to a real FormResponse, the stored fallbackAction is passed to onSubmissionOfFormResponse so the ROUTING_FORM_FALLBACK_HIT webhook fires correctly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add coverage for fallbackAction in queued form response flow Verify that fallbackAction is persisted when queuing and passed through to onSubmissionOfFormResponse when the queued response is converted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
0a84ce5c73 |
fix: use smsReminderNumber fallback for attendee phone in SMS reminders (#27942)
* SMS reminders not trigger * addressed devin review * Add tests: packages/features/ee/workflows/lib/service/scheduleLazySMSWorkflow.test.ts Generated by Paragon from proposal for PR #27942 * Add tests: packages/features/ee/workflows/lib/reminders/reminderScheduler.smsLazy.test.ts Generated by Paragon from proposal for PR #27942 * Add tests: packages/features/tasker/tasks/sendWorkflowSMS.test.ts Generated by Paragon from proposal for PR #27942 * Add tests: packages/features/ee/workflows/lib/reminders/smsReminderManager.test.ts Generated by Paragon from proposal for PR #27942 * Delete packages/features/ee/workflows/lib/reminders/reminderScheduler.smsLazy.test.ts * fix: update sendWorkflowSMS tests to match refactored implementation Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix: use smsReminderNumber fallback for attendee phone in SMS workflows Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * revert: keep only scheduleSMSReminders.ts changes, revert all other files Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix: restore reminderScheduler.ts and smsReminderManager.ts to original branch state Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> * fix: use smsReminderNumber fallback for attendee phone in WhatsApp reminders Co-Authored-By: anik@cal.com <adhabal2002@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
7e73d675d7 |
refactor: improve invoice.upcoming logging and add strategyName to billing strategies (#28143)
- Add strategyName property to ISeatBillingStrategy interface and all implementations - Log which strategy handled the invoice.upcoming webhook (not just whether it applied) - Always log strategy result (not just when applied=true) for better observability - Rename highWaterMarkApplied to strategyApplied since applied covers multiple strategies Co-Authored-By: unknown <> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
648ad72a54 | refactor: extract dedicated @calcom/i18n package (#28141) | ||
|
|
06f4b25080 |
fix: update routing form identifier hint text with learn more link (#27837)
* fix: update routing form identifier hint text with learn more link Co-Authored-By: carina@cal.com <c.wollendorfer@me.com> * UI improvements --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: CarinaWolli <wollencarina@gmail.com> |
||
|
|
1aae57daae |
refactor(booking-audit): discriminated union for displayFields and i18n param support (#27373)
* feat: Add infrastructure for no-show audit integration - Add Prisma migrations for SYSTEM source and NO_SHOW_UPDATED audit action - Add NoShowUpdatedAuditActionService with array-based attendeesNoShow schema - Update BookingAuditActionServiceRegistry to include NO_SHOW_UPDATED - Update BookingAuditTaskConsumer and BookingAuditViewerService - Add AttendeeRepository methods for no-show queries - Update IAuditActionService interface with values array support - Update locales with no-show audit translation keys Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: Add NO_SHOW_UPDATED to BookingAuditAction and SYSTEM to ActionSource types Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: Remove HOST_NO_SHOW_UPDATED and ATTENDEE_NO_SHOW_UPDATED from BookingAuditAction type to match Prisma schema Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: Update BookingAuditActionSchema to use NO_SHOW_UPDATED instead of HOST_NO_SHOW_UPDATED and ATTENDEE_NO_SHOW_UPDATED Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor: Remove deprecated no-show audit services and unify to NoShowUpdatedAuditActionService - Delete HostNoShowUpdatedAuditActionService and AttendeeNoShowUpdatedAuditActionService - Update BookingAuditProducerService.interface.ts to use queueNoShowUpdatedAudit - Update BookingAuditTaskerProducerService.ts to use queueNoShowUpdatedAudit - Update BookingEventHandlerService.ts to use onNoShowUpdated - Add integration tests for NoShowUpdatedAuditActionService Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: Add data migration step for deprecated no-show enum values Addresses Cubic AI review feedback (confidence 9/10): The migration now includes an UPDATE statement to convert existing records using the deprecated 'host_no_show_updated' or 'attendee_no_show_updated' enum values to the new unified 'no_show_updated' value before the type cast. This prevents migration failures if any existing data uses the old values. Co-Authored-By: unknown <> * fix: Use CASE expression in USING clause for enum migration Fixes PostgreSQL error 'unsafe use of new value of enum type' by avoiding the ADD VALUE statement and instead using a CASE expression in the ALTER TABLE USING clause to convert deprecated enum values (host_no_show_updated, attendee_no_show_updated) to the new unified value (no_show_updated) during the type conversion. Co-Authored-By: unknown <> * fix: Replace hardcoded color with semantic text-success class Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: Remove color class completely from display fields Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * feat: Add valuesWithParams support for translatable complex field values Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor(booking-audit): use discriminated union for displayFields and update consumers Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: add explicit return type to getBookingHistoryHandler to bust stale tRPC build cache Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor: replace $t() nested interpolation with separate translation keys and add translationsWithParams tests Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
60b6086221 |
feat: add keyboard shortcuts and tooltips to booking slideover buttons (#27428)
* feat: add keyboard shortcuts and tooltips to booking slideover buttons Co-Authored-By: peer@cal.com <peer@cal.com> * fix: remove duplicate useBookingLocation import and fix import ordering - Removed duplicate import of useBookingLocation from non-existent @calcom/web/modules/bookings/hooks/useBookingLocation path - Fixed import ordering to satisfy biome organizeImports rules - Removed unnecessary code comment - Original feature by @PeerRich via Devin AI Co-Authored-By: unknown <> * use same style arrows for both button and remove bydefault focus from them * fix join button tooltip hover * fix: disable keyboard shortcuts when overlays/dialogs are open on BookingDetailsSheet Co-Authored-By: unknown <> * fix: use focus-based detection instead of selector-based overlay detection for keyboard shortcuts Co-Authored-By: unknown <> * fix: allow keyboard shortcuts when focus is on sheet ancestors Co-Authored-By: unknown <> * fix: use capture phase for keyboard handler to prevent Enter from activating focused buttons Co-Authored-By: unknown <> * fix: allow shortcuts when focus is on page elements outside any Radix portal Co-Authored-By: unknown <> * fix: handle calendar event clicks in onInteractOutside to prevent sheet close/reopen Co-Authored-By: unknown <> * fix: stop arrow key propagation to prevent Radix dropdown from opening during booking navigation Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: always stop arrow key propagation when sheet is active, even at first/last booking Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: extract keyboard handler into testable utility with tests Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: resolve type errors in keyboard handler config and test mocks Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * test: add e2e tests for booking sheet keyboard shortcuts Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: replace text= locators with data-testid selectors in e2e tests Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * made 3 fixes: Fix 1 — Stabilize handleNext/handlePrevious/handleClose with useCallback In BookingDetailsSheet.tsx, all three handler functions were plain arrow functions recreated on every render, causing the useEffect to tear down and re-attach the document keydown listener unnecessarily. Wrapped all three in useCallback with proper dependency arrays (the Zustand store functions they call). Fix 2 — data-booking-list-item verified (no change needed) Confirmed that data-booking-list-item is rendered on BookingListItem.tsx and data-booking-calendar-event is rendered on Event.tsx. The onInteractOutside handler in the final merged state correctly checks both selectors. No code change required. Fix 3 — Removed dead code from JoinMeetingButton Reverted JoinMeetingButton back to a plain function component: Removed forwardRef wrapping (no caller passes a ref) Removed showTooltip prop (unused — tooltip is handled by the parent BookingDetailsSheet) Removed ref prop from the inner Button Removed unused Tod forwardRef imports --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com> Co-authored-by: eunjae@cal.com <hey@eunjae.dev> Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com> |
||
|
|
5d65df9c05 |
chore: migrate booking requested webhook trigger (#27546)
* init * wiring up * fix type * feat: implement DI pattern for webhook producer in API v2 - Export IWebhookProducerService and getWebhookProducer from platform-libraries - Add WEBHOOK_PRODUCER token and useFactory provider in RegularBookingModule - Inject webhookProducer in RegularBookingService and pass to base class This follows the composition root pattern where only the NestJS module knows about getWebhookProducer(), and all consumers depend only on the IWebhookProducerService interface via constructor injection. Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * test: migrate BOOKING_REQUESTED tests to new webhook architecture - Remove failing BOOKING_REQUESTED tests from fresh-booking.test.ts (4 tests) - Remove failing BOOKING_REQUESTED tests from reschedule.test.ts (2 tests) - Remove failing BOOKING_REQUESTED test from collective-scheduling.test.ts (1 test) - Replace WebhookTaskConsumer.test.ts with placeholder (constructor changed) - Create new webhook architecture test suite: - producer/WebhookTaskerProducerService.test.ts (14 tests) - consumer/WebhookTaskConsumer.test.ts (8 tests) - consumer/triggers/booking-requested.test.ts (8 tests) The new test suite is organized by trigger type for extensibility as more triggers are migrated to the producer/consumer pattern. Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * test: remove paid events BOOKING_REQUESTED test (moved to new architecture) Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * wrap webhook in own try-catch * wire datafetcher * fix * fix v2 * fix circular dependency * -- * merge-conflict-resolve * mreg-conflict-resolve * remove early return * test: add integration tests for BOOKING_REQUESTED webhook producer invocation Cover all 8 scenarios verifying the booking flow correctly invokes the webhook producer for BOOKING_REQUESTED: 1. Basic confirmation → queueBookingRequestedWebhook called 2. Booker-is-organizer + confirmation → still called 3. Confirmation threshold NOT met → not called (BOOKING_CREATED instead) 4. Confirmation threshold IS met → called 5. Paid event + confirmation → called after payment succeeds 6. Reschedule + confirmation (non-organizer) → called (not BOOKING_RESCHEDULED) 7. Reschedule + confirmation (organizer) → not called (BOOKING_RESCHEDULED instead) 8. Collective scheduling + confirmation → called Adds reusable MockWebhookProducer helper in @calcom/testing for extendable use as more webhook triggers migrate to the new architecture. Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * fix bug * fix conditional check * remove unnecessary comment * add missing expect * remove empty test * clean up * tasker config * -- * fix missing metadata * remove faulty if else * test: add payload content verification tests for BOOKING_REQUESTED webhook Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * remove unnecessary tests --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Hariom Balhara <1780212+hariombalhara@users.noreply.github.com> |
||
|
|
c321a6c07a |
feat: owner can test non accepted OAuth client (#27525)
* refactor: combine exchange and refresh into token endpoint * refactor: controller error handling * refactor: use snake_case * refactor: use snake_case * refactor: use snake case * refactor: token endpoint accepts application/x-www-form-urlencoded * refactor: token endpoint accepts application/x-www-form-urlencoded * refactor: flat token response data * refactor: error structure * refactor: client_id in the body * fix: address Cubic AI review feedback on OAuth2 endpoints - Fix getClient endpoint to use proper REST API error format instead of OAuth token error format (confidence 9/10) - Add missing space after comma in error format string in token.input.pipe.ts (confidence 9/10) - Support both camelCase and snake_case inputs in authorize endpoint for backward compatibility (confidence 10/10) - Restore legacy /exchange and /refresh endpoints alongside new /token endpoint for backward compatibility (confidence 10/10) - Add OAuth2TokensResponseDto for legacy endpoint wrapped responses - Add OAuth2LegacyExchangeInput and OAuth2LegacyRefreshInput for legacy endpoints Co-Authored-By: unknown <> * fix: address additional Cubic AI feedback on OAuth2 endpoints - Log errors when status code >= 500 in handleClientError (confidence 9/10) - Add Cache-Control: no-store and Pragma: no-cache headers to legacy /exchange and /refresh endpoints (confidence 9/10) Co-Authored-By: unknown <> * docs * Revert "fix: address additional Cubic AI feedback on OAuth2 endpoints" This reverts commit 39cc4aa3ebb9e59a171541d7010398425995ed89. * Revert "fix: address Cubic AI review feedback on OAuth2 endpoints" This reverts commit 97bf593186db04c0859f9ca30950c9e3e524019d. * docs * fix: address Cubic AI review feedback on OAuth2 endpoints - Fix getClient to use handleClientError instead of handleTokenError (confidence 10) - Restore legacy /exchange and /refresh endpoints for backward compatibility (confidence 9) - Fix RFC 6749 error format: use human-readable messages in error_description (confidence 9) - Fix errorDescription in OAuthService to use OAUTH_ERROR_REASONS mapping (confidence 9) Co-Authored-By: unknown <> * fix: address additional Cubic AI feedback on OAuth2 endpoints - Fix security issue: Replace 'CALENDSO_ENCRYPTION_KEY is not set' with generic 'Internal server configuration error' message (confidence 10/10) - Fix backward compatibility: Create OAuth2LegacyTokensDto with camelCase properties for legacy /exchange and /refresh endpoints (confidence 9/10) - Skipped: RFC 6749 error field issue (confidence 8/10, below threshold) Co-Authored-By: unknown <> * e2e * Revert "fix: address additional Cubic AI feedback on OAuth2 endpoints" This reverts commit a080e93f07aaf5a7dcf81fe605012cb7ebcdc192. * Revert "fix: address Cubic AI review feedback on OAuth2 endpoints" This reverts commit 04986a16c981521ca97069152457bf521a9ee45f. * fix: re-apply Cubic AI review feedback on OAuth2 endpoints - Restore OAuth2LegacyExchangeInput and OAuth2LegacyRefreshInput classes - Restore legacy /exchange and /refresh endpoints in OAuth2Controller - Restore OAuth2LegacyTokensDto and OAuth2TokensResponseDto classes - Restore OAUTH_ERROR_DESCRIPTIONS mapping in oauth2-error.service.ts - Restore OAUTH_ERROR_REASONS lookup in OAuthService.ts mapErrorToOAuthError - Fix encryption_key_missing error to not expose internal env var name Addresses Cubic AI feedback with confidence >= 9/10: - Comment 32 (9/10): Legacy endpoints and input classes - Comment 34 (9/10): Error description mapping in OAuthService - Comment 35 (10/10): OAUTH_ERROR_DESCRIPTIONS in error service Skipped (confidence < 9/10): - Comment 33 (8/10): getClient handleTokenError vs handleClientError Co-Authored-By: unknown <> * Revert "fix: re-apply Cubic AI review feedback on OAuth2 endpoints" This reverts commit 416bef9c931d9a7ed78c65a70a3425550d61b151. * delete unused file * fix: e2e tests * address cubic review * fix: address Cubic AI review feedback on OAuth2 exception filter - Fix header case sensitivity: use lowercase 'x-request-id' instead of 'X-Request-Id' since Express lowercases all request headers - Redact request body in error logs to prevent exposing sensitive OAuth2 credentials like client_secret, password, and refresh_token Co-Authored-By: unknown <> * docs: api v2 oauth controller docs * chore: remove authorize endpoint * feat: owner can test non accepted OAuth client * fix: remove sensitive data from OAuth2 exception logs Remove Authorization header and userEmail from error logs in OAuth2HttpExceptionFilter to avoid logging sensitive information. Addresses Cubic AI review feedback (confidence 9/10). Co-Authored-By: unknown <> * fix: e2e --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
0eb2c15b39 |
fix: handle JSON string name field from URL prefill for firstAndLastName variant (#28039)
* fix: handle JSON string name field from URL prefill for firstAndLastName variant * refactoring logic * improve test coverage * remove unnecessary comment --------- Co-authored-by: Maks Pikov <mixelburg@users.noreply.github.com> Co-authored-by: Romit <romitgabani1.work@gmail.com> Co-authored-by: Romit <85230081+romitg2@users.noreply.github.com> |
||
|
|
9bfa4165b9 |
fix: prevent sending raw errors in responses (#24282)
* fix: prevent sending raw errors in responses * correct already existing typo * style: fix import ordering per biome lint Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
ad65fbbd81 |
fix: change URL prefill behavior to skip only invalid fields (#26982)
* fix: change URL prefill behavior to skip only invalid fields Previously, when prefilling booking form fields from URL query parameters, if any single field failed validation, all prefilling was skipped and an empty object was returned. This change modifies the behavior so that only invalid fields are skipped, while valid fields are still prefilled. The implementation: - Adds validateSingleFieldForPrefill() to validate individual fields - Adds parseFieldByField() to collect valid fields when full parse fails - Modifies getBookingResponsesPartialSchema to use field-by-field parsing as a fallback when full schema validation fails - Logs which specific fields were skipped and why This improves user experience by preserving valid prefill data even when some fields have invalid values. Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor: reduce code duplication in partial prefill validation Simplify the implementation by integrating field-by-field error handling directly into the existing preprocess() function instead of using separate helper functions. Changes: - Remove validateSingleFieldForPrefill() and parseFieldByField() functions - Simplify getBookingResponsesPartialSchema to directly use preprocess() - Add try-catch wrapper in preprocess() when isPartialSchema=true - Continue processing other fields even if one fails during preprocessing - Log skipped fields with reasons at debug level This reduces code duplication while maintaining the same behavior of skipping only invalid fields during URL prefill. Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fixes * refactor: rename getRefinedValue to superRefineField and add edge case tests - Rename getRefinedValue to superRefineField for clarity - Remove duplicate multiselect test block - Add test for empty object name field during partial prefill - Add test for invalid URL format during partial prefill - Add test for null responses during partial prefill Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * Simplifu * Simplif more * Enhance booking responses schema tests to validate required fields and name variants. Updated error handling for empty names and added tests for first and last name requirements. Refactored schema validation logic to improve clarity and maintainability. * fix types * test: add test for email validation behavior during partial prefill Documents that email validation is relaxed to z.string() during partial prefill, consistent with phone field behavior where partial values like '+91' are accepted. This addresses Cubic AI feedback (confidence 9/10) to verify email handling. Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix * Add tests: packages/features/bookings/lib/getBookingResponsesSchema.test.ts Generated by Paragon from proposal for PR #26982 * Revert "Add tests: packages/features/bookings/lib/getBookingResponsesSchema.test.ts" This reverts commit fc2b7ad7ca8099bc4f68e97b383ea16b41cdd772. * Simplify * fix: sanitize partial prefill log to avoid exposing user input data Replaced raw Zod issues array in console.warn with a count of validation errors to prevent sensitive user data from being logged. Issue identified by cubic (confidence 9/10). Co-Authored-By: unknown <> * fix * Remove throw Error * Refactor booking responses schema tests to use helper functions for assertions - Introduced `expectResponsesToBe` and `expectParsingToFail` helper functions to streamline test assertions. - Replaced direct assertions with these helper functions for improved readability and maintainability. - Removed redundant error handling code to simplify test logic. --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
a78a3ffe39 |
refactor: optimize team booking limits query with in-app filtering (#28021)
Replace 3 sequential queries (with expensive attendee email IN clauses) with 2 parallel queries using indexed eventType.teamId filtering and in-application user filtering with Sets for O(1) lookups. Fix managed events booking-limit behavior: managed bookings now only match by organizer userId (not attendee email), preserving the original query semantics where managed bookings used userId-only matching. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
a6a428c8cb |
feat: make actionSource required with ValidActionSource type across booking handlers (#27869)
* feat: make actionSource required with ValidActionSource type across booking handlers Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: update getAuditActionSource to return ValidActionSource, default to SYSTEM Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: revert getAuditActionSource, handleSeats, RegularBookingService back to ActionSource Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> |
||
|
|
b1eb5a2809 |
feat: api v2 POST booking attendees endpoint (#27759)
* feat: add booking attendee endpoint * chore: add attendee added email for add guests handler * cleanup * fix: restore BookingPbacGuard to prevent IDOR vulnerability in booking attendees endpoint Co-Authored-By: unknown <> * chore: implement review feedback, add a core service for booking attendees endpoint * chore: implement PR feedback * fix: dont reuse add guests handler instead add logic to add attendee function * fix: revert previous changes * chore: implement cubic feedback * fix: e2e tests * fix: e2e tests * fix: remove convertTRPCErrorToErrorWithCode not needed --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
11b65b295b |
test: add missing negation operator tests for TEXT, NUMBER, and compound rules (#27690)
* Fix exclusion filter - include all team members * Fix display when members aren't saved in the DB * Update tests * test: add missing negation operator tests for TEXT, NUMBER, and compound rules Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: revert non-intentional changes to AddMembersWithSwitch.tsx Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> --------- Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> |
||
|
|
4c73695d3a |
fix: refresh slots on timezone change for booker timezone restrictions (#27491)
* fix: refresh slots on timezone change for booker timezone restrictions * refactor: use useMemo for timezone change detection * revert: remove unnecessary formatting changes * feat: add timezone refresh for platform components Add timezone change detection and slot refresh to BookerPlatformWrapper and EventTypeCalendarViewComponent to handle restriction schedules with useBookerTimezone enabled. * refactor: extract timezone slot refresh logic into reusable hook * Update packages/platform/atoms/calendar-view/EventTypeCalendarViewComponent.tsx Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> * Update packages/platform/atoms/calendar-view/EventTypeCalendarViewComponent.tsx Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> * fix * fix: prevent unnecessary getSchedule calls when useBookerTimezone is disabled * fix: add timezone fields to BookerEvent type * fix: add missing properties to BookerEvent and BookerEventProfile types * trying to fix type errors * Add restrictionScheduleId and useBookerTimezone fields * fix: correct import path for useBookerTime hook Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * fix: explicitly include restrictionScheduleId and useBookerTimezone in getPublicEvent return Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * chore: trigger fresh CI build Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * fix: cast event.data to BookerEvent for timezone fields access Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * refactor: address review feedback for timezone slot refresh Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * refactor: add explicit return type to event handler to ensure type propagation Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * refactor: extract useStableTimezone hook and remove dead timezone detection code Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> --------- Co-authored-by: hackice20 <yashkam431@gmail.com> Co-authored-by: Yash <116657771+hackice20@users.noreply.github.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
38b43f75ba |
refactor: remove circular dependencies from CalendarView atom (#27850)
* fix: decouple large calendar from features * fix: move calendar to features since this is the better approach * chore: move OOO slots to features * feat: add DefaultOutOfOfficeSlot fallback for calendar OOO rendering Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * chore: cleanup unused LargeCalendar component --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
2bc17313fd |
fix: deep link reschedule audit log to booking drawer history tab (#27709)
* fix: deep link reschedule audit log to booking drawer history tab Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: make booking drawer tab-agnostic for cross-tab deep links Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: use status-agnostic /bookings URL for audit log deep links - Update audit service URLs from /bookings/upcoming?uid=... to /bookings?uid=... - Add /bookings/page.tsx redirect that routes to /bookings/upcoming preserving query params - Update tests to expect new URL format Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fixes * refactor: use client-side replaceState instead of server redirect for booking deep links Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: use router.replace instead of replaceState to update tab and booking list Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * improvements * refactor: extract deep link logic from BookingListContainer into usePreSelectedBooking hook Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: use proper BookingOutput status type in test helper Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: decouple getTabForBooking from BookingOutput type for simpler testing Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: accept Date | string for endTime in BookingForTabResolution interface Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor: eliminate initialBookingUid prop drilling and revert formatting-only changes Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: use AuditDeepLink wrapper to preserve target=_blank through ServerTrans cloneElement Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * Improve code organization * refactor: rename usePreSelectedBooking to useSwitchToCorrectStatusTab Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: push preSelectedBooking into store so drawer opens on direct navigation Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fixes * fixes * fixes * fix --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> |
||
|
|
3a7122d613 |
fix: revert assignmentReason breaking change in webhook payloads (#27891)
* fix: revert assignmentReason breaking change in webhook payloads
Remove the new { category, details } format from EventPayloadType to
maintain backward compatibility for webhook consumers. The new format
is stripped at all webhook payload construction sites by destructuring
assignmentReason out of CalendarEvent before spreading into the payload.
A sanitizeAssignmentReasonForWebhook function provides an additional
safety net in sendPayload itself. Emails and booking single view
continue to use the new format via CalendarEvent.
Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
* fix: strip assignmentReason from handlePaymentSuccess webhook payload
Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
* fix: strip assignmentReason from triggerWebhooks and handleSeats webhook payloads
Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
* refactor: use zod safeParse instead of type assertion in sanitizeAssignmentReasonForWebhook
Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
||
|
|
c21281a55c | preserve customReplyToEmail (#27941) | ||
|
|
50c7210d6b |
fix: resolve signup watchlist review issues and auto-unlock on SIGNUP entry removal (#27923)
* fix: resolve signup watchlist review issues with deleteEntry, email verification ordering, and unlock flow Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * fix: scope sendEmailVerification to non-invite signups only Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * feat: auto-unlock users when SIGNUP-source watchlist entries are removed Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> * fix: remove PII from error logging in unlockSignupUser Co-Authored-By: ali@cal.com <alishahbaz7@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
d3bbed01f6 |
feat: add signup watchlist review mode (#27912)
* feat: add signup watchlist review feature flag and handler logic - Add 'signup-watchlist-review' global feature flag - Add SIGNUP to WatchlistSource enum in Prisma schema - When flag enabled, lock new signups and add email to watchlist - Show 'account under review' message on signup page - Add i18n strings for review UI - Create seed migration for the feature flag Co-Authored-By: alex@cal.com <me@alexvanandel.com> * test: add isAccountUnderReview tests to fetchSignup test suite Co-Authored-By: alex@cal.com <me@alexvanandel.com> * fix: address Cubic AI review feedback (confidence >= 9/10) - Remove 'import process from node:process' in signup-view.tsx (P0 bug in 'use client' component) - Move watchlist review check before checkoutSessionId early return in calcomSignupHandler (P1 premium bypass) - Revert selfHostedHandler to original state (out of scope per user request) - Add test mocks for FeaturesRepository and GlobalWatchlistRepository Co-Authored-By: alex@cal.com <me@alexvanandel.com> * fix: remove node:process import from useFlags.ts (client-side file) Co-Authored-By: alex@cal.com <me@alexvanandel.com> * fix: remove !token condition from watchlist review check Token is present in normal email-verified signups, so the !token condition was incorrectly skipping watchlist review for verified users. Co-Authored-By: alex@cal.com <me@alexvanandel.com> * Apply suggestion from @cubic-dev-ai[bot] Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * refactor: move user lock to UserRepository.lockByEmail Co-Authored-By: alex@cal.com <me@alexvanandel.com> * refactor: use cached getFeatureRepository() instead of deprecated FeaturesRepository Co-Authored-By: alex@cal.com <me@alexvanandel.com> * refactor: remove user locking, keep only watchlist addition on signup review Co-Authored-By: alex@cal.com <me@alexvanandel.com> * feat: lock user on signup review, remove watchlist entry on unlock Co-Authored-By: alex@cal.com <me@alexvanandel.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> |
||
|
|
1368ffe55d |
refactor: move data-table hooks/contexts/provider from features to web modules (#27833)
* refactor: move data-table hooks/contexts/provider from features to web modules Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: update broken useColumnResizing import path in DataTable.tsx Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: update remaining broken import paths for moved hooks Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * docs: update GUIDE.md import paths and file references for moved modules Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
397bf3cc0c |
fix: use personal credits if no more team credits (#27518)
* use personal credits if team has no more credits * clean up * adjust comment --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> |
||
|
|
98ec38aeaa |
feat: add annual plans for teams/organizations (#27896)
* wip: add annual plan priceId support * fix type errors * type cast |
||
|
|
d52e2d9fad |
feat: active user billing (#27867)
* factory and statergie * chore: use correct method of DI * feat: add onchagne * add logic to HWM stat * add webhook resolver methods to each statergy * move seat tracking + webhooks over to own statergy * Move to factory base approach * move logic to correct class * rename create -> createByTeamId * fix: remove debug `true ||` overrides from IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED Remove accidentally committed debug overrides that short-circuited IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED to always be true, bypassing Stripe credential checks. This would break self-hosted instances without Stripe configured. Identified by cubic (https://cubic.dev) Co-Authored-By: unknown <> * feat: active user billing * add tests * UI side for users on active billing * use correct period of stripe sub * feat: claude feedback * fix: skip Stripe sync for canceled/expired subscriptions to prevent repeated API calls Co-Authored-By: unknown <> * feat: feedback * feat: only render when active users mode is set * fix type error * fix: constants + feature flags * fix: default to null in tests * chore: use seats in test * fix: use node:crypto protocol for Node.js builtin imports Co-Authored-By: sean@cal.com <Sean@brydon.io> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
bf348ee209 |
refactor: migrate Icon to component icons from @coss/ui/icons (#27458)
* feat: add @coss/ui/icons package and migrate static icon usages
Create a new icon system in @coss/ui/icons that wraps lucide-react icons
with controlled props (size and className only). Migrate 44 component
files from <Icon name="xxx" /> to <XxxIcon /> pattern.
This is Phase 1 of the icon migration, covering only static icon names.
Dynamic icon usages (e.g., name={variable}) are skipped for now.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate more static icons to @coss/ui/icons (batch 2)
Migrated 18 files from <Icon name="xxx" /> to <XxxIcon /> pattern:
- Event meta, insights, shell, user table bulk actions
- Webhooks, blocklist, form-builder, form components
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate more static icons to @coss/ui/icons (batch 3)
Migrated 7 files:
- CancelBooking, AddGuestsDialog, ChargeCardDialog
- ReassignDialog, RescheduleDialog
- Categories, Slider
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate more static icons to @coss/ui/icons (batch 4)
Migrated 6 files:
- Organizations: AboutOrganizationForm, PaymentStatusView, profile
- Workflows: CallDetailsSheet, SkeletonLoaderList, TimeTimeUnitInput
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate more static icons to @coss/ui/icons (batch 5)
Migrated 4 files:
- TwoFactorModalHeader
- App setups: alby, make, btcpayserver
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 6)
- confirmDialog.tsx: clock icon
- ics-feedcalendar/Setup.tsx: trash, plus icons
- hitpay/Setup.tsx: info icon
- paypal/Setup.tsx: circle-alert icons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 7)
- webhook-edit-view.tsx: external-link icon
- webhook-new-view.tsx: external-link icon
- UserDropdown.tsx: chevron-down, user, settings, moon, map, circle-help, download, blocks, log-out icons
- TopNav.tsx: settings icon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 8)
- EmailInviteForm.tsx: x icon
- InviteOptions.tsx: mail, upload, link icons
- SkeletonLoader.tsx: search, clock, user icons
- Embed.tsx: sun, arrow-left icons
- CalendarSwitch.tsx: arrow-left, rotate-cw icons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 9)
- apps-view.tsx: search icon
- categories-view.tsx: arrow-left, arrow-right icons
- DatePicker.tsx: calendar icon
- EditLocationDialog.tsx: map-pin icon
- AppPage.tsx: circle-alert, book-open, external-link, mail, file, shield, flag icons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 10)
- LicenseSelection.tsx: loader, check icons
- AppConnectionItem.tsx: circle-alert, arrow-right icons
- oauth-client-form/index.tsx: info icons (x2)
- auth/error/page.tsx: x icon
- troubleshoot/layout.tsx: loader icon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 11)
- UpgradeTipWrapper.tsx: users, refresh-ccw, user-plus icons
- PbacOptInModal.tsx: shield-check, lock, users, shield icons
- AdvancedPermissionGroup.tsx: chevron-right, info icons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 12)
- AdminAppsList.tsx: pencil icon
- AvailableTimes.tsx: calendar-x-2 icon
- BookingDetailsSheet.tsx: external-link (x2), repeat icons
- BookingCalendarContainer.tsx: chevron-left, chevron-right icons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 13)
- videos-single-view.tsx: chevron-right icon
- TroubleshooterSidebar.tsx: arrow-left icon
- RuleBuilder.tsx: filter icon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 14)
- FieldMappingBuilder.tsx: arrow-right, link icons
- IntegrationAttributeSyncCard.tsx: key icon
- onboarding-view.tsx: loader icon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static icons to @coss/ui/icons (batch 15)
- team-profile-view.tsx: copy icon
- DateRangeFilter.tsx: check icon
- ColumnVisibilityButton.tsx: check icon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static Icon to @coss/ui/icons (batch 16)
- EventWorkflowsTab.tsx: lock
- event-types-listing-view.tsx: search
- onboarding-migrate-members-browser-view.tsx: arrow-left, arrow-right, rotate-cw, lock, ellipsis-vertical, check, user-plus
- onboarding-migrate-teams-browser-view.tsx: arrow-left, arrow-right, rotate-cw, lock, ellipsis-vertical, check, arrow-right, users
- EventAvailabilityTab.tsx: globe, user
- onboarding-teams-browser-view.tsx: arrow-left, arrow-right, rotate-cw, lock, ellipsis-vertical, check, arrow-right, users
- FormBuilder.tsx: mail, phone, arrow-up, arrow-down
- AIEventController.tsx: info
- EventTeamAssignmentTab.tsx: x
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static Icon to @coss/ui/icons (batch 17)
- EventAdvancedTab.tsx: pencil, info
- HostLocations.tsx: triangle-alert, loader
- EventTypeLayout.tsx: loader
- Locations.tsx: x, corner-down-right, check
- EditWeightsForAllTeamMembers.tsx: upload, search, info, chevron-down
- WorkflowPage.tsx: pencil
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static Icon to @coss/ui/icons (batch 18)
- TestPhoneCallDialog.tsx: phone
- WorkflowListPage.tsx: link
- UsersTable.tsx: building, lock
- TeamList.tsx: building, paintbrush, chart-line, user-plus, users, pencil
- bookings-single-view.tsx: chevron-left, check, calendar, x, external-link
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate static Icon to @coss/ui/icons (batch 19)
- TeamsListing.tsx: users, refresh-ccw, user-plus, mail, video, eye-off, info
- ConnectionInfo.tsx: clipboard
- IntercomContactForm.tsx: message-circle, loader, send
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: migrate static Icon to @coss/ui/icons in teams components
- EventTypesList.tsx: check → CheckIcon
- MemberInvitationModal.tsx: user, users, building → UserIcon, UsersIcon, BuildingIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: migrate static Icon to @coss/ui/icons in workflow components
- ImportNumberDialog.tsx: info → InfoIcon
- VoiceSelector.tsx: user → UserIcon
- IncomingCallsTab.tsx: info, phone-incoming → InfoIcon, PhoneIncomingIcon
- PhoneNumberTab.tsx: loader, phone → LoaderIcon, PhoneIcon
- VoiceSelectionDialog.tsx: pause, play, user → PauseIcon, PlayIcon, UserIcon
- WebCallDialog.tsx: loader, phone, phone-off, triangle-alert, trash, message-circle → new icons (kept Icon import for dynamic mic icon)
- WorkflowDetailsPage.tsx: zap, arrow-right → ZapIcon, ArrowRightIcon
- AddActionDialog.tsx: info → InfoIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: migrate static Icon to @coss/ui/icons in WorkflowStepContainer
- info → InfoIcon (2 instances)
- phone → PhoneIcon (2 instances)
- circle-help → CircleHelpIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: migrate static Icon to @coss/ui/icons in data-table and org components
- attributes-list-view.tsx: tags → TagsIcon
- AddFilterButton.tsx: plus, eye-off → PlusIcon, EyeOffIcon
- BaseSelectFilterOptions.tsx: check → CheckIcon
- DataTable.tsx: arrow-up, arrow-down, check, chevrons-up-down, eye-off → new icons
- booking-dry-run-success-view.tsx: check → CheckIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: migrate static Icon to @coss/ui/icons in username and routing components
- UsernameTextfield.tsx: check → CheckIcon
- PremiumTextfield.tsx: check, external-link → CheckIcon, ExternalLinkIcon (kept Icon for star with fill prop)
- Header.tsx (routing-forms): pencil, menu, waypoints → PencilIcon, MenuIcon, WaypointsIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate Icon to component icons in routing-forms pages
Batch 25: Migrate static Icon usages to @coss/ui/icons components.
Files changed:
- Forms.tsx: file-text, shuffle, chart-bar, circle-check, mail, download → FileTextIcon, ShuffleIcon, ChartBarIcon, CircleCheckIcon, MailIcon, DownloadIcon
- FormEdit.tsx: chevron-down, menu → ChevronDownIcon, MenuIcon
- IncompleteBooking.tsx: globe → GlobeIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate Icon to component icons in UI package
Batch 26: Migrate static Icon usages to @coss/ui/icons components.
Files changed:
- ProgressToast.tsx: file-down, x → FileDownIcon, XIcon
- showToast.tsx: check, info, x → CheckIcon, InfoIcon, XIcon
- InfoBadge.tsx: info → InfoIcon
- MeetingTimeInTimezones.tsx: globe → GlobeIcon
- InputError.tsx: info → InfoIcon
- ConfirmationDialogContent.tsx: circle-alert, check → CircleAlertIcon, CheckIcon
- CalendarSwitch.tsx: arrow-left, rotate-cw → ArrowLeftIcon, RotateCwIcon
- ArrowButton.tsx: arrow-up, arrow-down → ArrowUpIcon, ArrowDownIcon
- FileUploader.tsx: upload → UploadIcon (kept Icon for dynamic)
- Checkbox.tsx: check → CheckIcon
- EditableHeading.tsx: pencil → PencilIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate Icon to component icons in UI and app-store packages
Batch 27: Migrate static Icon usages to @coss/ui/icons components.
Files changed:
- MultiEmail.tsx: x → XIcon (converted width to size)
- AppListCard.tsx: circle-alert → CircleAlertIcon
- SplitButton.tsx: chevron-down → ChevronDownIcon (kept Icon for dynamic)
- Calendar.tsx: chevron-left, chevron-right → ChevronLeftIcon, ChevronRightIcon
- AppDependencyComponent.tsx: check, circle-x, arrow-right → CheckIcon, CircleXIcon, ArrowRightIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate Icon to component icons in form input components
Batch 28: Migrate static Icon usages to @coss/ui/icons components.
Files changed:
- TextField.tsx: info → InfoIcon (kept Icon for x with onClick)
- Input.tsx: eye, eye-off, search → EyeIcon, EyeOffIcon, SearchIcon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: use @coss/ui/src/icons in packages with legacy moduleResolution
Packages like packages/ui and packages/app-store use a legacy moduleResolution
setting that doesn't support subpath exports. This changes the import path from
@coss/ui/icons to @coss/ui/src/icons for these packages.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate Icon to component icons in UI form and editor components
Migrates static Icon usages:
- MultiOptionInput: x (2x), arrow-up, arrow-down
- components (select): check
- AddVariablesDropdown: chevron-down (3x)
- ToolbarPlugin: chevron-down
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: migrate Icon to component icons in settings and platform atoms
Migrates static Icon usages:
- SettingsLayoutAppDirClient: chevron-down (2x), chevron-right (2x), arrow-left
- platform/atoms dialog: x
- platform/atoms toast: x
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve @coss/ui/icons module resolution for legacy moduleResolution
Add typesVersions to @coss/ui package.json to help TypeScript resolve
subpath exports even with legacy moduleResolution: "node" setting.
Change imports from @coss/ui/src/icons to @coss/ui/icons to avoid
double-src path issue when Next.js applies import maps.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: localize 'Select field type' fallback label in FormEdit
Address Cubic AI review feedback (confidence 9/10) by using t() for
the hardcoded 'Select field type' string to ensure proper i18n support.
Co-Authored-By: unknown <>
* fix: add typesVersions wildcards for @coss/ui subpath imports
Add lib/*, components/*, and hooks/* to typesVersions to support
legacy moduleResolution with all package subpath patterns.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve missing Icon references in settings and workflows
- Add Icon import for dynamic icon usages in SettingsLayoutAppDirClient
- Replace static Icon usages with component icons (InfoIcon, PhoneIcon)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: resolve icon component type errors
- Add onClick prop support to IconProps
- Fix size prop type (use number instead of string)
- Rename local MailOpenIcon to MailOpenIconWrapper to avoid shadowing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: add data-testid to icon components for test compatibility
- Add testId parameter to createIcon function
- Auto-generate data-testid for all icons (e.g., "check-icon", "search-icon")
- Remove outdated mock for @calcom/ui/components/icon in tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update package.json
* Update package.json
* fix: migrate Icon to CalendarDaysIcon in videos-single-view.tsx
Co-Authored-By: unknown <>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
||
|
|
7cfb053026 |
feat: add wrong routing tab under Insights for reviewing assignment reports (#27423)
* Add DB table for wrong assignment reports * When report is submitted write to the db * Prevent duplicate reportings * test: add migration and tests for WrongAssignmentReport table Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add unique constraint on bookingUid and booking access check for hasWrongAssignmentReport - Add @unique constraint on bookingUid in WrongAssignmentReport model to prevent duplicate reports at DB level - Add booking ownership check using BookingAccessService in hasWrongAssignmentReport endpoint - Refactor hasWrongAssignmentReport into separate handler and schema files Addresses Cubic AI review feedback on PR #27405 Co-Authored-By: unknown <> * feat: add routingFormId to WrongAssignmentReport and fix Select clearing - Add routingFormId field to WrongAssignmentReport model in schema.prisma - Add relation to App_RoutingForms_Form with SetNull on delete - Update WrongAssignmentReportRepository.createReport to accept routingFormId - Update BookingRepository.findByUidIncludeEventTypeAndTeamAndAssignmentReason to include routedFromRoutingFormReponse - Extract routingFormId from booking in reportWrongAssignment handler - Fix Select clearing issue: handle null case when user clears team member selection - Update tests to include routingFormId field Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: add migration for routingFormId in WrongAssignmentReport Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add wrong assignment reports dashboard under routing tab - Add reviewedById and reviewedAt fields to WrongAssignmentReport model - Add repository methods for listing reports by status and updating status - Create tRPC endpoints for fetching reports and updating status - Create dashboard UI with pending/reviewed tabs showing routing form name - Add translation keys for dashboard UI - Integrate dashboard into routing insights page Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: move hooks before early return and fix indentation Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: address Udit's review comments - hasWrongAssignmentReport: throw UNAUTHORIZED error instead of returning false - reportWrongAssignment: add try-catch for Prisma P2002 unique constraint error - WrongAssignmentReport: add Team relation to teamId field - WrongAssignmentReportRepository: use findUnique instead of findFirst - reportWrongAssignment: use i18n for error messages Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: revert hasWrongAssignmentReport to return false when user lacks access Per PR checklist, hasWrongAssignmentReport should return { hasReport: false } when user lacks access to booking, not throw an error. This allows the UI to gracefully treat 'no access' as 'no report exists'. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: update mocks for findUnique and i18n in unit tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: throw UNAUTHORIZED in hasWrongAssignmentReport and squash migrations Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: move wrong assignment reports to its own tab under Insights Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Use data table for wrong reports * Add option to view routing trace * feat: add view routing form submission action to wrong assignment reports Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add RoutingFormResponseSheet component for viewing form submissions - Create slide-out sheet to display routing form responses - Map option IDs to display labels for select/multiselect fields - Handle both legacy and modern option formats - Add i18n strings: form_submission, no_responses_found Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: improve wrong assignment reports UX - Integrate RoutingFormResponseSheet as slide-out panel instead of new tab - Fix dropdown padding by using StartIcon prop instead of manual Icon - Allow direct status changes for reviewed reports (no need to reopen first) - Remove unused Icon import Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: change User relation onDelete from Cascade to SetNull in WrongAssignmentReport Address Hariom's review feedback: - Changed reportedById from Int to Int? (nullable) - Changed reportedBy relation from onDelete: Cascade to onDelete: SetNull - Updated migration SQL to reflect these changes This preserves wrong assignment reports even when the reporting user is deleted, as the data is still useful for analysis. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add missing i18n strings for wrong assignment reports dashboard Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: move form response display value resolution server-side Replace client-side option ID to label resolution in RoutingFormResponseSheet with a new lean tRPC endpoint (getFormResponseDisplay) that resolves values server-side using the existing getHumanReadableFieldResponseValue utility. This enforces DTO boundaries by returning a clean pre-resolved payload instead of leaking internal option format details to the client. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add report wrong assignment button to routing trace sheet Wire up the WrongAssignmentDialog from the routing trace sheet header so users can flag wrong assignments directly while viewing the trace. The report button is disabled with a tooltip when a report already exists. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: reuse existing WrongAssignmentDialog from parent Replace the duplicate WrongAssignmentDialog in RoutingTraceSheet with a callback to the existing instance in BookingActionsDropdown. This reduces the prop surface from a 6-field reportContext object to an onReport callback and hasExistingReport boolean. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: use repository instead of direct Prisma in getFormResponseDisplay Replace direct Prisma query with PrismaRoutingFormResponseRepository's findByIdIncludeForm method. Extend the method to also select form name, description, userId, and teamId needed for display and auth checks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: replace direct Prisma calls with repository methods Use MembershipRepository.hasMembership() for auth checks and TeamRepository.findAllByParentId() for child team queries instead of direct Prisma calls. Replace direct user query with UserRepository.getTimeZoneAndDefaultScheduleId(). Remove unused seed script. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: use PBAC services for wrong assignment report auth Replace manual MembershipRepository.hasMembership() checks with PBAC-aware permission checking. getWrongAssignmentReports uses createTeamPbacProcedure middleware since teamId is in input. updateWrongAssignmentReportStatus uses PermissionCheckService directly since teamId is discovered from the report entity. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve type errors in RoutingFormResponseSheet and wrong-routing view Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add seed script for wrong assignment reports test data Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * Revert "feat: add seed script for wrong assignment reports test data" This reverts commit 0bd60e9661858a59aab1573d14d57d81733b7991. * Only update reviewed fields when not pending Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * refactor: wrap handleStatusChange in useCallback to fix useMemo recalculation Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix routing sheet UI * fix: use appropriate error message in getFormResponseDisplay handler Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: extract WrongAssignmentReportService from tRPC handlers Move business logic (booking lookup, duplicate check, report creation, webhook dispatch, org-level team resolution) into a dedicated service in packages/features. Handlers become thin controllers that only handle auth checks and delegate to the service. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: restrict report status updates to admin/owner roles Remove MembershipRole.MEMBER from fallbackRoles in updateWrongAssignmentReportStatus permission check. Updating report status is an administrative action that should be limited to team admins and owners. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: localize hard-coded success message in WrongAssignmentReportService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: rename reviewed tab to handled and add missing translations Rename the "Reviewed" tab to "Handled" since it groups three distinct statuses (Reviewed, Resolved, Dismissed). Also add missing translation keys for "resolved" and "dismissed" status badges. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * merge: resolve conflicts with main branch Merge main into devin/1769747741-wrong-assignment-dashboard, resolving conflicts in: - BookingActionsDropdown.tsx: use main's booking prop with PR's fragment structure - reportWrongAssignment.handler.ts: keep PR's service-based approach - reportWrongAssignment.handler.test.ts: use main's class-based mocks with PR's additions - WrongAssignmentReportService.ts: align with main's repo method and field names Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add guard when accessing assignmentReasonSortedByCreatedAt Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fix: address Cubic AI review feedback - select projection and useLocale refactor Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove stale TRPCError assertion in test (service throws ErrorWithCode) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: remove unused findByTeamIdAndStatus and findByTeamIdAndStatuses methods Co-Authored-By: alex@cal.com <me@alexvanandel.com> * perf: add composite index on WrongAssignmentReport and narrow findByIdIncludeForm select Co-Authored-By: alex@cal.com <me@alexvanandel.com> * perf: use lightweight findTeamIdById in update-status handler instead of findById Co-Authored-By: alex@cal.com <me@alexvanandel.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: hariom@cal.com <hariombalhara@gmail.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: alex@cal.com <me@alexvanandel.com> |
||
|
|
50c5423ba7 |
fix: support underscores in workflow template variables with backward compatibility (#27571)
## What does this PR do?
Fixes an issue where underscores in form field identifiers were being stripped when converting to workflow template variables. According to the documentation, users should be able to use variables like `{COMPANY_NAME}` or `{MONTHLY_INFRASTRUCTURE_SPEND}`, but the regex in `formatIdentifierToVariable` was removing underscores, causing these variables to not match.
**The problem:**
- Form field identifier: `Company_Name` or `Monthly_Infrastructure_Spend`
- Expected variable: `{COMPANY_NAME}` or `{MONTHLY_INFRASTRUCTURE_SPEND}`
- Actual variable (before fix): `{COMPANYNAME}` or `{MONTHLYINFRASTRUCTURESPEND}`
**The fix:**
- Updated the regex from `[^a-zA-Z0-9 ]` to `[^a-zA-Z0-9_ ]` to preserve underscores in `formatIdentifierToVariable`
- Added a private `formatIdentifierToVariableLegacy` function that maintains the old behavior (strips underscores)
- Added `getVariableFormats` helper that returns both current and legacy formats for backward compatibility
- Added `convertResponsesToVariableFormats` helper in `executeAIPhoneCall.ts` to convert form responses to both variable formats
- Updated `customTemplate.ts` matching logic to support both variable formats
- Updated `executeAIPhoneCall.ts` to include both variable formats when building dynamic variables
This ensures existing templates using `{COMPANYNAME}` continue to work while new templates can use the documented `{COMPANY_NAME}` format.
## Mandatory Tasks (DO NOT REMOVE)
- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - no docs changes needed.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
1. Create a routing form with a field identifier containing underscores (e.g., `Company_Name`)
2. Create a workflow with a template using `{COMPANY_NAME}` (with underscore)
3. Submit the form and verify the variable is replaced correctly
4. Also test with `{COMPANYNAME}` (without underscore) to verify backward compatibility
**Automated tests added:**
- `customTemplate.test.ts` - 15 tests covering `formatIdentifierToVariable`, `getVariableFormats`, and template variable replacement
- `executeAIPhoneCall.test.ts` - 6 tests covering `convertResponsesToVariableFormats` function for form responses
## Human Review Checklist
- [ ] Verify the regex change `[^a-zA-Z0-9_ ]` correctly preserves underscores
- [ ] Verify backward compatibility: both `{COMPANY_NAME}` and `{COMPANYNAME}` should work for the same form field
- [ ] Verify `convertResponsesToVariableFormats` correctly generates both variable formats
- [ ] Review test coverage for edge cases (empty responses, undefined values)
---
Link to Devin run: https://app.devin.ai/sessions/9d5d90178714493086d94691865c3e07
Requested by: @hariombalhara
<!-- devin-review-badge-begin -->
---
<a href="https://app.devin.ai/review/calcom/cal.com/pull/27571">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin">
</picture>
</a>
<!-- devin-review-badge-end -->
|
||
|
|
06bb994145 |
fix: Improve wrong assignment report (#27162)
* Pass already fetched booking * Fetch the assignment reason * Update tests * Label as first assignment reason * Pass single booking object * Remove unused repository method * Only pass bookingUid to handler * Rename booking `assignmentReason` to `assignmentReasonSortedByCreatedAt` * fix: use renamed assignmentReasonSortedByCreatedAt property Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Remove take statement * fix: address Udit's review comments - Restore BookingAccessService for access control checks - Rename repository method from findByUidForWrongAssignmentReport to findByUidIncludeUserAndEventTypeTeamAndAttendeesAndAssignmentReason Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: update tests to use BookingAccessService mock Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use latest assignment reason in BookingDetailsSheet for consistency Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
98b6d63164 |
refactor: apply biome formatting to packages/features (#27844)
* refactor: apply biome formatting to packages/features (batch 1 - small subdirs) Format small subdirectories in packages/features: di, flags, holidays, oauth, settings, users, assignment-reason, selectedCalendar, hashedLink, host, form, form-builder, availability, data-table, pbac, schedules, troubleshooter, eventtypes, calendar-subscription, and root-level files. Also includes straggler apps/web BookEventForm.tsx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 2 - medium subdirs) Format medium subdirectories in packages/features: auth, credentials, calendars, routing-forms, routing-trace, attributes, watchlist, calAIPhone, tasker, and webhooks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 3 - bookings + insights) Format bookings and insights subdirectories in packages/features. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 4 - ee) Format packages/features/ee subdirectory covering billing, workflows, organizations, teams, managed-event-types, round-robin, dsync, integration-attribute-sync, and payments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 5 - booking-audit part 1) Format booking-audit di, actions, common, dto, repository, and types subdirectories in packages/features/booking-audit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 6 - booking-audit part 2) Format booking-audit service subdirectory in packages/features/booking-audit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
6089f47d24 |
feat: add fallback action options to routing form fallback section (#27449)
* feat: add no users found fallback action for routing forms - Add NoUsersFoundFallbackActionType enum with CustomPageMessage and ExternalRedirectUrl options - Add noUsersFoundFallbackAction field to zodNonRouterRoute schema - Add NoUsersFoundFallback UI component in RouteBuilder for configuring fallback action - Update handleResponse to return noUsersFoundFallbackAction when no team members match - Add i18n translation keys for new UI strings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: change fallback to use same action options as main route - Replace noUsersFoundFallbackAction with fallbackAction that has same structure as main action - Add action dropdown and input fields to fallback attributes query builder section - Support Event redirect, External URL, and Custom page options in fallback - Remove separate NoUsersFoundFallback toggle component - Update handleResponse to return fallbackAction Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: ensure fallbackAction type is always defined in onChange handlers Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add guards for route.fallbackAction in onChange handlers Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: only return fallbackAction when no users are found Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: restructure fallback section to mirror main route structure Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: ensure backwards compatibility for existing routes with fallbackAttributesQueryValue Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: initialize fallbackAction with main event type for backwards compatibility Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: include fallbackAction in getRoutesToSave to persist changes Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use fallbackAction in getRoutedUrl when no team members found Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use i18n for fallback label and add tests for fallback action Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: do not trigger fallback action when CRM contact owner is found Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: prioritize fallbackAction over fallbackAttributesQueryValue When a route has a fallbackAction configured, skip the fallbackAttributesQueryValue to ensure the fallbackAction is triggered when no team members are found. This maintains backwards compatibility by only using fallbackAttributesQueryValue when fallbackAction is not set. Also treats teamMemberIdsMatchingAttributeLogic being null (routing couldn't run, e.g., missing orgId) the same as an empty array for the purpose of triggering the fallbackAction. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract RouteActionSelector shared component for action selection UI Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add i18n string for default custom page message Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add webhook trigger when routing form fallback route is hit - Add ROUTING_FORM_FALLBACK_HIT to WebhookTriggerEvents enum in Prisma schema - Add new trigger to routing-forms webhook triggers in constants - Add translation string for the new webhook trigger - Implement triggerFallbackWebhook function in formSubmissionUtils.ts - Call webhook trigger from handleResponse.ts when fallback action is used Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove webhook object from error log to avoid exposing secrets Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * revert: remove webhook trigger changes (to be moved to separate PR) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: only show fallback query builder when fallbackAction is explicitly set The fallback attributes query builder was being shown for new routes when fallbackAction was not set, causing an extra 'Add rule' button to appear. This broke e2e tests that relied on the button index. Now the fallback query builder is only shown when fallbackAction is explicitly set to EventTypeRedirectUrl, which happens after the route is saved and reloaded (via auto-initialization in useRoutes). Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use data-testid for attribute query builder selectors in e2e tests - Add data-testid='attributes-query-builder' to the main attributes query builder div - Update addAttributeRoutingRule and addAttributeRoutingRuleWithOperator to use the data-testid selector instead of nth() indices - This makes the tests more robust and independent of DOM structure changes Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: initialize fallbackAction for new routes in useCreateRoute hook - New routes created via useCreateRoute now initialize fallbackAction - This ensures new routes have a valid fallbackAction when saved - Matches the initialization logic for existing routes in useRoutes Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: initialize fallbackAction at save time when action is EventTypeRedirectUrl - When saving routes, if fallbackAction is undefined but action is EventTypeRedirectUrl, initialize fallbackAction from the main action - This handles the case where user creates a new route and changes action to an event type - Fixes e2e test failures where form save was failing due to undefined fallbackAction Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: initialize fallbackAction when main action changes to EventTypeRedirectUrl Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: only show fallback section when main action has valid event type selected Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: check for valid fallbackAction event type before preserving existing value Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Give more structure to main and fallback routes * Update comment * Rename fallbackAttributesQueryBuilder to matchingMembersFallbackRoute * Display custom event redirect input * fix: address Cubic AI review feedback for routing form fallback - Simplify getFallbackAction logic to use checkedFallback flag instead of manually parsing attributesQueryValue (confidence 9/10) - Add i18n translation for 'And connect with specific team members' string using t('connect_with_specific_team_members') (confidence 9/10) Co-Authored-By: unknown <> * fix: update getFallbackAction to use checkedFallback and handle missing orgId case - Use checkedFallback flag as primary indicator for triggering fallback action - Also handle edge case where attribute routing was configured but couldn't run due to missing orgId (teamMemberIdsMatchingAttributeLogic is null) - Update test to mock checkedFallback: true when expecting fallback action Co-Authored-By: unknown <> * Address UI comment * fix: Use fallbackAttributesQueryValue when fallback action is event redirect Only use fallbackAttributesQueryValue when: 1. fallbackAction is EventTypeRedirectUrl (attribute routing applies) 2. fallbackAction is not set (backwards compatibility) Skip it for CustomPageMessage and ExternalRedirectUrl fallback actions since attribute routing doesn't apply to those action types. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: correct JSX syntax error in matchingMembersFallbackRoute Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: extract getCustomSlug helper to deduplicate custom event type slug logic Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: only show fallback attribute filtering for teams under orgs Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: show fallback action for all team forms, gate attribute filtering on isOrganization Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
36713fc12e |
feat: add UTM parameter data to insights bookings CSV download (#27854)
* feat: add UTM parameter data to insights bookings CSV download Co-Authored-By: carina@cal.com <c.wollendorfer@me.com> * test: add UTM data tests and update snapshots for csvDataTransformer Co-Authored-By: carina@cal.com <c.wollendorfer@me.com> * fix: use Tracking relation for UTM data instead of flat fields on Booking Co-Authored-By: carina@cal.com <c.wollendorfer@me.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
681d191537 |
fix: ensure metadata key is always present in BOOKING_CREATED webhook payload (#27300)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: ali@cal.com <ali@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> |
||
|
|
dc3e681e01 |
fix: hide cancel/reschedule links in emails when disabled (#27637)
When disableCancelling or disableRescheduling is enabled on an event type, the confirmation email still showed non-functional cancel/reschedule links. The ManageLink email component already had correct conditional logic to hide these links, but two flows constructed the CalendarEvent manually without including the flags: the booking confirmation handler and the payment booking flow. This caused the flags to be undefined, which ManageLink interpreted as enabled. Added disableCancelling and disableRescheduling to the Prisma select and CalendarEvent object in both confirm.handler.ts and getBooking.ts. Closes #22906 |
||
|
|
f4abbb2de1 |
feat: refactor billing to strategy implemention (#27828)
* factory and statergie * chore: use correct method of DI * feat: add onchagne * add logic to HWM stat * add webhook resolver methods to each statergy * move seat tracking + webhooks over to own statergy * Move to factory base approach * move logic to correct class * rename create -> createByTeamId * fix: remove debug `true ||` overrides from IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED Remove accidentally committed debug overrides that short-circuited IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED to always be true, bypassing Stripe credential checks. This would break self-hosted instances without Stripe configured. Identified by cubic (https://cubic.dev) Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
3908cda372 |
perf: optimize getBusyTimesForLimitChecks with batched parallel queries (#27399)
* perf: optimize getBusyTimesForLimitChecks with batched parallel queries and raw SQL Co-Authored-By: udit@cal.com <udit222001@gmail.com> * test: add unit tests for getBusyTimesForLimitChecks batched query optimization Co-Authored-By: udit@cal.com <udit222001@gmail.com> * refactor: use Prisma findMany instead of raw SQL for better testability The batching (50 user chunks) and parallel execution (Promise.all) provide the main performance optimization. Using findMany instead of $queryRaw maintains the same performance characteristics while being compatible with prismock for testing. Co-Authored-By: udit@cal.com <udit222001@gmail.com> * fix: type error * refactor: add integration test * chore: remove log * chore: remove log * fix: avoid logging PII (userId) in busyTimes debug log Replace JSON.stringify(busyTimes) with count to avoid exposing userId in logs. Addresses Cubic AI review feedback (confidence 9/10). Co-Authored-By: unknown <> * chore: undo --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
ae31e05bec |
refactor: decouple @calcom/features from @calcom/trpc/server [2] (#27821)
* inviteMemberUtils in featuers * update imports * wip * wip * fix: remove PII from log statements in inviteMemberUtils - Remove email (usernameOrEmail) from error log in sendSignupToOrganizationEmail - Replace full user object with userId in debug log in sendExistingUserTeamInviteEmails Co-Authored-By: unknown <> * revert: restore original code for pure relocation (no formatting/logic changes) Co-Authored-By: benny@cal.com <sldisek783@gmail.com> * fix * fix: update test mocks to use new import path for inviteMemberUtils Co-Authored-By: benny@cal.com <sldisek783@gmail.com> * revert: restore original formatting in proration test and handleGroupEvents Co-Authored-By: benny@cal.com <sldisek783@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
431fbe44fc |
refactor: decouple @calcom/features from @calcom/trpc/server (#27751)
* make GetPublicEventInput * space * mv feature flags router to trpc * remove trpc imports * wip * mv OrgMembershipLookup to features * fix * fix * update * fix * revert formatting-only changes to improve PR reviewability Co-Authored-By: benny@cal.com <sldisek783@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
c0504993a6 |
feat: Write wrong assignment reports to the database (#27405)
* Add DB table for wrong assignment reports * When report is submitted write to the db * Prevent duplicate reportings * test: add migration and tests for WrongAssignmentReport table Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add unique constraint on bookingUid and booking access check for hasWrongAssignmentReport - Add @unique constraint on bookingUid in WrongAssignmentReport model to prevent duplicate reports at DB level - Add booking ownership check using BookingAccessService in hasWrongAssignmentReport endpoint - Refactor hasWrongAssignmentReport into separate handler and schema files Addresses Cubic AI review feedback on PR #27405 Co-Authored-By: unknown <> * feat: add routingFormId to WrongAssignmentReport and fix Select clearing - Add routingFormId field to WrongAssignmentReport model in schema.prisma - Add relation to App_RoutingForms_Form with SetNull on delete - Update WrongAssignmentReportRepository.createReport to accept routingFormId - Update BookingRepository.findByUidIncludeEventTypeAndTeamAndAssignmentReason to include routedFromRoutingFormReponse - Extract routingFormId from booking in reportWrongAssignment handler - Fix Select clearing issue: handle null case when user clears team member selection - Update tests to include routingFormId field Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: add migration for routingFormId in WrongAssignmentReport Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: address Udit's review comments - hasWrongAssignmentReport: throw UNAUTHORIZED error instead of returning false - reportWrongAssignment: add try-catch for Prisma P2002 unique constraint error - WrongAssignmentReport: add Team relation to teamId field - WrongAssignmentReportRepository: use findUnique instead of findFirst - reportWrongAssignment: use i18n for error messages Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: revert hasWrongAssignmentReport to return false when user lacks access Per PR checklist, hasWrongAssignmentReport should return { hasReport: false } when user lacks access to booking, not throw an error. This allows the UI to gracefully treat 'no access' as 'no report exists'. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: update mocks for findUnique and i18n in unit tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: throw UNAUTHORIZED in hasWrongAssignmentReport and squash migrations Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: change User relation onDelete from Cascade to SetNull in WrongAssignmentReport Address Hariom's review feedback: - Changed reportedById from Int to Int? (nullable) - Changed reportedBy relation from onDelete: Cascade to onDelete: SetNull - Updated migration SQL to reflect these changes This preserves wrong assignment reports even when the reporting user is deleted, as the data is still useful for analysis. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
c58e1f4ae5 |
feat: add filter segment validation with useActiveFiltersValidator hook and refactor DataTableProvider (#27208)
* feat: add activeFilters validator to DataTableProvider for filter segment validation - Add validateActiveFilters prop to DataTableProvider to filter out inaccessible values - Create useActiveFiltersValidator hook in bookings module to validate filter values - Integrate validator in bookings-view.tsx to validate userId, eventTypeId, teamId filters - Add comprehensive tests for the filter validation logic This provides a scalable solution for handling stale filter segment data by validating filters at the caller level using already-fetched accessible resource IDs. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: add type guard for eventTypeIds to ensure number[] type Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: delay segment filter application until validator is ready - Change useActiveFiltersValidator to return 'loading' state while data is fetching - Add pending segment handling in DataTableProvider to delay filter application - Expose isValidatorPending in context for consumers to disable queries - Update BookingListContainer to disable bookings query while validator is pending This prevents both errors from invalid filters and flash from fetching without filters. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: extract useSegmentManagement hook from DataTableProvider - Extract segment management logic into dedicated useSegmentManagement hook - Reduces DataTableProvider from ~500 lines to ~330 lines - Use NuqsSetter type to match nuqs useQueryState setter signatures - Maintains all existing functionality and type safety Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: export ActiveFiltersValidator types from data-table lib/types Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: import ActiveFiltersValidatorState from lib/types instead of hook Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * Revert "refactor: extract useSegmentManagement hook from DataTableProvider" This reverts commit dd588ac4cfb1d709c71d1f621994a7e8f3118f33. * refactor: split DataTableProvider into fine-grained context providers - Create DataTableStateContext for raw nuqs state management - Create DataTableSegmentContext for segment management - Create DataTableFiltersContext for filter manipulation - DataTableProvider now composes all providers with a bridge component - Maintains backward compatibility via combined DataTableContext Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: apply segment filters when navigating back to page with existing URL state When navigating back to a page with a segment already selected in the URL, the segment was being marked as selected but its filters were not being applied. This caused non-deterministic behavior where the filter segment would sometimes not take effect. The fix ensures that when segmentIdRaw exists in the URL and segments are fetched, we also call applySegmentFilters() (with validator timing support) instead of just setting the selectedSegment state. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: simplify filter validator to only handle multi-select These filters are always multi-select, so remove unnecessary single-select handling code and tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: cancel debounced search term on unmount Cancel the debounced search term on unmount/dependency change to avoid queued updates firing after the provider unmounts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
9424649d6f |
fix: add isCompanyEmail check to organization upgrade path (#27813)
Users with personal emails (e.g. Gmail) could enter the org creation flow at /settings/organizations/new but only hit the company email error at checkout, with no way to fix it from the form. After changing their email in settings, the cached store email was still used. - Add server-side isCompanyEmail check in page.tsx to redirect early - Add client-side check in CreateANewOrganizationForm with clear messaging - Always use current session email for non-admin users (not cached store) - Add tests for isCompanyEmail utility Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
edf9cd70dd |
fix: hide cal branding on platform workflows (#27385)
* fix: hide cal branding on platform workflows * refactor: rely on existing with platform variables code * revert: comment * fix e2e * chore: remove unit results |