main
100
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b539adf47b |
perf: add paginated host endpoints and repository methods for large teams (#28156)
* perf: add paginated host endpoints and delta-based host updates for event type editor - New cursor-paginated tRPC endpoints: getHostsForAssignment, getHostsForAvailability, searchTeamMembers, getChildrenForAssignment, exportHostsForWeights, getHostsWithLocationOptions - Delta-based host update support in update.handler.ts (pendingHostChanges, pendingChildrenChanges) - Repository additions: EventTypeRepository.findChildrenByParentId, HostRepository pagination, MembershipRepository.searchMembers, UserRepository.findByIdsWithPagination - Remove teamMembers from getEventTypeById initial load - Shared types: PendingHostChangesInput, PendingChildrenChangesInput, HostUpdateInput Co-Authored-By: unknown <> * fix: revert getTranslation import path to @calcom/i18n/server Co-Authored-By: unknown <> * fix: guard findChildrenByParentId to only run when pendingChildrenChanges exists Co-Authored-By: unknown <> * refactor: remove delta-based saving logic from backend PR Move pendingHostChanges/pendingChildrenChanges processing out of backend PR. These changes belong in the frontend PR since they are tightly coupled to the new frontend delta tracking components. Backend PR now contains only read-side optimizations: - Paginated host/children/member endpoints - Repository methods - getEventTypeById optimizations Co-Authored-By: unknown <> * refactor: move getEventTypeById changes to frontend PR for type safety Reverts getEventTypeById.ts, eventTypeRepository.ts, API v2 atom service, and platform libraries to main. The backend PR now only adds new infrastructure (paginated endpoints, repository methods, findChildrenByParentId) without changing existing return types. The getEventTypeById optimizations will be in the frontend PR instead. Co-Authored-By: unknown <> * refactor: move findTeamMembersMatchingAttributeLogic pagination to frontend PR The handler's return type change (adding nextCursor/total) breaks frontend files on main that expect the old shape. Moving these changes to the frontend PR keeps the backend PR purely additive. Co-Authored-By: unknown <> * fix: address Cubic review comments - empty array filter, stable total count, Set lookup Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix inifnite pagination loop Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: derive teamId from event type to prevent cross-team enumeration in exportHostsForWeights Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: restore doc comment to correct method hasAnyTeamMembershipByUserId Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use memberUserIds?.length to handle empty array filter in findHostsForAssignmentPaginated Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use explicit undefined check for memberUserIds to preserve empty array semantics Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: rename findChildrenByParentId to findChildrenByParentIdIncludeOwner The method selects owner with user profile data, so the name should reflect the included relation per Cal.com repository naming conventions. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: rename host repository methods to follow naming conventions - findHostsForAvailabilityPaginated -> findHostsPaginatedIncludeUser - findHostsForAssignmentPaginated -> findHostsPaginatedIncludeUserForAssignment Repository methods should not be named after use-cases (Availability/Assignment) but should describe what data they include, per Cal.com conventions. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: standardize slice(0, limit) across all pagination methods Replace slice(0, -1) with slice(0, limit) in all HostRepository pagination methods for consistency. slice(0, limit) is clearer about intent since it directly references the limit parameter. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * perf: only run total count query on first page in findByIdsWithPagination Wrap the count query in a !cursor guard so it only runs on the first page request, avoiding an extra database query on every scroll. Consistent with the hasFixedHosts optimization in HostRepository. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add integration tests for paginated host endpoints Tests cover getHostsForAvailability and getHostsForAssignment handlers: - Basic host retrieval - Cursor-based pagination across multiple pages - Host data fields (isFixed, priority, weight, name, email) - Search filtering by name - memberUserIds filtering (including empty array returning zero results) - hasFixedHosts only present on first page Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: extract EventTypeHostService and make TRPC handlers thin - Create EventTypeHostService at packages/features/host/services/ with all DTO types and business logic for 5 event-type-host endpoints - Refactor all 5 handlers to delegate to the service (thin handlers) - Add 17 unit tests covering DTO mapping, authorization, segment filtering, default values, and pagination pass-through Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * docs: add PR review context comments to EventTypeHostService Reference key review decisions from PR #28156 as code comments: - searchTeamMembers: membership check + repository delegation per @eunjae-lee - exportHostsForWeights: cross-team enumeration security fix per @hariombalhara - exportHostsForWeights: repository method instead of direct Prisma per @hariombalhara Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Revert "docs: add PR review context comments to EventTypeHostService" This reverts commit 1a1596e012e971f349f01339ce7572516042f1b3. * fix: use explicit undefined/null check for memberUserIds in searchMembers Fixes empty array semantics so memberUserIds: [] correctly returns zero results instead of all members. Now consistent with HostRepository pattern which uses 'memberUserIds !== undefined' instead of 'memberUserIds?.length'. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: replace TRPCError with ErrorWithCode in EventTypeHostService Per AGENTS.md rules, services in packages/features/ should use ErrorWithCode instead of TRPCError. The errorConversionMiddleware will automatically convert it to the appropriate TRPCError at the router layer. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Remove comment Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: remove unused teamId from exportHostsForWeights schema teamId was originally accepted by the schema when the handler used it directly. After the security fix to derive teamId server-side from the event type, the field became dead code. Removing it to keep the API contract accurate. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Abstract types * Update imports --------- 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> |
||
|
|
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> |
||
|
|
9d29055808 |
feat: replace admin API settings page with link to API docs (#28046)
* feat: replace admin API settings page with link to API docs Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: remove unused AdminAPIView component Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: rename admin API tab to API Docs Co-Authored-By: joe@cal.com <j.auyeung419@gmail.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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
82a4780145 |
feat: show routing trace dialog on assignment reason badge click (#27629)
* feat: show routing trace dialog on assignment reason badge click Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove duplicate RoutingTraceSheet rendering - Remove RoutingTraceSheet from BookingListItem.tsx to avoid duplicate rendering - Move RoutingTraceSheet in BookingActionsDropdown.tsx outside of isBookingFromRoutingForm condition - Use booking.assignmentReason.length > 0 condition for RoutingTraceSheet rendering - Remove unused isOpenRoutingTraceSheet getter and RoutingTraceSheet import from BookingListItem.tsx Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
b6916df671 |
test: add E2E tests for assignAllTeamMembers with attribute segment filters (#27680)
* test: add E2E tests for assignAllTeamMembers with attribute segment filters Cover all 4 attribute types (SINGLE_SELECT, MULTI_SELECT, TEXT, NUMBER) with booking flow verification plus edge cases (no match, all match). Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use auto-retrying assertion for no-match edge case test Replace flaky waitForTimeout(2000) + count check with Playwright's toHaveCount(0, { timeout: 15000 }) which retries until availability settles, preventing CI timing issues. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add exclusion tests for members without attribute assigned Add 4 new E2E tests covering the case where team members have no attribute assigned at all (not just a different value). Each attribute type (SINGLE_SELECT, MULTI_SELECT, TEXT, NUMBER) is tested to verify that members without the attribute are excluded from the booking pool. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add negation operator tests and restructure exclusion tests - Restructure 'Members without attribute assigned' tests: assign matching attribute to teammate-1 (not owner) so round-robin can't coincidentally pass when the bug exists - Add 4 negation operator tests (select_not_any_in, multiselect_not_some_in, not_equal for TEXT and NUMBER) that verify unassigned members should match negation filters. Marked with test.fail() as they confirm a known bug where getLogicResultForAllMembers skips members without attribute assignments entirely. - Add edge case: no members have attribute assigned -> no available slots Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: remove test.fail() markers from negation tests after bug fix Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
f819f6488e |
test: add E2E tests for routing form attribute conditions (#27681)
* feat: add comprehensive E2E tests for routing form attribute conditions Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: assert routedTeamMemberIds in URL instead of email in results Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: assert both routedTeamMemberIds in URL and email in results Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: include users without attribute assignments in exclusion condition evaluation Users with no attribute assigned were excluded from the team members list entirely, causing exclusion operators (not_equals, not_some_in, not_like, not_between, etc.) to never match them. Now getAttributesAssignmentData includes all team members, even those without attribute assignments. Also adds unit tests and E2E tests for this scenario. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: update getAttributes test to reflect new behavior for empty attributes Users without attribute assignments are now included with empty attributes so exclusion operators can match them. Updated test expectation accordingly. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: remove redundant usersWithAssignments code (fix already in _prepareAssignmentData from main) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
bc0ff0da8e |
fix: Exclusion attribute filter (#27669)
* Fix exclusion filter - include all team members * Fix display when members aren't saved in the DB * Update tests * Undo change to member switch |
||
|
|
9de621eb23 |
perf: replace O(n*m) array lookups with O(1) Map lookups in attribute routing (#27599)
* Replace n x m array functions with maps * test: add tests and benchmark for Map-based attribute lookup optimization Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add real-world enterprise scenario (14 attrs x 6,530 opts) to benchmark Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: remove benchmark file Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Rename function * Pass built maps to functions --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
8d79209e74 |
perf: Optmize DB queries around attribute routing (#27600)
* Replace n x m array functions with maps * feat: add attributeIds filter to findManyByOrgMembershipIds Allow filtering attribute-to-user assignments by specific attribute IDs. This enables querying only the attributes needed for a routing rule instead of fetching all attributes for all team members. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: extract attribute IDs from routing rules and filter queries Add extractAttributeIdsFromQueryValue helper to parse routing rules and identify which attributes are referenced. Pass these IDs through getAttributesAssignmentData to _queryAllData to only fetch the attribute assignments that are actually needed for evaluation. For a team with 785 members and 14 attributes, if a routing rule only references 2-3 attributes, this reduces the query from ~3500 rows to ~500 rows. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: use attribute filtering in findTeamMembersMatchingAttributeLogic Extract attribute IDs from the routing rules (main + fallback) and pass them to getAttributesForLogic to only fetch necessary data. This completes the optimization to reduce database load when evaluating routing rules that only reference a subset of attributes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: filter attributes query by attribute IDs Also filter the attributes query (not just attributeToUser assignments) by the attribute IDs referenced in routing rules. For a routing rule that references 2 out of 14 attributes with 6524 total options, this reduces: - Attributes fetched: 14 → 2 - Options fetched: 6524 → ~930 (proportional reduction) - Fewer regex replacements in replaceAttributeOptionIdsWithOptionLabel Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add comprehensive test coverage for attribute routing query optimization Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Revert "Replace n x m array functions with maps" This reverts commit 312eeb03bd1aba19760f093c798861a23b5fc66f. * fix: re-establish extractAttributeIdsFromQueryValue mock after resetAllMocks Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
f7381d1b6d |
Parallelize calls (#27486)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
c0f6a1b088 |
feat: add redirect option for non-routed visits to event types (#27468)
* feat: add redirect option for non-routing form bookings Add a new event type option that redirects to a custom URL when the booking was not made through a routing form (no cal.routingFormResponseId or cal.queuedFormResponseId query parameters). Changes: - Add redirectUrlOnNoRoutingFormResponse field to EventType schema - Add UI toggle in Advanced tab to configure the redirect URL - Implement redirect logic in bookingSuccessRedirect hook - Add translations for new UI strings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to test builder Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to BookerEvent type Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to getPublicEventSelect Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirect logic to getServerSideProps for non-routing form bookings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove redirectUrlOnNoRoutingFormResponse from booking success flow Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use 'in' operator for type narrowing on redirectUrlOnNoRoutingFormResponse Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: exclude redirectUrlOnNoRoutingFormResponse from test assertions Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: include redirectUrlOnNoRoutingFormResponse in test assertions and update description Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to mockUpdatedEventType Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove redirect logic from instant meetings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to EventTypeRepository select Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to form default values Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Reword string * fix: bust tRPC cache for redirectUrlOnNoRoutingFormResponse Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: guard redirect when rescheduleUid or bookingUid is present Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add redirectUrlOnNoRoutingFormResponse to dynamicEvent defaults Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add bookingUid guard to team getServerSideProps redirect Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
1d5228ef38 |
fix: skip duplicate CRM lookup when router already performed it (#27487)
When the routing form redirects to an event type, it now passes cal.crmLookupDone=true to indicate that the CRM contact owner lookup was already performed. The event type SSR checks for this flag and skips the duplicate CRM lookup, improving performance. This fixes the scenario where no CRM contact owner exists - previously the lookup would be performed twice (once in the router, once in SSR), but now it's only performed once. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
f91511b927 |
feat(salesforce): add field rules for round robin routing (#27402)
* feat(salesforce): add field rules for round robin skip - Add rrSkipFieldRules schema to appDataSchema in zod.ts - Implement applyFieldRules method in CrmService.ts for post-query filtering - Integrate field rules into getContacts method when forRoundRobinSkip=true - Add UI component for configuring field rules in EventTypeAppCardInterface - Add translations for new UI strings - Add comprehensive tests for field rules functionality Field rules allow users to specify conditions based on Salesforce record fields with 'ignore' or 'must_include' actions. Rules are evaluated with AND logic and gracefully handle missing fields by skipping those rules. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add children prop to Section.SubSectionHeader for field rules Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat(salesforce): add edit button for field rules Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat(salesforce): apply field rules to GraphQL results Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat(salesforce): add Redis caching for field validation Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix(salesforce): remove Redis caching to fix ERR_INVALID_THIS error - Removed Redis caching for field validation that was causing ERR_INVALID_THIS errors - Simplified field rules filtering to try query directly and skip filtering if it fails - Restored ensureFieldsExistOnObject method for other uses (write to record) - Field rules now gracefully handle invalid fields by skipping filtering Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: reformat getAttributes.ts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(salesforce): dynamically build GraphQL query for field rules with multi-edge iteration - Add buildDynamicAccountQuery to inject field rule fields into GraphQL query - Add passesFieldRules to evaluate ignore/must_include rules against UIAPI nodes - Validate field rules via getObjectFieldNames (in-memory + Redis cache) before branching - Remove applyFieldRulesToGraphQLRecords (used jsforce conn in GraphQL path) - Iterate all edges in Tiers 1 and 2 instead of only the first result - Rank Tier 3 accounts by contact count and fallback to next on field rule failure Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(salesforce): add field rule routing trace steps Add trace calls alongside field rule info logs for routing visibility: - fieldRulesValidated: records validation result in CrmService - fieldRuleFilteredRecord: records when account is filtered at each tier - fieldRuleEvaluated: records individual rule evaluation details - allRecordsFilteredByFieldRules: records when SOQL records are all filtered Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(salesforce): remove duplicate field validation and fix disabled Select options applyFieldRules now receives pre-validated rules from the early validation block instead of re-validating internally. Also adds the missing options prop to the disabled Select in the field rules UI. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(salesforce): include failed rule details in field rule trace steps Rename passesFieldRules to getFailingFieldRule so the caller receives the specific rule that caused filtering. The fieldRuleFilteredRecord trace step now includes failedRule with field, value, and action. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(salesforce): add GraphQL path tests for field rules Cover field rule filtering across all three GraphQL resolution tiers (contact, account, related contacts) with ignore and must_include actions, multi-edge fallback, case-insensitivity, and dynamic query selection. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Abstract new field rules settings * Reduce extra SOQL call * fix(salesforce): fix type errors in CrmService and GraphQL client - Add missing import for getRedisService from @calcom/features/di/containers/Redis - Fix ensureFieldsExistOnObject to properly return Field[] instead of incomplete function - Use Array.from() instead of spread operator for Set and Map iterators to fix downlevelIteration errors 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> |
||
|
|
7abbc8c22c |
feat: Routing trace presenter (#27372)
* feat: Add routing trace presenters Add domain-specific presenters (SalesforceRoutingTracePresenter, RoutingFormTracePresenter) that format trace steps into human-readable strings, and a core RoutingTracePresenter that delegates to them based on step domain. Includes unit tests for all presenters. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Add findByBookingUid to RoutingTraceRepository Add method to look up a routing trace by booking UID, needed by the routing trace presenter tRPC endpoint. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Add getRoutingTrace tRPC endpoint Expose routing trace data for a booking via viewer.bookings.getRoutingTrace. Tries the permanent RoutingTrace first (round robin bookings), then falls back to PendingRoutingTrace via the booking's form response relation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Add routing trace side sheet to booking list item Add a route icon button on booking list items that came from routing forms. Clicking it opens a side sheet displaying the full routing trace as human-readable steps. Adds RoutingTraceSheet component, store state, and translation key. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: Move routing trace action to dropdown menu Move the routing trace button from a standalone icon on the booking list item into the actions dropdown menu alongside "Report wrong assignment". The RoutingTraceSheet is now rendered from BookingActionsDropdown. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Improve routing trace UI and handle unnamed routes - Redesign RoutingTraceSheet with vertical timeline layout, domain badges, skeleton loading state, and millisecond timestamps - Use Salesforce app-store icon for Salesforce steps - Fall back to "Unnamed route" when route name is missing or matches route ID - Fix dropdown menu icon to git-merge (valid icon, unique in menu) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: Add tests for getRoutingTrace handler and findByBookingUid repository method Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Abstract functions * Fix build error * Add permission check * fix: Update getRoutingTrace tests to include ctx and mock BookingAccessService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
ca5d931165 |
fix: preserve UI config across iframe resets for element-click embeds (#27363)
* fix: preserve UI config across iframe resets for element-click embeds For element-click embeds, ui() is called before the iframe exists, and iframeReset() clears the queue when the modal is opened. This causes UI config like hideEventTypeDetails, cssVarsPerTheme, and styles to be lost. This fix stores UI config in a persistent property that survives iframe resets and applies it when the iframe becomes ready. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add assertion to verify hideEventTypeDetails config is applied in element-click embed Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add mergeUiConfig function and related tests for UI configuration merging - Introduced mergeUiConfig function to handle merging of UI configuration, specifically for cssVarsPerTheme at theme level. - Added comprehensive tests for mergeUiConfig covering various scenarios including merging themes, handling missing properties, and preserving existing configuration values. - Updated utils.test.ts to include tests for the new function and ensure correct behavior in different merging situations. * Fixes * Remove process import as it breaks embed.js * Simplify * fix name * fix name * fix: use forEach instead of for...of for URLSearchParams iteration 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: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
034fbd63f1 |
feat: Add CrmRoutingTraceService and SalesforceRoutingTraceService (#27318)
* Add DB schema * Init zod schema * Init RoutingTrace and PendingRoutingTrace repository interfaces * Create PrismaPendingRoutingTraceRepository * Init RoutingTraceService * Create RoutingTraceService container * User routing trace service in routing * Create RoutingTraceRepository and PrismaRoutingTraceRepoistory * Add findByFormResponseId and findByQueuedFormResponseId to PendingRoutingTraceRepository * Update DI containers * RoutingTraceService create process booking method * Use pending routing trace rather than URL params * Fix schema * Fix writing assignment reason for routed booking * Remove from service * Refactor RoutingTraceService to not rely on async local storage * Pass RoutingTraceService through routing call * Add attribute-logic-evaluated to routing trace step * Add routing trace to trpc endpoint * Add CRM routing trace step * Fix extracting routing trace to assignment reason * Add back CRM params to prevent refetching * test: Add unit tests for RoutingTraceService and repositories Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: Add missing mock for RoutingTraceService in getRoutedUrl tests Also fix pre-existing lint issues in the test file: - Add explicit types to mockForm and mockSerializableForm variables - Add explicit type to url parameter in mockContext - Replace 'as any' with 'as unknown as InstanceType<typeof UserRepository>' Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Link pending form submission to routing trace * Clean up * Add lookup field assignment reasons * Rename to PendingRoutingTrace * Add migration file * fix: Update RoutingTraceService tests to use assignmentReasonRepository mock - Add getStepsCount() method back to RoutingTraceService - Add queuedFormResponseId support to processForBooking method - Update tests to use mockAssignmentReasonRepository instead of prisma mock - Remove test for missing routingTraceRepository (all deps now required) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Remove PII (organizer email) from log payload in RoutingTraceService Addresses Cubic AI review feedback with confidence 9/10. Logging PII violates sensitive information logging rules. Co-Authored-By: unknown <> * Write field values at the time of routing * Write attributes used to route * feat: add CRM routing trace service Add CrmRoutingTraceService as a reusable wrapper around RoutingTraceService for CRM-specific tracing. Also adds CrmRoutingTraceServiceInterface type to support passing trace services through the CRM call chain. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add Salesforce routing trace infrastructure Add SalesforceRoutingTrace static class with 19 trace methods covering: - Account resolution (SOQL path): searching by website, contact domain - Lookup field queries - Owner lookups (contact, lead, account) - Validation and skip scenarios - GraphQL three-tier resolution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: wire CRM trace service through call chain Pass crmTrace parameter through the CRM call chain: - routerGetCrmContactOwnerEmail creates CrmRoutingTraceService - Passes to app booking form handlers and CRM round robin skip - CrmManager.getContacts accepts and forwards crmTrace - All handlers accept optional crmTrace parameter Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add trace instrumentation to Salesforce CRM service Instrument Salesforce CRM methods with routing trace steps: - getContacts: trace owner lookups for contact/lead/account - getAccountIdBasedOnEmailDomainOfContacts: trace website and domain searches - findUserEmailFromLookupField: trace lookup field queries - GetAccountRecordsForRRSkip (GraphQL): trace three-tier resolution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: rename SalesforceRoutingTrace to SalesforceRoutingTraceService Consistent naming with CrmRoutingTraceService. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add unit tests for CrmRoutingTraceService and SalesforceRoutingTraceService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: use AsyncLocalStorage for CRM routing trace Replace explicit crmTrace parameter passing with AsyncLocalStorage: - Add AsyncLocalStorage to RoutingTraceService with getCurrent() and runAsync() - Update SalesforceRoutingTraceService to auto-resolve trace from AsyncLocalStorage - Remove CrmRoutingTraceService wrapper (no longer needed) - Remove crmTrace parameter from all CRM method signatures - Wrap CRM operations in routingTraceService.runAsync() context This is cleaner than threading crmTrace through 5+ function layers. The trace context is available within the withReporting wrapper. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Use async local storage for `CrmRoutingTraceService` * fix: correct template literal syntax in RoutingTraceService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use narrowed eventTypeId variable in nested async function Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: update SalesforceRoutingTraceService tests to use AsyncLocalStorage API Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: rename crmTrace to crmRoutingTraceService 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> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Volnei Munhoz <volnei@cal.com> |
||
|
|
f536100224 |
feat: Add RoutingFormTrace (#27316)
* Add DB schema * Init zod schema * Init RoutingTrace and PendingRoutingTrace repository interfaces * Create PrismaPendingRoutingTraceRepository * Init RoutingTraceService * Create RoutingTraceService container * User routing trace service in routing * Create RoutingTraceRepository and PrismaRoutingTraceRepoistory * Add findByFormResponseId and findByQueuedFormResponseId to PendingRoutingTraceRepository * Update DI containers * RoutingTraceService create process booking method * Use pending routing trace rather than URL params * Fix schema * Fix writing assignment reason for routed booking * Remove from service * Refactor RoutingTraceService to not rely on async local storage * Pass RoutingTraceService through routing call * Add attribute-logic-evaluated to routing trace step * Add routing trace to trpc endpoint * Add CRM routing trace step * Fix extracting routing trace to assignment reason * Add back CRM params to prevent refetching * test: Add unit tests for RoutingTraceService and repositories Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: Add missing mock for RoutingTraceService in getRoutedUrl tests Also fix pre-existing lint issues in the test file: - Add explicit types to mockForm and mockSerializableForm variables - Add explicit type to url parameter in mockContext - Replace 'as any' with 'as unknown as InstanceType<typeof UserRepository>' Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Link pending form submission to routing trace * Clean up * Add lookup field assignment reasons * Rename to PendingRoutingTrace * Add migration file * fix: Update RoutingTraceService tests to use assignmentReasonRepository mock - Add getStepsCount() method back to RoutingTraceService - Add queuedFormResponseId support to processForBooking method - Update tests to use mockAssignmentReasonRepository instead of prisma mock - Remove test for missing routingTraceRepository (all deps now required) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Remove PII (organizer email) from log payload in RoutingTraceService Addresses Cubic AI review feedback with confidence 9/10. Logging PII violates sensitive information logging rules. Co-Authored-By: unknown <> * Write field values at the time of routing * Write attributes used to route * fix: Add CHECK constraint to ensure at least one response ID is set in routing trace tables Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Address PR review comments for routing trace feature - Add checkedFallback to routing trace step data (Comment 11) - Extract hardcoded domain/step strings to constants (Comment 13) - Use @default(now()) for createdAt in PendingRoutingTrace and RoutingTrace (Comment 15) - Add DEFAULT CURRENT_TIMESTAMP to migration for createdAt fields Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Use UTC-safe timezone expression for createdAt defaults in routing trace tables Addresses Cubic AI review feedback (confidence 9/10) to prevent timezone issues by using dbgenerated("timezone('UTC', now())") instead of bare now() for the createdAt fields in PendingRoutingTrace and RoutingTrace models. Co-Authored-By: unknown <> * fix: Align migration SQL with Prisma's expected timezone syntax Use 'UTC'::text cast in timezone() function to match Prisma's generated SQL. Co-Authored-By: unknown <> * fix: Revert migration SQL to match Prisma schema timezone syntax Remove ::text cast from timezone() function to match what Prisma generates from the schema definition. Co-Authored-By: unknown <> * fix: Use explicit ::text cast in timezone() for PostgreSQL compatibility PostgreSQL normalizes timezone('UTC', now()) to timezone('UTC'::text, now()) internally. Update both schema and migration to use the explicit cast to ensure they match and pass the migration check. Co-Authored-By: unknown <> * feat: Add RoutingFormTraceService domain class for type-safe routing traces - Create RoutingFormTraceService class with routeMatched, fallbackRouteUsed, attributeLogicEvaluated, and attributeFallbackUsed methods - Add ROUTING_FORM_STEPS constants - Add unit tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Integrate RoutingFormTraceService for routing form tracing - Add routingFormTraceService parameter to findMatchingRoute - Record route_matched or fallback_route_used step when route is selected - Use "Default Route" as name for form-level fallback routes - Refactor findTeamMembersMatchingAttributeLogic to use RoutingFormTraceService - Update handleResponse to accept and pass routingFormTraceService - Create RoutingFormTraceService in getRoutedUrl and pass through the flow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: Add test coverage for RoutingFormTraceService integration Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: Integrate RoutingFormTraceService for routing form tracing - Add routingFormTraceService parameter to findMatchingRoute - Record route_matched or fallback_route_used step when route is selected - Use "Default Route" as name for form-level fallback routes - Refactor findTeamMembersMatchingAttributeLogic to use RoutingFormTraceService - Update handleResponse to accept and pass routingFormTraceService - Create RoutingFormTraceService in getRoutedUrl and pass through the flow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Restore schema and migration from main branch Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Use correct parameter name routingFormTraceService in tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Use 'default_route' instead of 'Default Route' for fallback route name 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> |
||
|
|
620445d85f |
feat: Use RoutingTraceService to write assignment reasons (#27225)
* Add DB schema * Init zod schema * Init RoutingTrace and PendingRoutingTrace repository interfaces * Create PrismaPendingRoutingTraceRepository * Init RoutingTraceService * Create RoutingTraceService container * User routing trace service in routing * Create RoutingTraceRepository and PrismaRoutingTraceRepoistory * Add findByFormResponseId and findByQueuedFormResponseId to PendingRoutingTraceRepository * Update DI containers * RoutingTraceService create process booking method * Use pending routing trace rather than URL params * Fix schema * Fix writing assignment reason for routed booking * Remove from service * Refactor RoutingTraceService to not rely on async local storage * Pass RoutingTraceService through routing call * Add attribute-logic-evaluated to routing trace step * Add routing trace to trpc endpoint * Add CRM routing trace step * Fix extracting routing trace to assignment reason * Add back CRM params to prevent refetching * test: Add unit tests for RoutingTraceService and repositories Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: Add missing mock for RoutingTraceService in getRoutedUrl tests Also fix pre-existing lint issues in the test file: - Add explicit types to mockForm and mockSerializableForm variables - Add explicit type to url parameter in mockContext - Replace 'as any' with 'as unknown as InstanceType<typeof UserRepository>' Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Link pending form submission to routing trace * Clean up * Add lookup field assignment reasons * Rename to PendingRoutingTrace * Add migration file * fix: Update RoutingTraceService tests to use assignmentReasonRepository mock - Add getStepsCount() method back to RoutingTraceService - Add queuedFormResponseId support to processForBooking method - Update tests to use mockAssignmentReasonRepository instead of prisma mock - Remove test for missing routingTraceRepository (all deps now required) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Remove PII (organizer email) from log payload in RoutingTraceService Addresses Cubic AI review feedback with confidence 9/10. Logging PII violates sensitive information logging rules. Co-Authored-By: unknown <> * Write field values at the time of routing * Write attributes used to route * fix: Add CHECK constraint to ensure at least one response ID is set in routing trace tables Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Address PR review comments for routing trace feature - Add checkedFallback to routing trace step data (Comment 11) - Extract hardcoded domain/step strings to constants (Comment 13) - Use @default(now()) for createdAt in PendingRoutingTrace and RoutingTrace (Comment 15) - Add DEFAULT CURRENT_TIMESTAMP to migration for createdAt fields Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Use UTC-safe timezone expression for createdAt defaults in routing trace tables Addresses Cubic AI review feedback (confidence 9/10) to prevent timezone issues by using dbgenerated("timezone('UTC', now())") instead of bare now() for the createdAt fields in PendingRoutingTrace and RoutingTrace models. Co-Authored-By: unknown <> * fix: Align migration SQL with Prisma's expected timezone syntax Use 'UTC'::text cast in timezone() function to match Prisma's generated SQL. Co-Authored-By: unknown <> * fix: Revert migration SQL to match Prisma schema timezone syntax Remove ::text cast from timezone() function to match what Prisma generates from the schema definition. Co-Authored-By: unknown <> * fix: Use explicit ::text cast in timezone() for PostgreSQL compatibility PostgreSQL normalizes timezone('UTC', now()) to timezone('UTC'::text, now()) internally. Update both schema and migration to use the explicit cast to ensure they match and pass the migration check. Co-Authored-By: unknown <> * fix: Use CURRENT_TIMESTAMP for createdAt defaults (standard Cal.com pattern) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Use @default(now()) for createdAt in routing trace tables to match migration 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: Pedro Castro <pedro@cal.com> |
||
|
|
01ae6f1b9e |
fix: Salesforce tokens add token_lifetime (#27264)
* Create `getSalesforceTokenLifetime` * When connecting salesforce, add token_lifetime * Migrate token_lifetime and refetch if token expiry doesn't match * Add tests for Salesforce token lifetime feature - Add unit tests for getSalesforceTokenLifetime function - Add integration tests for token lifecycle management in CrmService - Fix type error in CrmService.ts by extracting refreshToken variable Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: re-trigger CI Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
b02af9ae53 | Update config with new id (#27197) | ||
|
|
3355fab4fb | feat: display assignment reason in organizer emails and booking single view (#27192) | ||
|
|
ec951cacad |
perf: getUserAvailability if dateRange is empty, early return (#26000)
* Early return if date range is empty * test: add tests for empty workingHours early return optimization 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: Volnei Munhoz <volnei@cal.com> |
||
|
|
2608e136cb |
fix: use appropriate error codes in chargeCard handler (#27013)
- Change 'Booking not found' to throw NOT_FOUND (404) instead of plain Error - Preserve ErrorWithCode for ChargeCardFailure to properly map to BAD_REQUEST (400) - Add specific error handling for 'User is not a member of the team' -> FORBIDDEN (403) - Add specific error handling for 'User ID is required' and 'No payment credential found' -> BAD_REQUEST (400) - Keep INTERNAL_SERVER_ERROR (500) only for actual server errors like 'Payment app not implemented' - Update test to expect ErrorWithCode to be re-thrown instead of wrapped in translated Error Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
463987c02d |
feat: add GitHub Action to check Prisma migrations match schema (#26897)
* feat: add GitHub Action to check Prisma migrations match schema Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: use CI_DATABASE_URL secret instead of hardcoded URL Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add test field to verify prisma migration check workflow Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use git-based check for prisma changes to bypass paths-filter issue Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add migration for test field to verify prisma migration check workflow Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: revert test field and migration after verifying workflow Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: split paths-filter into two actions to fix predicate-quantifier issue Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: rename has_companion to has-companion for consistent naming Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: update steps.filter references to steps.filter-exclusions Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
40a7f53d1f | Add IF NOT EXISTS (#26893) | ||
|
|
adb7509d96 | Rename migration file (#26889) | ||
|
|
6501743e5e |
feat: Add attribute sync logic from Salesforce (#26517)
* Add db schema * Add `CredentialRepository.findByTeamIdAndSlugs` * Add enabled app slugs for attribute syncing * Create repository for `IntegrationAttributeSync` * Create zod schemas * Create `AttributeSyncUserRuleOutputMapper` * Create `IntegrationAttributeSyncService` * Create DI contianer * Create trpc endpoints * Create page * Include team name in `CredentialRepository.findByTeamIdAndSlugs` * Update schema and relations * Update types and schemas * Add more methods to IntegrationAttributeSyncRepository * Add more services to `IntegrationAttributeSyncService` - getById - Init updateIncludeRulesAndMappings * Refactor `getTeams.handler` to use repository * Create `createAttributeSync` trpc endpoint * Create `updateAttributeSync` trpc endpoint * Add router to trpc * Create attribute sync child components * Pass custom actions to `FormCard` * Create `IntegrationAttributeSyncCard` * Pass inital props via server side * Fix prop * Only refetch on mutation * Fixes * Add form error when duplicate field and attribute combo * Add `updateTransactionWithRUleAndMappings` logic * Adjust zod schemas * Service add `updateIncludeRulesAndMappings` * Pass orgId from server to component * Rename types * Add deleteById method to repository * Add name to integrationAttributeSync * Add deleteById method to service * Rename method * Add deleteAttributeSync trpc endpoint * Make the IntegrationAttributeSyncCard a dummy component * test: add tests for IntegrationAttributeSync feature Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Move creating a attribute sync record to the service * Add i18n strings * Safe select credential in find by id and team * Fix default credentialId value in form * Update repository return types * Add i18n string * Make credentialId optional for form schema * Fix label * Add cascade deletes * Add verification that syncs belong to org * Create mapper for repository output * Type fixes * Remove old test file * Pass `attributeOptions` from parent to children * Infer types from zod schema * Type fixes * Type fix * Clean up * Add i18n strings * Remove unused file * Address feedback * Add migration file * Address feedback * Add validation for new integration values * Remove unused router * Move away from z.infer to z.ZodType * Clean up comments * Type fix * Type fixes * Type fix * fix: add passthrough to syncFormDataSchema to preserve extra fields Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove incorrect test that expected extra fields to pass through syncFormDataSchema Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add endpoint for SF to call * Create scratch org config * Create sf cli scripts * Create package logic * Update README * Remove unused file * Add indexes * Add aria label * Address feedback - consistent validation * Fix import paths for attribute types * Add `CredentialRepository.findByAppIdAndKeyValue` * Get credential by instance URL * Verify incoming sfdc orgId matches credential sfdc orgId * Rename method * Get user name integration syncs * refactor: change attributeSyncRules array to singular attributeSyncRule The database schema enforces a one-to-one relationship between IntegrationAttributeSync and AttributeSyncRule (via @unique constraint), and the UI only supports a single rule. This change makes the TypeScript type match the database schema and UI behavior. Changes: - Update IntegrationAttributeSync interface to use attributeSyncRule: AttributeSyncRule | null - Update mapper to return singular rule instead of wrapping in array - Update UI component to access sync.attributeSyncRule directly - Update IIntegrationAttributeSyncUpdateParams Omit type - Update tests to use attributeSyncRule: null instead of attributeSyncRules: [] Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Convert `membershipRepository.findAllByUserId` to a normal method * Add temp files to git ignore * Init and process team conditions * Biome formatting * Add `AttributeService` to get user attributes * Add DI container for AttributeService * AttributeSyncService evaluate attribute conditions * Create DI container for attributeSyncService * Return result for full condition * Evaluate if attribute sync should apply to user * Add method * Change PrismaAttributeOptionRepository to instance methods * Init AttributeSyncFieldMappingsService and process attribute syncs * Add AttributeSyncFieldMappingService DI container * Refactor orgId to organizationId * Add membership validation to sync field service * AttributeSYncFieldMappingService use repository methods * AttributeSyncFieldMappingService.processMappings add mapping logic * Add DI tokens * user-sync endpoint to implement attribute syncing * Validate team belongs to org for rule * test: add tests for AttributeSyncRuleService, AttributeSyncFieldMappingService, and AttributeService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Remove duplicate migration file * Fix merge conflict * fix: resolve type errors in attribute sync feature (#26814) Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Rename variable * Fix log typo * Fix file name * Add error logging * Use credential teamId * fix: add missing mockTeamRepository and team validation to tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix naming * Fix file import * Type fix * Pass MembershipRepository as a dep in AttributeSyncFieldMappingService * Type fix * fix: add mockMembershipRepository to AttributeSyncFieldMappingService tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Update packages/app-store/salesforce/api/user-sync.ts Add error handling when getting orgId from stored salesforce id Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fix: address Cubic code review comments - PrismaAttributeRepository: use nested select instead of include: true for options - CredentialRepository: use this.primaClient instead of global prisma, use select instead of include for relations - AttributeSyncFieldMappingService: optimize O(n*m) complexity with Map lookup for O(1) access Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix typo in CredentialRepository * Update README * Update sfdx-project * Add SFDC package tests * fix: improve Salesforce Apex test assertions to verify actual behavior - Enhanced CalComHttpMock to track HTTP callout invocations and capture requests - Updated UserUpdateHandlerTest to verify HTTP callouts are made with correct data - Updated CalComCalloutQueueableTest to verify HTTP callouts are made correctly - Replaced System.assert(true, ...) with meaningful assertions that verify: - Correct number of HTTP callouts - Request body contains expected fields - Request method is POST Addresses Cubic AI review feedback (confidence 9/10 issues only) Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> |
||
|
|
d04bc970e0 | Add missing migration (#26799) | ||
|
|
2664eb459b |
feat: Init Cal.com Salesforce package (#26330)
* Add db schema * Add `CredentialRepository.findByTeamIdAndSlugs` * Add enabled app slugs for attribute syncing * Create repository for `IntegrationAttributeSync` * Create zod schemas * Create `AttributeSyncUserRuleOutputMapper` * Create `IntegrationAttributeSyncService` * Create DI contianer * Create trpc endpoints * Create page * Include team name in `CredentialRepository.findByTeamIdAndSlugs` * Update schema and relations * Update types and schemas * Add more methods to IntegrationAttributeSyncRepository * Add more services to `IntegrationAttributeSyncService` - getById - Init updateIncludeRulesAndMappings * Refactor `getTeams.handler` to use repository * Create `createAttributeSync` trpc endpoint * Create `updateAttributeSync` trpc endpoint * Add router to trpc * Create attribute sync child components * Pass custom actions to `FormCard` * Create `IntegrationAttributeSyncCard` * Pass inital props via server side * Fix prop * Only refetch on mutation * Fixes * Add form error when duplicate field and attribute combo * Add `updateTransactionWithRUleAndMappings` logic * Adjust zod schemas * Service add `updateIncludeRulesAndMappings` * Pass orgId from server to component * Rename types * Add deleteById method to repository * Add name to integrationAttributeSync * Add deleteById method to service * Rename method * Add deleteAttributeSync trpc endpoint * Make the IntegrationAttributeSyncCard a dummy component * test: add tests for IntegrationAttributeSync feature Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Move creating a attribute sync record to the service * Add i18n strings * Safe select credential in find by id and team * Fix default credentialId value in form * Update repository return types * Add i18n string * Make credentialId optional for form schema * Fix label * Add cascade deletes * Add verification that syncs belong to org * Create mapper for repository output * Type fixes * Remove old test file * Pass `attributeOptions` from parent to children * Infer types from zod schema * Type fixes * Type fix * Clean up * Add i18n strings * Remove unused file * Address feedback * Add migration file * Address feedback * Add validation for new integration values * Remove unused router * Move away from z.infer to z.ZodType * Clean up comments * Type fix * Type fixes * Type fix * fix: add passthrough to syncFormDataSchema to preserve extra fields Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove incorrect test that expected extra fields to pass through syncFormDataSchema Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add endpoint for SF to call * Create scratch org config * Create sf cli scripts * Create package logic * Update README * Remove unused file * Add indexes * Add aria label * Address feedback - consistent validation * Fix import paths for attribute types * refactor: change attributeSyncRules array to singular attributeSyncRule The database schema enforces a one-to-one relationship between IntegrationAttributeSync and AttributeSyncRule (via @unique constraint), and the UI only supports a single rule. This change makes the TypeScript type match the database schema and UI behavior. Changes: - Update IntegrationAttributeSync interface to use attributeSyncRule: AttributeSyncRule | null - Update mapper to return singular rule instead of wrapping in array - Update UI component to access sync.attributeSyncRule directly - Update IIntegrationAttributeSyncUpdateParams Omit type - Update tests to use attributeSyncRule: null instead of attributeSyncRules: [] Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: implement FeatureOptInService (#25805) * feat: implement FeatureOptInService WIP * clean up * feat: consolidate feature repositories and add updateFeatureForUser - Implement updateFeatureForUser in FeaturesRepository (similar to updateFeatureForTeam) - Move getUserFeatureState and getTeamFeatureState from PrismaFeatureOptInRepository to FeaturesRepository - Update FeatureOptInService to use only FeaturesRepository - Add setUserFeatureState and setTeamFeatureState methods to FeatureOptInService - Update _router.ts to remove PrismaFeatureOptInRepository usage - Remove PrismaFeatureOptInRepository.ts and FeatureOptInRepositoryInterface.ts - Update features.repository.interface.ts and features.repository.mock.ts - Add integration tests for updateFeatureForUser, getUserFeatureState, getTeamFeatureState - Update service.integration-test.ts to use FeaturesRepository Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: rename updateFeatureForUser to setUserFeatureState Rename to match the convention used for setTeamFeatureState Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: return FeatureState type from getUserFeatureState and getTeamFeatureState * fix integration tests * clean up logics * update services and router * refactor: change getUserFeatureState and getTeamFeatureState to accept featureIds array - Renamed getUserFeatureState to getUserFeatureStates - Renamed getTeamFeatureState to getTeamFeatureStates - Changed parameter from featureId: string to featureIds: string[] - Changed return type from FeatureState to Record<string, FeatureState> - Updated FeatureOptInService to use the new batch methods - Added tests for querying multiple features in a single call - Optimized listFeaturesForTeam to fetch all feature states in one query Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * feat: add getFeatureStateForTeams for batch querying multiple teams - Added getFeatureStateForTeams method to query a single feature across multiple teams in one call - Updated FeatureOptInService.resolveFeatureStateAcrossTeams to use the new batch method - Replaces N+1 queries with a single database query for team states - Added comprehensive integration tests for the new method Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: combine org and team state queries into single call - Include orgId in the teamIds array passed to getFeatureStateForTeams - Extract org state and team states from the combined result - Reduces database queries from 3 to 2 in resolveFeatureStateAcrossTeams Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: use team.isOrganization and clarify computeEffectiveState comment Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: use MembershipRepository.findAllByUserId with isOrganization Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * feat: add featureId validation using isOptInFeature type guard Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * less queries * add fallback value * fix type error * move files * add autoOptInFeatures column * use autoOptInFeatures flag within FeatureOptInService * add setUserAutoOptIn and setTeamAutoOptIn * fix computeEffectiveState logic * rewrite computeEffectiveState * clean up integration tests * clean up in afterEach * fix type error * refactor: use FeaturesRepository methods instead of direct Prisma calls Replace all manual userFeatures and teamFeatures Prisma operations with the new setUserFeatureState and setTeamFeatureState repository methods. Changes include: - Admin handlers (assignFeatureToTeam, unassignFeatureFromTeam) - Test fixtures and integration tests - Playwright fixtures - Development scripts This ensures consistent feature flag management through the repository pattern and supports the new tri-state semantics (enabled/disabled/inherit). Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * clean up * fix the logic * extract some logic into applyAutoOptIn() * remove wrong code * refactor: convert setUserFeatureState and setTeamFeatureState to object params with discriminated union - Convert multiple positional parameters to single object parameter - Use discriminated union types: assignedBy required for enabled/disabled, omitted for inherit - Update all callers across repository, service, handlers, fixtures, and tests * fix type error * use Promise.all * fix --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Prevent duplicate field and attribute mappings * Add validation that attribute belongs to the org * fix: address Cubic AI review feedback - Add @@index([credentialId]) to IntegrationAttributeSync model for efficient cascade deletes and credential-based queries (confidence: 9/10) - Fix translation key from 'credential_required' to 'attribute_sync_credential_required' to match existing locale definition (confidence: 10/10) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: address remaining cubic review feedback - RuleBuilder.tsx: Use unique IDs for React keys instead of array index to prevent reconciliation bugs when removing conditions - updateAttributeSync.handler.ts: Add early organization check before service calls for consistency - createAttributeSync.handler.ts: Add CredentialNotFoundError class for type-safe error handling instead of string matching - IntegrationAttributeSyncService.test.ts: Replace expect.fail() with proper Vitest rejects.toSatisfy() pattern Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Pull test file from main * fix: address Cubic AI review feedback (confidence >= 9/10) - Remove sensitive fields (email, changedFields) from logging in user-sync.ts - Rename scratch-org:open to scratch-org:start in package.json to match README Co-Authored-By: unknown <> * Update README --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
8dbe3848e7 |
feat: Create Integration Attribute Sync records (#26007)
* Add db schema * Add `CredentialRepository.findByTeamIdAndSlugs` * Add enabled app slugs for attribute syncing * Create repository for `IntegrationAttributeSync` * Create zod schemas * Create `AttributeSyncUserRuleOutputMapper` * Create `IntegrationAttributeSyncService` * Create DI contianer * Create trpc endpoints * Create page * Include team name in `CredentialRepository.findByTeamIdAndSlugs` * Update schema and relations * Update types and schemas * Add more methods to IntegrationAttributeSyncRepository * Add more services to `IntegrationAttributeSyncService` - getById - Init updateIncludeRulesAndMappings * Refactor `getTeams.handler` to use repository * Create `createAttributeSync` trpc endpoint * Create `updateAttributeSync` trpc endpoint * Add router to trpc * Create attribute sync child components * Pass custom actions to `FormCard` * Create `IntegrationAttributeSyncCard` * Pass inital props via server side * Fix prop * Only refetch on mutation * Fixes * Add form error when duplicate field and attribute combo * Add `updateTransactionWithRUleAndMappings` logic * Adjust zod schemas * Service add `updateIncludeRulesAndMappings` * Pass orgId from server to component * Rename types * Add deleteById method to repository * Add name to integrationAttributeSync * Add deleteById method to service * Rename method * Add deleteAttributeSync trpc endpoint * Make the IntegrationAttributeSyncCard a dummy component * test: add tests for IntegrationAttributeSync feature Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Move creating a attribute sync record to the service * Add i18n strings * Safe select credential in find by id and team * Fix default credentialId value in form * Update repository return types * Add i18n string * Make credentialId optional for form schema * Fix label * Add cascade deletes * Add verification that syncs belong to org * Create mapper for repository output * Type fixes * Remove old test file * Pass `attributeOptions` from parent to children * Infer types from zod schema * Type fixes * Type fix * Clean up * Add i18n strings * Remove unused file * Address feedback * Add migration file * Address feedback * Add validation for new integration values * Remove unused router * Move away from z.infer to z.ZodType * Clean up comments * Type fix * Type fixes * Type fix * fix: add passthrough to syncFormDataSchema to preserve extra fields Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: remove incorrect test that expected extra fields to pass through syncFormDataSchema Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add indexes * Add aria label * Address feedback - consistent validation * Fix import paths for attribute types * refactor: change attributeSyncRules array to singular attributeSyncRule The database schema enforces a one-to-one relationship between IntegrationAttributeSync and AttributeSyncRule (via @unique constraint), and the UI only supports a single rule. This change makes the TypeScript type match the database schema and UI behavior. Changes: - Update IntegrationAttributeSync interface to use attributeSyncRule: AttributeSyncRule | null - Update mapper to return singular rule instead of wrapping in array - Update UI component to access sync.attributeSyncRule directly - Update IIntegrationAttributeSyncUpdateParams Omit type - Update tests to use attributeSyncRule: null instead of attributeSyncRules: [] Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: implement FeatureOptInService (#25805) * feat: implement FeatureOptInService WIP * clean up * feat: consolidate feature repositories and add updateFeatureForUser - Implement updateFeatureForUser in FeaturesRepository (similar to updateFeatureForTeam) - Move getUserFeatureState and getTeamFeatureState from PrismaFeatureOptInRepository to FeaturesRepository - Update FeatureOptInService to use only FeaturesRepository - Add setUserFeatureState and setTeamFeatureState methods to FeatureOptInService - Update _router.ts to remove PrismaFeatureOptInRepository usage - Remove PrismaFeatureOptInRepository.ts and FeatureOptInRepositoryInterface.ts - Update features.repository.interface.ts and features.repository.mock.ts - Add integration tests for updateFeatureForUser, getUserFeatureState, getTeamFeatureState - Update service.integration-test.ts to use FeaturesRepository Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: rename updateFeatureForUser to setUserFeatureState Rename to match the convention used for setTeamFeatureState Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: return FeatureState type from getUserFeatureState and getTeamFeatureState * fix integration tests * clean up logics * update services and router * refactor: change getUserFeatureState and getTeamFeatureState to accept featureIds array - Renamed getUserFeatureState to getUserFeatureStates - Renamed getTeamFeatureState to getTeamFeatureStates - Changed parameter from featureId: string to featureIds: string[] - Changed return type from FeatureState to Record<string, FeatureState> - Updated FeatureOptInService to use the new batch methods - Added tests for querying multiple features in a single call - Optimized listFeaturesForTeam to fetch all feature states in one query Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * feat: add getFeatureStateForTeams for batch querying multiple teams - Added getFeatureStateForTeams method to query a single feature across multiple teams in one call - Updated FeatureOptInService.resolveFeatureStateAcrossTeams to use the new batch method - Replaces N+1 queries with a single database query for team states - Added comprehensive integration tests for the new method Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: combine org and team state queries into single call - Include orgId in the teamIds array passed to getFeatureStateForTeams - Extract org state and team states from the combined result - Reduces database queries from 3 to 2 in resolveFeatureStateAcrossTeams Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: use team.isOrganization and clarify computeEffectiveState comment Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: use MembershipRepository.findAllByUserId with isOrganization Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * feat: add featureId validation using isOptInFeature type guard Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * less queries * add fallback value * fix type error * move files * add autoOptInFeatures column * use autoOptInFeatures flag within FeatureOptInService * add setUserAutoOptIn and setTeamAutoOptIn * fix computeEffectiveState logic * rewrite computeEffectiveState * clean up integration tests * clean up in afterEach * fix type error * refactor: use FeaturesRepository methods instead of direct Prisma calls Replace all manual userFeatures and teamFeatures Prisma operations with the new setUserFeatureState and setTeamFeatureState repository methods. Changes include: - Admin handlers (assignFeatureToTeam, unassignFeatureFromTeam) - Test fixtures and integration tests - Playwright fixtures - Development scripts This ensures consistent feature flag management through the repository pattern and supports the new tri-state semantics (enabled/disabled/inherit). Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * clean up * fix the logic * extract some logic into applyAutoOptIn() * remove wrong code * refactor: convert setUserFeatureState and setTeamFeatureState to object params with discriminated union - Convert multiple positional parameters to single object parameter - Use discriminated union types: assignedBy required for enabled/disabled, omitted for inherit - Update all callers across repository, service, handlers, fixtures, and tests * fix type error * use Promise.all * fix --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * Prevent duplicate field and attribute mappings * Add validation that attribute belongs to the org * fix: address Cubic AI review feedback - Add @@index([credentialId]) to IntegrationAttributeSync model for efficient cascade deletes and credential-based queries (confidence: 9/10) - Fix translation key from 'credential_required' to 'attribute_sync_credential_required' to match existing locale definition (confidence: 10/10) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: address remaining cubic review feedback - RuleBuilder.tsx: Use unique IDs for React keys instead of array index to prevent reconciliation bugs when removing conditions - updateAttributeSync.handler.ts: Add early organization check before service calls for consistency - createAttributeSync.handler.ts: Add CredentialNotFoundError class for type-safe error handling instead of string matching - IntegrationAttributeSyncService.test.ts: Replace expect.fail() with proper Vitest rejects.toSatisfy() pattern Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Pull test file from main --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Eunjae Lee <hey@eunjae.dev> |
||
|
|
d5c2212c41 |
chore: Add logging eventId from Stripe webhook (#26623)
* Add loggin * fix: use established logger instead of console.log for Stripe webhook eventId Co-Authored-By: unknown <> * fix: remove sensitive stripe-signature header from error logs Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
08edd4f361 |
chore: Add logging to msteams (#23684)
* Add logging * fix: Add response status checking to MS Teams adapter error handling - Add response.ok checks before parsing JSON in createMeeting and updateMeeting - Remove console.log statements that could leak credential information - Ensure error handling matches original handleErrorsRaw behavior for tests Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix logs * Revert "fix: Add response status checking to MS Teams adapter error handling" This reverts commit 35820d21e1a54d9e04d83fd5f53584d64a5459b6. * fix: Add response status checking to MS Teams adapter error handling - Check response.ok before parsing JSON in createMeeting and updateMeeting - Re-throw HttpError instances instead of wrapping them in catch blocks - This ensures HTTP errors (like 500) are properly propagated Co-Authored-By: unknown <> * fix: Correct log message in updateMeeting to say 'updating' instead of 'creating' Co-Authored-By: unknown <> --------- 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> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> |
||
|
|
f6d3b11582 |
refactor: Membership.findByUserIdAndTeamId to instance method (#26628)
* Make and instance method * Refactor files * fix: update MembershipRepository mocks to use vi.hoisted() for proper hoisting Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
04e447058c |
fix: Add copy-app-store-static to docker file (#26565)
* Add `copy-app-store-static` step * Biome formatting |
||
|
|
0cf5de5ef8 |
fix: log Zoom token refresh errors at ERROR level (#26547)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
8b5d9202db |
refactor: convert PrismaAttributeToUserRepository to accept Prisma as dependency (#26515)
* refactor: convert PrismaAttributeToUserRepository to accept Prisma as dependency Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use Prisma types from generated client instead of custom types Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
048a9b04fa |
chore: add logging in next-auth (#26404)
* Add logging in next-auth * Add logging at other return |
||
|
|
2b61bddf7b |
feat: add completed onboarding column to organization members table (#25582)
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> Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> |
||
|
|
8ac3d423cb |
fix: When checking email domains to block replace includes with endsWith (#26166)
* Lint fixes * Replace `includes` with `endsWith` * Fix typo * test: add tests for email domain blocking fix Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
3a59cd41cc |
feat: add toggle to opt out of booking title translation in instant meetings (#25547)
* feat: add toggle to opt out of booking title translation in instant meetings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add autoTranslateTitleEnabled to test builder Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: respect autoTranslateTitleEnabled toggle in InstantBookingCreateService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: fetch autoTranslateTitleEnabled directly in InstantBookingCreateService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: rename autoTranslateTitleEnabled to autoTranslateInstantMeetingTitleEnabled - Renamed field to clarify it only applies to instant meeting title translation - Moved Prisma query to EventTypeRepository.findInstantMeetingConfigById() - Removed title translation logic from update.handler.ts (flag only controls instant meeting title) - Updated all references across the codebase - Added new i18n translation keys for the renamed field Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add autoTranslateInstantMeetingTitleEnabled to test destructuring patterns Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use Prisma.TeamCreateInput type for metadata in test helper Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add autoTranslateInstantMeetingTitleEnabled to mockUpdatedEventType in test Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: use generic findByIdMinimal instead of business-specific method - Add autoTranslateInstantMeetingTitleEnabled to eventTypeSelect constant - Remove findInstantMeetingConfigById from EventTypeRepository - Update InstantBookingCreateService to use findByIdMinimal Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: remove autoTranslateInstantMeetingTitleEnabled from eventTypeSelect (not needed for findByIdMinimal) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: add autoTranslateInstantMeetingTitleEnabled to event type form defaults - Rename shouldTranslateTitle to shouldAutoTranslateInstantMeetingTitle for clarity - Add autoTranslateInstantMeetingTitleEnabled to findById and findByIdForOrgAdmin selects - Add autoTranslateInstantMeetingTitleEnabled to useEventTypeForm defaultValues Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: only update autoTranslateInstantMeetingTitleEnabled when explicitly provided Fixes issue where omitting the field in update requests would overwrite the saved opt-out setting with the default value (true). Now the field is only included in the update payload when explicitly provided. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
dc44825ce5 |
fix: prevent overwriting existing event type values with undefined (#25624)
When updating an event type, fields like autoTranslateDescriptionEnabled and disableGuests were being overwritten with false/default values even when they weren't explicitly provided in the update request. Changes: - autoTranslateDescriptionEnabled: Only set when explicitly provided (not undefined) to avoid overwriting existing true values with false - disableGuests: Only set when bookingFields is explicitly provided, since it's derived from the guests field in bookingFields Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
0605572969 |
fix: Log detailed error in getConnectedCalendar (#25338)
* Log error * Reverse sent error message changes --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> |
||
|
|
f33edb2b99 |
feat: Generate email workflow payload at time of sending (#25446)
* wip * wip * feature: Booking Tasker without DI yet * feature: Booking Tasker with DI * fix type check 1 * fix type check 2 * fix * comment booking tasker for now * fix: DI regularBookingService api v2 * fix: convert trigger.dev SDK imports to dynamic imports to fix unit tests The unit tests were failing because BookingEmailAndSmsTriggerTasker.ts had static imports of trigger files that depend on @trigger.dev/sdk. This caused Vitest to try to resolve the SDK at module load time, even though it should be optional. Changed all imports in BookingEmailAndSmsTriggerTasker.ts from static to dynamic (using await import()) so the trigger files are only loaded when the tasker methods are actually called, not at module load time during tests. This fixes the 'Failed to load url @trigger.dev/sdk' errors that were causing 28+ test failures. Co-Authored-By: morgan@cal.com <morgan@cal.com> * fix unit tests * keep inline smsAndEmailHandler.send calls * chore: add team feature flag * add satisfies ModuleLoader * fix type check app flags * move trigger in feature * fix: add trigger.dev prisma generator * fix: email app statuses * fix: CalEvtBuilder unit test * chore: improvements, schema, config, retry * fixup! chore: improvements, schema, config, retry * chore: cleanup code * chore: cleanup code * chore: clean code and give full payload * remove log * add booking notifications queue * add attendee phone number for sms * bump trigger to 4.1.0 * add missing booking seat data in attendee * update config * fix logger regular booking service * fix: prisma as external deps of trigger * fix yarn.lock * revert change to example app booking page * fix: resolve circular dependencies and improve cold start performance in trigger tasks - Convert BookingRepository import to type-only in CalendarEventBuilder.ts to eliminate circular dependency risk - Convert EventNameObjectType, CalendarEvent, and JsonObject imports to type-only in BookingEmailAndSmsTaskService.ts - Use dynamic imports in all trigger notification tasks (confirm, request, reschedule, rr-reschedule) to reduce cold start time - Move heavy imports (BookingEmailSmsHandler, BookingRepository, prisma, TriggerDevLogger, BookingEmailAndSmsTaskService) inside run functions - Eliminates module-level prisma import which violates repo guidelines and adds cold start overhead - Reduces initial module dependency graph by deferring heavy imports (email templates, workflows, large repositories) until task execution Co-Authored-By: morgan@cal.com <morgan@cal.com> * fix: improve cold start performance in reminderScheduler with dynamic imports - Remove module-level prisma import (violates 'No prisma outside repositories' guideline) - Use dynamic imports for UserRepository (1,168 lines) - only loaded when needed in EMAIL_ATTENDEE action - Use dynamic imports for twilio provider (386 lines) - only loaded in cancelScheduledMessagesAndScheduleEmails - Use dynamic imports for all manager functions by action type: - scheduleSMSReminder (387 lines) - loaded only for SMS actions - scheduleEmailReminder (459 lines) - loaded only for Email actions - scheduleWhatsappReminder (266 lines) - loaded only for WhatsApp actions - scheduleAIPhoneCall (478 lines) - loaded only for AI phone call actions - Use dynamic imports for sendOrScheduleWorkflowEmails in cancelScheduledMessagesAndScheduleEmails - Significantly reduces cold start time by deferring heavy module loading until execution paths need them - Eliminates module-level prisma import that violated repository pattern guidelines Co-Authored-By: morgan@cal.com <morgan@cal.com> * fix: improve cold start performance in BookingEmailSmsHandler with dynamic imports - Remove module-level imports of all email-manager functions (653 LOC + 30+ email templates) - Add dynamic imports in each method (_handleRescheduled, _handleRoundRobinRescheduled, _handleConfirmed, _handleRequested, handleAddGuests) - Defer heavy email-manager loading until method execution - Verified no circular dependencies between email-manager and bookings - Significantly reduces cold start time for RegularBookingService and BookingEmailAndSmsTaskService Co-Authored-By: morgan@cal.com <morgan@cal.com> * fix: use dynamic imports * update yarn lock * code review * trigger config project ref in env * update yarn lock * add .env.example trigger variables * add .env.example trigger variables * fix: cleanup error handling and loggin * fix: trigger config from env * fix: small typo fix * fix: ai review comments * fix: ai review comments * ai review * Add `create` on `WorkflowReminderRepository` * `sendWorkflowEmails` tasker to accept lazy payload * Add `scheduleLazyEmailWorkflow` to `WorkflowService * Process scheduled date in `scheduleLazyEmailWorkflow` * Type fixes * Use `WorkflowService` to schedule * Refactor `scheduleEmailReminderForEvt` to use `WorkflowService.processWorkflowScheduledDate` * Pass seat reference to lazy scheduled workflow reminder * Refactor `WorkflowReminderRepository` to accept prisma as constructor * Abstract `FormSubmissionData` type * Abstract select statement and add get by uid to `BookingRepository` * Add `FormSubmissionData` type * Add `findByIdIncludeStepAndWorkflow` to `WorkflowReminderRepository` * Tasker payload to accept `workflowReminderId` * Create `BookingSeatRepository` * Write `workflowReminderId` to tasker payload * Add `generateCommonScheduleFunctionParams` to `WorkflowService` * Init * Use services in tasker * Abstract types * In reminderScheduler use workflowService to generate common params * Type fix * Return params from emailWorkflowService.generateParametersToBuildEmailWorkflowContent * Use emailWorkflowService to generate params * Abstract types * Generate email content and send in EmailWorkflowService * Move check to caller * Use EmailWorkflowService to generate email payload in emailReminderManager * Fix initalizing repository * Use evt.videoCallData first before the booking metadata * Only get non-deleted references to build calendar event * Remove check for videoCallData.id * Dynamic import credit service * BookingRepository.getByUid to only return what we need from attendee * Type fixes * test: Add comprehensive tests for lazy email workflow generation and fix broken tests - Fix prisma mocks in sms-manager.test.ts and outOfOfficeCreateOrUpdate.handler.test.ts to export both 'default' and named 'prisma' exports - Add EmailWorkflowService.test.ts with 4 tests for error handling paths - Add sendWorkflowEmails.test.ts with 7 tests for schema validation and email sending - Add tests to WorkflowService.test.ts for scheduleLazyEmailWorkflow, processWorkflowScheduledDate, and generateCommonScheduleFunctionParams methods Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Write `seatReferenceUid` * Return promise * Fix log * Change to `Promise.allSettled` * Type fix * Fix failing test * fix: reorder workflow step checks to fix test failure The test 'should throw error if workflow step not found on reminder' was failing because the code checked workflowStep.verifiedAt before checking if workflowStep exists. When workflowStep is null, this caused the error message to include 'undefined' instead of the expected workflow step id. Fixed by reordering the checks: 1. First check if workflowStep exists 2. Then check if workflowStep.verifiedAt exists Also updated the test expectation to match the correct error message. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: hbjORbj <sldisek783@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> |
||
|
|
2b2bf36703 |
fix: Grab booking organizer credentials when team admins request reschedule (#24645)
* Change arg name from `bookingUId` to `bookingUid` * Lint fix * Use `BookingRepository` to find booking to reschedule * Move early return further up if no booking is found * Use `PermissionCheckService` if request rescheduling a team booking * Remove redundent check * Remove redundent eventType query * Using `BookingRepository` to update the booking to rescheduled * Update type in `getUsersCredentialsIncludeServiceAccountKey` to only require params that are required * Get booking organizer credentials * Type fixes * test: Add tests for team admin request reschedule with organizer credentials - Add test for team admin requesting reschedule with proper permissions - Add test verifying organizer's credentials are used (not requester's) - Add test for team member without permissions (should fail) These tests cover the fix in PR #24645 which ensures that when a team admin requests a reschedule, the booking organizer's credentials are used to delete calendar events instead of the requester's credentials. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Address code review comments for request reschedule - Change user: true to user: { select: { id, email } } to only fetch required fields - Change eventType include to select with explicit fields including teamId - Remove sensitive information (user object, cancellationReason) from debug log - All integration tests passing locally Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Type fix * Remove businesss logic references from repository methods. * Move business logic to handler * Type fix --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
e5ebf7feb4 |
fix: signup (#25334)
* Handle Stripe logic in `paymentCallback` * Remove endpoint * Do not send email verification email if premium username * Remove logic from verify-view * Callback send verification email * Add `create` method to `VerificationToken` repository * Create `VerificationTokenService` * Early return if payment failed * Refactor token generation * Add tests * Type fixes * Type fixes |
||
|
|
dd7c553cc3 |
fix: Remove hosts - verify event type belongs to event type (#25321)
* Add check that event type belongs to team * Add `findAcceptedMembershipsByUserIdsInTeam` to `MembershipRepository` * Validate that passed `userIds` belong to a team * Add tests * Typo fix |
||
|
|
dc3df122e2 |
feat: Add configurable trial days to org subscriptions + wizard warning (#25229)
* feat: Add trial days to organization subscriptions and workspace warning - Add ORGANIZATION_TRIAL_DAYS environment variable for configurable trial periods - Implement trial days in Stripe checkout session (only when env var is set) - Add warning message to organization setup page about workspace structure - Add translation string for organization trial workspace warning - Add ORGANIZATION_TRIAL_DAYS to turbo.json env vars - Fix pre-existing linting warnings in CreateANewOrganizationForm.tsx - Add ESLint disable comments for turbo/no-undeclared-env-vars warnings Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Rename variable * Add trial days to `purchaseTeamOrOrgSubscription` * fix: Move organization trial warning to spot 3 below form card - Add optional footer prop to WizardLayout component - Use footer prop in create-new-view.tsx to render warning at spot 3 - Remove warning from inside CreateANewOrganizationForm component - Warning now appears below the form card as requested Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: Add organization trial warning to all wizard steps - Add warning footer to step 2 (about-view.tsx) - Add warning footer to step 3 (add-teams-view.tsx) - Add warning footer to step 4 (onboard-members-view.tsx) - Add warning footer to step 5 (payment-status-view.tsx) - Add warning footer to resume-view.tsx (step 1 resume page) - Warning now appears on all steps of the organization creation wizard Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Correct environment variable name to STRIPE_ORG_TRIAL_DAYS - Changed ORGANIZATION_TRIAL_DAYS to STRIPE_ORG_TRIAL_DAYS in turbo.json - This matches the actual usage in OrganizationPaymentService.ts and payments.ts - Ensures the environment variable is properly recognized by the build system Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: Create shared OrganizationWizardLayout component - Create OrganizationWizardLayout component that wraps WizardLayout - Centralizes the trial warning footer logic in one place - Update all 6 wizard pages to use the shared component: - create-new-view.tsx - about-view.tsx - add-teams-view.tsx - onboard-members-view.tsx - payment-status-view.tsx - resume-view.tsx - Remove duplicate useLocale/Alert imports and footer props from pages - Simplifies maintenance by having warning logic in a single location Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix lint error * Add `ORG_TRIAL_DAYS` as constant * Add comment * Ensure no negative number is passed --------- 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> |
||
|
|
717a26f223 |
fix: prevent bulk update of locked locations in child managed event types (#24978)
* fix: prevent bulk update of locked locations in child managed event types - Filter out child managed event types with locked locations in getBulkUserEventTypes - Add validation in bulkUpdateEventsToDefaultLocation to prevent updating locked fields - Implements defense in depth with validation at multiple layers Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Abstract filtering logic * test: add comprehensive tests for bulk location update filtering - Add unit tests for filterEventTypesWhereLocationUpdateIsAllowed - Add unit tests for bulkUpdateEventsToDefaultLocation - Add integration tests for getBulkUserEventTypes - Fix bug: change unlockedFields?.locations check from !== undefined to === true This ensures that locations: false is properly treated as locked, addressing the security issue identified in PR review comments Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: filter locked managed event types on app installation page - Add parentId to eventTypeSelect in getEventTypes function - Apply filterEventTypesWhereLocationUpdateIsAllowed to both team and user event types - Only filter when isConferencing is true to avoid affecting other app types - Fixes issue where locked managed event types were showing in the event type selection list on /apps/installation/event-types page Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix(embed-react): remove obsolete availabilityLoaded event listener The availabilityLoaded event does not exist in the EventDataMap type system in embed-core. This code was causing 5 TypeScript errors in CI: - Type 'availabilityLoaded' does not satisfy constraint 'keyof EventDataMap' - 'data' is of type 'unknown' (2 occurrences) - Type 'availabilityLoaded' is not assignable to action union (2 occurrences) Since this is an example file and the event is not defined in the type system, removing this obsolete code resolves the type errors. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: correct Prisma type for metadata in test helper function Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use flexible PrismaLike type for better test compatibility Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: properly type mock Prisma objects in test files Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: properly mock Prisma methods in test file Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Filter out metadata * Undo change in embed file * Address feedback --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
7e4d9e26c6 |
refactor: implement DI in team billing service and team billing data repository factory (#24803)
* Move TeamBillingRepositories * WIP refactor team internal billing service * Remove duplicate billing repository files * Remove logic check in repository for billing is enabled * Rename repository to `TeamBillingData` * Use repository factory in main service * Fix new import paths * Rename to * Ensure `IS_TEAM_BILLING_ENABLED` is of type boolean * Rename classes to TeamBillingService and TeamBillingServiceFactory * Implement DI in `BookingServiceFactory` * `TeamBillingService` use repository in `getOrgIfNeeded` * DI `isTeamBillingEnabled` to `TeamBillingServiceFactory` * Rename files for consistency * Return stub BillingRepository if billing is not enabled * Move Stripe billing service to service folder * Rename file * `StripeBillingService.getSubscriptionStatus` return `SubscriptionStatus` * Type fices in StripeBillingService * Type fix in `stubTeamBillingService` * DI the `BillingProviderService` into the `TeamBillingService` * Implement DI in `skipTeamTrials.handler` * Implement DI for team billing in `inviteMember.handler` * `skipTeamTrials.handler` use `team.isOrganization` * Implement DI for billing in `hasActiveTeamPlan.handler` * Type fixes * Implement DI in `bulkDeleteUsers.handler` * Implement `BillingProviderServiceFactory` in `updateProfile.handler` * Implment `BillingProviderServiceFactory` in `buyCredits.handler` * Fix import in `stripeCustomer.handler` * Add a constructor to `teamBillingServiceFactory` * Add DI to `PrismaTeamBillingRepository` * Add DI to `StripeBillingService` * Implement singleton in `BillingProviderServiceFactory` * Add DI folder and contents to billing folder * Use `getTeamBillingServiceFactory` in `inviteMember.handler` * Add `saveTeamBilling` method to `ITeamBillingService` * Implement DI in new team route * Implement DI in `teamService` * Implement DI in `OrganizationPaymentService` * Implement DI in `credit-service` * In `StripeBillingService` remove `static` from status methods * Implemnt DI in `_invoice.paid.org` * Refactor `hasActiveTeamPlan` to use `getTeamBillingFactory` * Refactor `skipTeamTrials` to use `getTeamBillingFactory` * Refactor `skipTeamTrials` to use `getTeamBillingServiceFactory` * `stripeCustomer.handler` to use `getBillingProviderService` * Remove old factories * Type fix * Remove unused factory * Refactor `updateProfile.handler` to use `getBillingProviderService` * Change name to `TeamBillingDataRepositoryFactory` * Type Prisma return in `prisma.module` * Type fix * Refactor `buyCredits.handler` to use `getBillingProviderService` * Refactor `credit-service` to use billing DI containers * Type fix * Add `getTeamBillingDataRepository` * Refactor `_invoice.paid.org` to use DI container * Refactor `_customer.subscription.deleted.team-plan` to use DI container * Refactor `calcomHandler` to use DI container * Refactor `getCustomerAndCheckoutSession` to use DI container * Refactor `verify-email` to use DI containers * Refactor `api/create/route` to use DI container * Refactor downgradeUsers to use DI container * Type fix * Clean up console.logs * Add await to `this.billingRepository.create` in `saveTeamBilling` Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Fix type errors * Address comments * fix: update tests to work with new DI pattern - Update teamBillingService.test.ts to properly inject DI dependencies - Remove unused billingModule import and mock - Fix import naming in teamService.integration-test.ts (remove unused rename) - Fix import path for TeamBillingPublishResponseStatus All tests now properly mock IBillingProviderService, ITeamBillingDataRepository, and IBillingRepository instead of using the old BillingRepositoryFactory pattern. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: add compatibility layer and env setup for unit tests - Add STRIPE_PRIVATE_KEY dummy value to vitest.config.ts to prevent DI module errors - Fix import paths in credit-service.test.ts (StripeBillingService, TeamBillingService) - Create compatibility barrel at packages/features/ee/billing/teams/index.ts for test mocking Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: update unit tests to mock DI container properly - Update teamService.test.ts to mock getTeamBillingServiceFactory() instead of TeamBilling.findAndInit - Update teamService.alternative.test.ts to mock DI container - Update credit-service.test.ts to mock getBillingProviderService() and use SubscriptionStatus enum values - Update OrganizationPaymentService.test.ts to mock DI container instead of direct StripeBillingService import - Remove all 'as any' type casting to comply with Cal.com coding standards - Fix unused variable warnings by prefixing with underscore All 53 tests now passing (16 + 1 + 30 + 6) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: update remaining unit tests to use DI pattern - Fix StripeBillingService.test.ts to inject mock Stripe client directly - Fix teamBillingFactory.test.ts to mock getTeamBillingServiceFactory() from DI container - Fix skipTeamTrials.test.ts to mock DI container and use SubscriptionStatus enum All 11 previously failing tests now pass (5 + 5 + 1) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Undo changes made to Prisma module * fix: address test-related PR comments - Fix OrganizationPaymentService.test.ts mock path from @calcom/ee to @calcom/features/ee - Refactor teamBillingFactory.test.ts to test real factory logic instead of mocking container - Remove duplicate teamBillingService.test..ts file with incorrect double-dot filename All three test files now pass successfully with proper DI patterns. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Address feedback * fix: update teamService integration test to mock new DI factory pattern Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: remove duplicate imports in credit-service.test.ts Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Remove unused index file * `getBySubscriptionId` to return team or null * Address feedback * Merge fix * Refactor file names * fix: correct mockStripe variable name to stripeMock in StripeBillingService.test.ts Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: update internal-team-billing.test.ts to use new DI structure with TeamBillingService - Replace InternalTeamBilling with TeamBillingService - Use constructor injection with mock dependencies instead of factory pattern - Remove BillingRepositoryFactory mock and import - Update all test cases to use mockBillingProviderService, mockTeamBillingDataRepository, and mockBillingRepository - Simplify saveTeamBilling tests to focus on repository.create calls - All 11 tests now pass with the new DI structure Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: update createWithPaymentIntent.handler.test.ts to mock DI container's getBillingProviderService - OrganizationPaymentService now uses getBillingProviderService() from DI container - Test was mocking @calcom/features/ee/payments/server/stripe directly, which no longer works - Added mock for @calcom/features/ee/billing/di/containers/Billing module - Mock returns fake billing provider that delegates to mockSharedStripe - Preserves all existing test assertions and helpers - Fixed lint error by prefixing unused lastCreatedSessionId with underscore - All 11 tests now pass (1 skipped as expected) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> |
||
|
|
21411b8f93 |
docs: update embed-events.mdx with all currently emitted embed events (#25099)
* docs: update embed-events.mdx with all currently emitted embed events Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * docs: remove V2 suffix from event names in documentation Per feedback, the documentation should not expose internal versioning details. Event names are now presented as clean, non-versioned names: - bookingSuccessful (instead of bookingSuccessfulV2) - rescheduleBookingSuccessful (instead of rescheduleBookingSuccessfulV2) - dryRunBookingSuccessful (instead of dryRunBookingSuccessfulV2) - dryRunRescheduleBookingSuccessful (instead of dryRunRescheduleBookingSuccessfulV2) Added note about using wildcard listener for future-proofing. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * docs: use V2 suffix for embed event names to match code (#25263) * docs: update embed events to use V2 event names - Document bookingSuccessfulV2 instead of deprecated bookingSuccessful - Document rescheduleBookingSuccessfulV2 instead of deprecated rescheduleBookingSuccessful - Keep dryRunBookingSuccessful and dryRunRescheduleBookingSuccessful without V2 suffix (only V2 versions exist) - Add comprehensive event documentation with all public and internal events - Organize events into Public Events and Internal Events sections Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * fix: use V2 suffix for dry-run event names - Change dryRunBookingSuccessful to dryRunBookingSuccessfulV2 - Change dryRunRescheduleBookingSuccessful to dryRunRescheduleBookingSuccessfulV2 - These match the actual event names emitted in the code (only V2 versions exist) 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: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
7635d338c0 |
fix: increase dropdown z-index to appear above logo (#24057)
- Change dropdown z-index from z-10 to z-50 to ensure dropdowns appear above navigation elements - TopNav uses z-40, so dropdowns need higher z-index to be properly visible - Fixes issue where Cal.com logo was appearing above dropdown menus Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
5ceda11a0b |
fix: add 'use client' to routing-forms components to resolve React error 185 (#25107)
Adds 'use client' directive to FormInputFields.tsx and widgets.tsx in the routing-forms package. These components use React hooks (useLocale, setState) but were missing the client directive, causing React error 185 (invalid hook call) in production builds due to Next.js App Router bundling differences. The error only occurred in production, not local dev, because production builds optimize and bundle packages differently. The widgets.tsx file uses the useLocale hook in the Button component, and FormInputFields.tsx passes state setters to child components. Fixes the reroute dialog error reported in production. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
787828d0ca |
feat: Toggle auto adding users to an org if they signup without an invite (#25051)
* Remove auto adding users to an org * Update tests * Fix tests * fix: Update organization invitation E2E tests to not expect auto-accept before signup - Changed isMemberShipAccepted expectations from true to false before signup - Users with emails matching orgAutoAcceptEmail are no longer auto-accepted - They must explicitly accept the invitation after signup - Fixed lint warnings for unused parameters Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Update E2E tests to expect pending membership after signup without auto-accept Since auto-accept functionality was removed, users with emails matching orgAutoAcceptEmail are no longer automatically accepted into organizations after signup. They remain in pending state until explicitly accepted. Updated assertions in: - 'nonexisting user is invited to Org' test - 'nonexisting user is invited to a team inside organization' test Both tests now correctly expect isMemberShipAccepted: false after signup. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Restore `verify-email` and tests from `main` * Add `orgAutoJoinOnSignup` to `organizationSettings` * Update `OrganizationRepository.findUniqueNonPlatformOrgsByMatchingAutoAcceptEmail` to find orgs where `orgAutoJoinOnSignup` is true * `organization.update` lint fix * `organization.update` to handle `orgAutoJoinOnSignup` * Create toggle for `orgAutoJoinOnSignup` * test: Add comprehensive tests for orgAutoJoinOnSignup functionality - Update existing test to expect null instead of error when multiple orgs match - Add test for when orgAutoJoinOnSignup is false (should return null) - Add test for when orgAutoJoinOnSignup is true (should return org) - Add test for default behavior (orgAutoJoinOnSignup defaults to true) These tests verify that the new orgAutoJoinOnSignup setting correctly controls whether users are automatically added to organizations during email verification. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Type fix * e2e: invited users should be accepted after signup (address cubic r2511916791) Reverted post-signup isMemberShipAccepted assertions from false to true for explicit invite scenarios. When users are explicitly invited to an org/team and complete signup via invite link, their membership should be accepted. This is distinct from auto-join by domain (controlled by orgAutoJoinOnSignup), which only affects users who sign up without an invite but match the org's email domain. Backend sets membership.accepted = true on invite completion in: packages/features/auth/signup/utils/createOrUpdateMemberships.ts:61,67,77,83 Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix API V2 build --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
5267f8c3c1 | Escape special characters in email query (#25079) | ||
|
|
7d17b443cf |
chore: Add cache log (#24954)
* Add log * Update getCalendar.ts |
||
|
|
2dc0e2a6f2 |
fix: use highest role for org admins accessing sub team event types (#24748)
* fix: use highest role for org admins accessing sub team event types When an org admin who is also a member of a sub team (but only as MEMBER role) tries to update a sub team event type, they were being denied access. This was because the permission check logic was using the team MEMBER role instead of checking both team and org roles and using the highest one. This fix updates PermissionCheckService.checkPermission() and checkPermissions() to use the highest role between team membership and org membership, similar to how getEventTypePermissions() already works. Changes: - Added getHighestRole() helper method to determine the highest role between two roles - Updated checkPermission() to check both team and org membership and use the highest role - Updated checkPermissions() to use the same logic - Added test case for org admin who is team member updating sub team event type Fixes the issue where org admins get 'permission required eventType.update' errors when updating sub team event types. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add PBAC-enabled test case for org admin accessing sub team event types Adds a test case to verify that when PBAC is enabled, org admins who are also members of a sub team (but only with MEMBER role) can still access sub team event types through their org-level ADMIN permissions. This complements the existing fallback (PBAC disabled) test case and ensures both code paths handle org admin permissions correctly. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
d7df154059 |
fix: Add critical logger for booking created log to prevent stdout buffering issues (#24570)
* Add critical logger for booking created log to prevent stdout buffering issues Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add comment * Separate critialLogger into it's own file --------- 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> |
||
|
|
4d3727db12 |
Default fetchCrm to true for getRoutedUrl (#24635)
|
||
|
|
78c2a69389 | Script to reassign attributes (#24496) | ||
|
|
bb9c4bb8f3 |
feat: Update HubSpot meetings to CANCELLED status instead of archiving on booking cancellation (#24478)
* feat: Update HubSpot meetings to CANCELLED status instead of archiving When a booking is cancelled in Cal.com, preserve the meeting record in HubSpot by updating it to a CANCELLED status rather than archiving it. This maintains the meeting history for better tracking and reporting. Changes: - Renamed hubspotDeleteMeeting to hubspotCancelMeeting - Updated the method to set hs_meeting_outcome to CANCELLED - Changed from archive() to update() API call - Removed unused CustomPublicObjectInput interface Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Remove return statement to match void return type in deleteEvent Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: Remove hs_timestamp from cancel meeting to keep it minimal Only update the meeting outcome status when cancelling, without modifying the timestamp field. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Use correct HubSpot API value for canceled meetings Changed hs_meeting_outcome from "CANCELLED" to "CANCELED" to match HubSpot API specification. HubSpot uses lowercase American spelling "CANCELED" as the valid enum value for canceled meeting outcomes. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
17ab088af8 |
fix: Faulty logic around shouldServeCache (#24465)
* Should return `false` if no `teamId` is passed to `getShouldServeCache` * Change to falsey check * test: Add comprehensive tests for shouldServeCache fix - Add tests for CacheService.getShouldServeCache to verify it returns false when no teamId is provided (instead of undefined) - Add tests for GoogleCalendarService.getFreeBusyResult to verify the falsey check properly handles undefined, null, 0, empty string, and false values - All tests verify the fix in PR #24465 which changes undefined return to false and changes === false check to !shouldServeCache Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: Resolve type errors in test files - Fix private credential property access by using type assertion - Add missing IFeaturesRepository methods to mock 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: Alex van Andel <me@alexvanandel.com> |
||
|
|
b312955838 |
feat: Add subscription start, trial end, and dates to billing tables (#24408)
* Add subscription start, trial end, and end dates to db * Add subscription start, trial end, and end date to db * Write subscription start date on new team subscriptions * Write subscription start date for new orgs * Fix typo in stripe billing service file (billling -> billing) * Use `StripeBillingService.extractSubscriptionDates` * Remove comments * Address comment * Fix typo in file import * Fix typo in file import * Add missing SubscriptionStatus enum values - Add INCOMPLETE, INCOMPLETE_EXPIRED, UNPAID, PAUSED enum values - These values are referenced in stripe-billing-service.ts status mapping - Fixes type errors in billing-related code Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
4303fb8726 |
feat: Salesforce - add urql/retry-exchange (#24302)
* Add .env variables * Add `urql/exchange-retry` * Add retry mechanic to graphql client * Only add retries if .env variables are set * Remove console.log |
||
|
|
c702da0334 |
feat: Add team billing tables (#24148)
* Init billing tables * Create `IBillingRepository` types * Create billing repositories * Create billingRepositoryFactory * Eslint fix - remove unused organizationOnboarding * internal-team-billing create saveTeamBilling method using repositories * On new teams write to team billing table * On new org write to org billing table * Change fields to organizationId * Add todo comment * Revert "Change fields to organizationId" This reverts commit bbb2e5dfa6b4c20a8a395f5730848a492cd70d68. * test: add comprehensive tests for team billing tables - Fix credit-service.test.ts Prisma mock to export prisma object - Replace any types with proper TypeScript types in credit-service.test.ts - Add unit tests for PrismaTeamBillingRepository covering record creation, enum casting, and error handling - Add unit tests for PrismaOrganizationBillingRepository with same coverage - Add unit tests for BillingRepositoryFactory to verify correct repository selection - Add unit tests for InternalTeamBilling.saveTeamBilling() method testing delegation to correct repositories - All 53 tests pass with TZ=UTC yarn test - Type checking passes with yarn type-check:ci --force Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * refactor: update saveTeamBilling tests to mock repository interface - Replace prismaMock usage with BillingRepositoryFactory mock - Mock IBillingRepository interface instead of Prisma directly - Follow repository mocking pattern from handleResponse.test.ts - All tests passing (53 total) Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Remove log statement * Remove repository tests * Address feedback --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
654a865007 |
refactor: Salesforce getContacts (#24235)
* lint fixes * Create getContactOrLeadFromEmail method * Use getContactOrLeadFromEmail in getContacts * Move normal getContact query * fix: correct return type in getContactOrLeadFromEmail and add search mock - Fix getContactOrLeadFromEmail to return single ContactRecord instead of array - Add conn.search() implementation to salesforceMock for integration tests - Ensure id field is always string with proper fallbacks for AccountId and Id - Fix Owner.Email to use undefined instead of null in mock Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive tests for getContactOrLeadFromEmail method - Add 6 new unit tests covering all key scenarios - Test contact lookup, lead fallback, and preference logic - Test both roundRobinSkipFallbackToLeadOwner and createEventOnLeadCheckForContact code paths - Add search mock support to mockConnection in beforeEach - All 34 tests passing, type-check clean Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Implement change to error from #24090 * Address feedback * Type fix * test: update SOQL query expectations to include Account.OwnerId Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
f003ef935b |
Remove safeStringify from graphql errors (#24188)
|
||
|
|
b2239374bc |
fix: Remove team members as org admin (#24020)
* Fallback to org admin * Prevent accidental privilege escalation as code changes in the future * When org admin, we don't actually need to do the db query * Use findMany and Map to drill down permission adjustments * Exclude .MEMBER from overriding role, we likely don't want to demote * refactor logic * Add tests for services/factories + removeHandler * fix type check --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: Sean Brydon <sean@cal.com> |
||
|
|
88391c7942 |
fix: Handle account user lookup fields for queued form responses (#23811)
* Add constants for queued response id query string * Ignore eslint - app store imports * Return `routingFormResponseId` or `queuedFormResponseId` from URL params * Pass routingForm params to `getTeamMemberEmailForResponseOrContact` * Handle getting form responses for queued form responses * Type fix * add test * Add tests --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> |
||
|
|
31270ca86b |
feat: Write same metadata to Stripe for booking payment and no show fee payment (#23634)
* Add `findBookingById` to `BookingRepository` * Create `generateMetadata` to Stripe `PaymentService` * `create` method to use `generateMetadata` * Remove unused trpc endpoint * Pass booking id to chargeCard method * Use generateMetadata in chargeCard method * Remove unused stripeAppKeys * Add error handling if booking doesn't contain attendee * Rename to * Return attendees in a consistent order --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
d7397d4563 |
fix: managed event types inherit team hideBranding setting (#23562)
* fix: managed event types inherit team hideBranding setting - Add getParentTeamForBranding helper to query parent team data - Update shouldHideBrandingForEvent to use parent team when eventType.team is null - Ensures CTA 'create your own booking link with Cal' respects team branding settings - Follows existing pattern used by eventType.team?.id ?? eventType.parent?.teamId Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * chore: update yarn.lock dependencies Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Get parent event type team branding * Use data from getEventTypeFromDB * Undo yarn.lock changes * Undo yarn.lock changes from latest main * Address code commit --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
d6b17b76db |
test: add comprehensive unit tests for no-show fee payment functions (#23626)
* feat: add time-based cancellation fees for no-show fee events - Add configurable time threshold (minutes/hours/days) for cancellation fees - Show warnings during booking submission and cancellation - Automatically charge fees when bookings cancelled within threshold - Exempt organizer/admin cancellations from fees - Extend existing no-show fee infrastructure Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: replace any type with proper type guards for metadata - Use Record<string, unknown> instead of any for metadata type - Add proper type assertions for nested metadata properties - Maintain type safety while avoiding ESLint no-explicit-any warning Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: handle JsonValue type compatibility in shouldChargeCancellationFee - Add proper type guard for metadata JsonValue from Prisma - Ensure metadata is object before casting to Record<string, unknown> - Fixes TypeScript error on line 390 in handleCancelBooking.ts Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Refactor Devin changes to Stripe options * Undo Devin changes to advanced tab * Add translations * Pass props to CancelBooking * Display no show fee charge for attendee * WIP * Anstract shouldChargeNoSHowCancellationFee * Abstract `handleNoShowFee` * Add to * Refactor `chargeCard.handler` * Remove Devin code * Type fix in `shouldChargeNoShowCancellationFee` * Create `processNoSHowFeeOnCancellation` * Process no show fee on cancellation * Type fix * Skip processing no show fee if organizer or admin is cancelling * Add translation * Dynamically get and in * Remove unused translations * Undo dev change * Refactor logic * Type fix * remove any * revert WEBAPP_URL_FOR_OAUTH * Clean up console.log remnants * test: add comprehensive tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions - Add handleCancelBooking test for attendee fee charging within time threshold - Add UI component tests for cancellation fee warning display - Add E2E test for cancellation fee warning during booking flow All 23 new tests pass successfully, covering: - Time-based logic with different units (minutes, hours, days) - Role-based exemptions (organizer, team admin vs regular attendee) - Payment charging integration with HOLD payment option - UI warning display during booking submission and cancellation - Edge cases like invalid metadata and past bookings Fixed lint issues: - Replaced 'any' types with proper Record<string, unknown> - Fixed Playwright test.skip() usage with ESLint disable comments Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions - Add handleCancelBooking test for attendee fee charging within time threshold - Add UI component tests for cancellation fee warning display - Add E2E test for cancellation fee warning during booking flow All unit and integration tests pass successfully. E2E test implementation complete. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions - Add handleCancelBooking test for attendee fee charging within time threshold - Add UI component tests for cancellation fee warning display - Add E2E test for cancellation fee warning during booking flow - Fix TypeScript issues and prettier formatting - All tests follow existing Cal.com patterns and pass locally Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive unit and E2E tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions and attendee fee charging - Add UI component tests for cancellation fee warning display in CancelBooking component - Add E2E test for cancellation fee warning during booking flow - Fix TypeScript errors in CancelBooking.tsx with proper type annotations - All tests follow existing Cal.com patterns and use proper mocking/test utilities Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Revert dev change * Add missing translation * Remove Devin code * Revert Devin changes * test: fix attendee cancellation test logic and ensure comprehensive test coverage - Fix userId in attendee cancellation test to properly test fee charging - Ensure all test files follow Cal.com patterns with proper mocking - Add comprehensive coverage for time thresholds, role exemptions, and UI warnings - All tests pass locally with proper timezone handling Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix tests * test: add comprehensive unit tests for no-show fee payment functions - Add unit tests for handleNoShowFee.ts covering successful scenarios, error handling, and edge cases - Add unit tests for processNoShowFeeOnCancellation.ts covering cancellation logic and payment conditions - Tests include proper mocking of dependencies and comprehensive coverage of all code paths - All tests pass with TZ=UTC yarn test and type checking passes Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Don't block cancel flow for failed payment processing * Await single attendee getTranslation in `handleNoShowFee` * Add missing data * Undo old strings * Type fix --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> |
||
|
|
083a162d0e |
feat: add time-based cancellation fees for no-show fee events (#23595)
* feat: add time-based cancellation fees for no-show fee events - Add configurable time threshold (minutes/hours/days) for cancellation fees - Show warnings during booking submission and cancellation - Automatically charge fees when bookings cancelled within threshold - Exempt organizer/admin cancellations from fees - Extend existing no-show fee infrastructure Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: replace any type with proper type guards for metadata - Use Record<string, unknown> instead of any for metadata type - Add proper type assertions for nested metadata properties - Maintain type safety while avoiding ESLint no-explicit-any warning Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: handle JsonValue type compatibility in shouldChargeCancellationFee - Add proper type guard for metadata JsonValue from Prisma - Ensure metadata is object before casting to Record<string, unknown> - Fixes TypeScript error on line 390 in handleCancelBooking.ts Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Refactor Devin changes to Stripe options * Undo Devin changes to advanced tab * Add translations * Pass props to CancelBooking * Display no show fee charge for attendee * WIP * Anstract shouldChargeNoSHowCancellationFee * Abstract `handleNoShowFee` * Add to * Refactor `chargeCard.handler` * Remove Devin code * Type fix in `shouldChargeNoShowCancellationFee` * Create `processNoSHowFeeOnCancellation` * Process no show fee on cancellation * Type fix * Skip processing no show fee if organizer or admin is cancelling * Add translation * Dynamically get and in * Remove unused translations * Undo dev change * Refactor logic * Type fix * remove any * revert WEBAPP_URL_FOR_OAUTH * Clean up console.log remnants * test: add comprehensive tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions - Add handleCancelBooking test for attendee fee charging within time threshold - Add UI component tests for cancellation fee warning display - Add E2E test for cancellation fee warning during booking flow All 23 new tests pass successfully, covering: - Time-based logic with different units (minutes, hours, days) - Role-based exemptions (organizer, team admin vs regular attendee) - Payment charging integration with HOLD payment option - UI warning display during booking submission and cancellation - Edge cases like invalid metadata and past bookings Fixed lint issues: - Replaced 'any' types with proper Record<string, unknown> - Fixed Playwright test.skip() usage with ESLint disable comments Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions - Add handleCancelBooking test for attendee fee charging within time threshold - Add UI component tests for cancellation fee warning display - Add E2E test for cancellation fee warning during booking flow All unit and integration tests pass successfully. E2E test implementation complete. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions - Add handleCancelBooking test for attendee fee charging within time threshold - Add UI component tests for cancellation fee warning display - Add E2E test for cancellation fee warning during booking flow - Fix TypeScript issues and prettier formatting - All tests follow existing Cal.com patterns and pass locally Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * test: add comprehensive unit and E2E tests for time-based cancellation fees - Add unit tests for shouldChargeCancellationFee function with time thresholds and role exemptions - Add handleCancelBooking integration tests for organizer/team admin exemptions and attendee fee charging - Add UI component tests for cancellation fee warning display in CancelBooking component - Add E2E test for cancellation fee warning during booking flow - Fix TypeScript errors in CancelBooking.tsx with proper type annotations - All tests follow existing Cal.com patterns and use proper mocking/test utilities Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Revert dev change * Add missing translation * Remove Devin code * Revert Devin changes * test: fix attendee cancellation test logic and ensure comprehensive test coverage - Fix userId in attendee cancellation test to properly test fee charging - Ensure all test files follow Cal.com patterns with proper mocking - Add comprehensive coverage for time thresholds, role exemptions, and UI warnings - All tests pass locally with proper timezone handling Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Fix tests * Remove reverted PR translations --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> |
||
|
|
25c20e5093 | fix: Handle personal billing portal on backend (#23521) | ||
|
|
f1d1674693 |
feat: allow organization owners access to shared billing portal (#23451)
* feat: allow organization owners access to shared billing portal - Modify stripepayment portal endpoint to accept teamId parameter - Use team's subscription ID to get customer ID from Stripe subscription - Validate user permissions before allowing team billing access - Update platform and regular billing views to pass teamId - Maintain backward compatibility with individual user billing Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Add `getTeamByIdIfUserIsAdmin` to `TeamRepository` * Add `getSubscriptionFromId` function * Generate portal URL via the team's subscription not the requesting user's customerId * Pass teamId to `/portal` endpoint * Undo Devin change to platform billing * Address coderabbit comments --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
bfa23ddb80 |
refactor: Remove app store index (#23449)
* Remove app store index * Remove reliance on app-store mock * Remove app store mock |
||
|
|
1fd1202373 | fix: Allow install on teams for concurrent meeting apps (#23429) | ||
|
|
84bd4d3d38 |
Remove payment fee from chargeCard (#23411)
|
||
|
|
b2244503b1 |
fix: Missing jose module in saml-jackson package (#23291)
* Ensure packages are bundled with code * Update dependencies --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> |
||
|
|
2d90d11e9e |
feat: Add custom label for organizer default app and link meeting (#23114)
* Create `CalVideoSettings` type * Create `LocationOptionContainer` * Extract cal video settings to `CalVideoSettings` * Refactor `<Locations />` component to use `<CalVideoSettings />` * Unify naming * Move location folder back under components * Type fixes * Extract types * Add custom label prop to default app types * Extract `LocationInput` component * Create `DefaultLocationSettings` component * Move `locations` folder * Add custom label field for link and organizer default locations * Type fixes * Save the custom label in db * Include location custom label when querying db * Display custom label on booking page * Add translations * Type fixes * Change `customLabel` to `supportsCustomLabel` * Remove unused code * Show the customLabel on booking page * Fix hover tooltip text as well * Fix displaying exact value on booking page * Add missing translation * Remove default label of "Value" * Replace nullish collescing with OR * Replace nullish collescing with OR --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> |
||
|
|
b9aee3b18c |
fix: Add guests via URL param even if field is hidden (#23229)
* Add guests via URL param even if field is hidden * Clean up |
||
|
|
cf13c06c57 |
chore: Upgrade boxyhq/saml-jackson to 1.52.2 (#23231)
* Upgrade jackson to 1.52.2 * Update apps/web/package.json Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Remove unused option prop --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
f9e24f51a7 |
refactor: Extract <CalVideoSettings /> from `<Locations /> (#23113)
* Create `CalVideoSettings` type * Create `LocationOptionContainer` * Extract cal video settings to `CalVideoSettings` * Refactor `<Locations />` component to use `<CalVideoSettings />` * Unify naming * Move location folder back under components * Type fixes * Delete console.log |
||
|
|
ff79064ca7 |
fix: Managed event types - children inherit team's appearance settings (#23116)
* Get parent event type team's appearance settings * Use style profile to get brand colours * Update packages/features/eventtypes/lib/getPublicEvent.ts --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
ed6f9d8252 |
fix: Add cal.eu to IS_CALCOM (#23111)
* Add cal.eu to `IS_CALCOM` * Create `getCalcomUrl` function * Use `getCalcomURl` in generate metadata * Use `getCalcomURl` in `buildCanonical` * Linting fix |
||
|
|
ab703a4346 | Add and to (#23020) | ||
|
|
4baa9b6bc1 | wrap samlResponse in try/catch (#22984) | ||
|
|
bf8f966811 |
chore: Add logging to SAML endpoints (#22968)
* Add logging to SAML endpoints * Update packages/features/auth/lib/next-auth-options.ts --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> |
||
|
|
cfefba6d4d | Revert "perf: use repository for webhooks list query & caching in /settings/developer/webhooks/... RSC (#21781)" (#22963) | ||
|
|
815e13303b | Compare membership with teamId (#22957) | ||
|
|
b7e11dc112 |
chore: Add logging to handleNewBooking (#22868)
* Add logging * Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update logger config, fix Create booking log * Added oooExcludedDateRanges + type error fix --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> |
||
|
|
91932212e3 |
fix: Cal Video sidebar not showing meeting time in timezone (#22821)
* Pass params as object to `formatToLocalizedTime` * Refactor videos-single-view * Refactor bookings-single-view |
||
|
|
f81bb92beb |
fix: increment iCalSequence when changing booking location (#22847)
* fix: increment iCalSequence when changing booking location - Add iCalSequence parameter to buildCalEventFromBooking function - Update editLocation handler to increment sequence by 1 in CalendarEvent - Update database with incremented iCalSequence when location changes - Update buildCalEventFromBooking test to include new fields - Ensures ICS files properly update existing calendar events instead of creating duplicates Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * `BookingRepository.updateLocationById` to accept responses and iCalSequence * `editLocation.handler` use `BookingRepository` * Update iCalSequence * Use iCalSequence from booking param * Add iCalUID to evt object * Clean up * Fix test * Fix test --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |
||
|
|
f7b201b0b5 |
fix: Return empty available days if error querying calendar (#22828)
* Return a busy block placeholder if calendar throws an error * Refactor `getCalendarsEvents` to return an object with a success prop * Throw error in `getBusyTimes` if failed to fetch calendar availability * Return empty available days if error getting busy times * yeet. * Type fix * Fix type error in getLuckyUsers * Type fixes * Type fix * Type fix * Fix test * Fix test mocks * Refactor calendars.service to use new calendarBusyTimesQuery --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> |
||
|
|
704bbf2757 |
chore: Refactor logs (#22824)
* Refactor logs * Add specific info to log |
||
|
|
4e92b6edeb |
chore: Log availability snapshot when booking is created (#22782)
* Add userAvailability type * Add user availability to return value of getUsersAvailability * Log availabilitySnapshot when booking is created * Type fix |
||
|
|
6c936472d2 |
feat: add cancelledBy and rescheduledBy parameters to workflow links (#22438)
* feat: add cancelledBy and rescheduledBy parameters to workflow links - Extended workflow reminder selection to include user and team data - Added getWorkflowAssigneeEmail helper function to resolve assignee email - Updated email and SMS workflow templates to include assignee in cancel/reschedule links - For user workflows, uses user email; for team workflows, uses team owner email - Maintains backward compatibility when assignee data is unavailable Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use workflow recipient email instead of assignee email for link parameters - Updated getWorkflowRecipientEmail to determine recipient based on workflow action type - EMAIL_ADDRESS uses sendTo email, EMAIL_HOST uses organizer, EMAIL_ATTENDEE uses attendee - SMS_ATTENDEE/WHATSAPP_ATTENDEE use attendee email for cancelledBy/rescheduledBy params - Maintains backward compatibility when recipient data unavailable Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: use emailReminderManager for email workflows with recipient parameters - Updated emailReminderManager to include recipient email in cancel/reschedule links - Added getEmailWorkflowRecipientEmail function for proper recipient determination - Removed changes from deprecated scheduleEmailReminders.ts - SMS_ATTENDEE correctly uses attendee email like EMAIL_ATTENDEE Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Get attendee's email when sending SMS * Remove unused query * feat: add cancelledBy and rescheduledBy parameters to getSMSMessageWithVariables Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Clean up Devin --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> |