Skip to content

Comments

feat: add optional guest members from team#22127

Closed
jayantpranjal0 wants to merge 1 commit intocalcom:mainfrom
jayantpranjal0:add_guest_team
Closed

feat: add optional guest members from team#22127
jayantpranjal0 wants to merge 1 commit intocalcom:mainfrom
jayantpranjal0:add_guest_team

Conversation

@jayantpranjal0
Copy link

@jayantpranjal0 jayantpranjal0 commented Jun 29, 2025

What does this PR do?

Visual Demo (For contributors especially)

A visual demonstration is strongly recommended, for both the original and new change (video / image - any one).

Video Demo (if applicable):

  • Show screen recordings of the issue or feature.
  • Demonstrate how to reproduce the issue, the behavior before and after the change.

Image Demo (if applicable):

image
  • Add side-by-side screenshots of the original and updated change.
  • Highlight any significant change(s).

Mandatory Tasks (DO NOT REMOVE)

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

How should this be tested?

Checklist

  • I haven't read the contributing guide
  • My code doesn't follow the style guidelines of this project
  • I haven't commented my code, particularly in hard-to-understand areas
  • I haven't checked if my changes generate no new warnings

Summary by cubic

Added the ability to include team members as optional guests for event types, allowing them to receive invites without checking their availability.

  • New Features
    • Added UI control to select optional guest team members when editing an event type.
    • Updated calendar integrations to send optional invites to selected team members.

@jayantpranjal0 jayantpranjal0 requested review from a team June 29, 2025 02:53
@jayantpranjal0 jayantpranjal0 requested a review from a team as a code owner June 29, 2025 02:53
@vercel
Copy link

vercel bot commented Jun 29, 2025

Someone is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant
Copy link

CLAassistant commented Jun 29, 2025

CLA assistant check
All committers have signed the CLA.

@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Jun 29, 2025
@graphite-app graphite-app bot requested a review from a team June 29, 2025 02:53
@github-actions
Copy link
Contributor

github-actions bot commented Jun 29, 2025

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "Added feature to add optional guest members from team". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

@github-actions github-actions bot added ❗️ migrations contains migration files $25 teams area: teams, round robin, collective, managed event-types ✨ feature New feature or request labels Jun 29, 2025
@dosubot dosubot bot added this to the Community Only milestone Jun 29, 2025
@dosubot dosubot bot added the event-types area: event types, event-types label Jun 29, 2025
@graphite-app
Copy link

graphite-app bot commented Jun 29, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (06/29/25)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add community label" took an action on this PR • (06/29/25)

1 label was added to this PR based on Keith Williams's automation.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 6 issues across 21 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

@jayantpranjal0 jayantpranjal0 changed the title Added feature to add optional guest members from team feat: add optional guest members from team Jun 29, 2025
@jayantpranjal0
Copy link
Author

@cubic-dev-ai check for any issues again

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Jun 29, 2025

@jayantpranjal0 I've started the AI code review. It'll take a few minutes to complete.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 4 issues across 21 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

Copy link
Contributor

@Devanshusharma2005 Devanshusharma2005 left a comment

Choose a reason for hiding this comment

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

hey @jayantpranjal0 thanks for the pr. can you please address the issues suggested by cubic ?

@kart1ka kart1ka marked this pull request as draft July 1, 2025 17:58
@kart1ka
Copy link
Contributor

kart1ka commented Jul 1, 2025

Making it draft. Feel free to rfr once the comments are addressed.

@jayantpranjal0
Copy link
Author

@jayantpranjal0 jayantpranjal0 marked this pull request as ready for review July 2, 2025 01:55
@jayantpranjal0
Copy link
Author

jayantpranjal0 commented Jul 2, 2025

@cubic-dev-ai check out this commit

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Jul 2, 2025

@jayantpranjal0 I noticed you tagged me but I'm not quite sure what you need help with.

Here are some things you can ask me to do:

  • Ask questions: @cubic-dev-ai why is this change needed?
  • Request a review: @cubic-dev-ai review this PR
  • Get clarification: @cubic-dev-ai can you explain this suggestion?

Please tag me again with your specific request and I'll be happy to help!

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Jul 2, 2025

@jayantpranjal0 I've started the AI code review. It'll take a few minutes to complete.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 3 issues across 21 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 2 issues across 21 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

@jayantpranjal0
Copy link
Author

@cubic-dev-ai any reviews?

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Jul 2, 2025

@jayantpranjal0 This PR introduces the "optional guest team members" feature across the event type flow and calendar integrations. Key points from review:

  • The database migration and Prisma schema changes correctly add a many-to-many relation between EventType and User for optional guests.
  • The event type form UI and state management are updated to allow selecting team members as optional guests.
  • Calendar integration logic (Google, Exchange, Feishu, Lark, Zoho) is updated to include these optional guests in event creation, ensuring they are marked as optional and not duplicated with required attendees.
  • The feature is opt-in per event type and does not affect existing flows unless enabled.

No major issues found. Minor suggestions:

  • Ensure all calendar integrations handle edge cases (e.g., duplicate emails, self-invites) consistently.
  • Add/expand tests to cover the new optional guest logic, especially for calendar payloads.

Overall, the implementation is sound and aligns with the described feature.

@jayantpranjal0
Copy link
Author

The PR is ready for review. Please approve the workflows

@jayantpranjal0
Copy link
Author

@jayantpranjal0
Copy link
Author

Also, wanted to know if there is a communication channel for cal.com

@kart1ka
Copy link
Contributor

kart1ka commented Jul 2, 2025

hi @jayantpranjal0

Please note that this PR will need a video as visual evidence instead of just an image. Could you kindly add a Loom video demonstrating the feature?

@anikdhabal anikdhabal added the Low priority Created by Linear-GitHub Sync label Jul 4, 2025
@github-actions
Copy link
Contributor

This PR is being marked as stale due to inactivity.

@github-actions github-actions bot added the Stale label Jul 19, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 19, 2025

Walkthrough

This change introduces support for designating team members as optional guests in event bookings. A new many-to-many relation between event types and users is added to the database schema, with corresponding migration and Prisma schema updates. Backend logic is updated to handle the new optionalGuestTeamMembers field throughout event type creation, update, and retrieval, including validation to ensure only team members can be added as optional guests. The CalendarEvent interface and event builder are extended to include optional guest team members, and all major calendar provider integrations are updated to correctly handle and mark these attendees as optional. The frontend now includes a UI component for selecting optional guest team members, with appropriate form handling and localization. No changes are made to the signatures of existing exported or public entities, except for the addition of new fields and components related to optional guest team members.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/app-store/exchangecalendar/lib/CalendarService.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

packages/app-store/larkcalendar/lib/CalendarService.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

packages/app-store/exchange2013calendar/lib/CalendarService.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

  • 16 others
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (6)
packages/app-store/larkcalendar/lib/CalendarService.ts (1)

425-434: Filter out members without email addresses before mapping.

This issue was already identified in a previous review. Mapping directly without filtering out members that lack an email can create attendee objects with third_party_email undefined, which may cause the Lark API to reject the request.

-    if (event.optionalGuestTeamMembers) {
-      const optionalGuestMembers = event.optionalGuestTeamMembers?.map(
+    if (event.optionalGuestTeamMembers) {
+      const optionalGuestMembers = event.optionalGuestTeamMembers?.filter(({ email }) => !!email).map(
        ({ email }): LarkEventAttendee => ({
          type: "third_party",
          is_optional: true,
          third_party_email: email,
        })
      );
      attendeeArray.push(...optionalGuestMembers);
    }
packages/app-store/exchangecalendar/lib/CalendarService.ts (2)

72-76: Use the imported Person interface for better type safety.

Using an inline object type reduces type safety and consistency. The Person interface is already imported and should be used.

      if (event.optionalGuestTeamMembers) {
-        event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
+        event.optionalGuestTeamMembers.forEach((member: Person) => {
          appointment.OptionalAttendees.Add(new Attendee(member.email));
        });
      }

115-120: Prevent unintended data loss by making clearing conditional.

Clearing optional attendees unconditionally can remove existing optional guests even when the update payload doesn't include optionalGuestTeamMembers, leading to data loss.

-    appointment.OptionalAttendees.Clear();
     if (event.optionalGuestTeamMembers) {
+       appointment.OptionalAttendees.Clear();
-       event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
+       event.optionalGuestTeamMembers.forEach((member: Person) => {
         appointment.OptionalAttendees.Add(new Attendee(member.email));
       });
     }
packages/app-store/exchange2013calendar/lib/CalendarService.ts (1)

126-131: Identical logic for iterating over optionalGuestTeamMembers and adding each attendee is duplicated in both createEvent and updateEvent. Duplicated code makes future changes error-prone and harder to maintain; consider extracting this into a shared helper method.

packages/prisma/schema.prisma (1)

203-203: LGTM! Many-to-many relation properly implemented.

The new optionalGuestTeamMembers relation is correctly implemented as an explicit many-to-many relation using a join table (as evidenced by the migration file). This resolves the previous concern about Prisma's constraint on multiple implicit many-to-many relations between the same models.

Also applies to: 337-337

packages/features/eventtypes/components/tabs/advanced/GuestTeamMemberController.tsx (1)

26-28: State synchronization properly implemented.

The useEffect correctly addresses the previous concern about stale state by updating isGuestTeamMembersEnabled whenever eventType.optionalGuestTeamMembers changes, ensuring the component stays synchronized with prop updates.

🧹 Nitpick comments (2)
apps/web/public/static/locales/en/common.json (1)

936-937: Tweak wording for grammatical correctness

Minor grammar issue – “Adding team members as an optional guest” mixes plural members with singular guest. Recommend pluralizing “guest” and adding the missing “will” for consistency with the rest of the sentence.

-"optional_guest_team_members_description": "Adding team members as an optional guest will always send an optional invite, but not check their availability.",
+"optional_guest_team_members_description": "Adding team members as optional guests will always send an optional invite, but will not check their availability.",
packages/features/eventtypes/components/tabs/advanced/GuestTeamMemberController.tsx (1)

64-64: Consider adding error handling for data transformation.

While the current implementation should work in practice, consider adding validation:

  • Line 64: parseInt(option.value) could benefit from validation or using Number() with error handling
  • Lines 81-82: The || "" fallbacks on member.user.email and member.user.id.toString() suggest these could be undefined, but they should always be truthy - consider removing redundant fallbacks or adding proper validation
- onChange(options.map((option) => ({ id: parseInt(option.value) })));
+ onChange(options.map((option) => ({ id: Number(option.value) })).filter(item => !isNaN(item.id)));
- label: member.user.email || "",
- value: member.user.id.toString() || "",
+ label: member.user.email,
+ value: member.user.id.toString(),

Also applies to: 78-82

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b599ce4 and 4ebf0e8.

📒 Files selected for processing (22)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/app-store/exchange2013calendar/lib/CalendarService.ts (2 hunks)
  • packages/app-store/exchange2016calendar/lib/CalendarService.ts (2 hunks)
  • packages/app-store/exchangecalendar/lib/CalendarService.ts (2 hunks)
  • packages/app-store/feishucalendar/lib/CalendarService.ts (1 hunks)
  • packages/app-store/googlecalendar/lib/CalendarService.ts (1 hunks)
  • packages/app-store/larkcalendar/lib/CalendarService.ts (1 hunks)
  • packages/app-store/zohocalendar/lib/CalendarService.ts (2 hunks)
  • packages/features/CalendarEventBuilder.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts (1 hunks)
  • packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx (2 hunks)
  • packages/features/eventtypes/components/tabs/advanced/GuestTeamMemberController.tsx (1 hunks)
  • packages/features/eventtypes/lib/types.ts (1 hunks)
  • packages/lib/defaultEvents.ts (1 hunks)
  • packages/lib/server/repository/eventType.ts (1 hunks)
  • packages/platform/atoms/event-types/hooks/useEventTypeForm.ts (1 hunks)
  • packages/prisma/migrations/20250628001746_add_optional_guest_team_members/migration.sql (1 hunks)
  • packages/prisma/schema.prisma (2 hunks)
  • packages/trpc/server/routers/viewer/eventTypes/types.ts (1 hunks)
  • packages/trpc/server/routers/viewer/eventTypes/update.handler.ts (3 hunks)
  • packages/types/Calendar.d.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (14)
packages/features/eventtypes/lib/types.ts (1)
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.341Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts (1)
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.341Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
packages/trpc/server/routers/viewer/eventTypes/types.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/platform/atoms/event-types/hooks/useEventTypeForm.ts (2)
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.341Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
Learnt from: alishaz-polymath
PR: calcom/cal.com#22304
File: packages/features/eventtypes/components/MultiplePrivateLinksController.tsx:92-94
Timestamp: 2025-07-16T06:42:27.001Z
Learning: In the MultiplePrivateLinksController component (packages/features/eventtypes/components/MultiplePrivateLinksController.tsx), the `currentLink.maxUsageCount ?? 1` fallback in the openSettingsDialog function is intentional. Missing maxUsageCount values indicate old/legacy private links that existed before the expiration feature was added, and they should default to single-use behavior (1) for backward compatibility.
packages/app-store/feishucalendar/lib/CalendarService.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
packages/app-store/larkcalendar/lib/CalendarService.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.341Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
packages/app-store/exchange2016calendar/lib/CalendarService.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
packages/app-store/googlecalendar/lib/CalendarService.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/exchange2013calendar/lib/CalendarService.ts (3)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx (2)
Learnt from: alishaz-polymath
PR: calcom/cal.com#22304
File: packages/features/eventtypes/components/MultiplePrivateLinksController.tsx:92-94
Timestamp: 2025-07-16T06:42:27.001Z
Learning: In the MultiplePrivateLinksController component (packages/features/eventtypes/components/MultiplePrivateLinksController.tsx), the `currentLink.maxUsageCount ?? 1` fallback in the openSettingsDialog function is intentional. Missing maxUsageCount values indicate old/legacy private links that existed before the expiration feature was added, and they should default to single-use behavior (1) for backward compatibility.
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.341Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
apps/web/public/static/locales/en/common.json (1)

undefined

<retrieved_learning>
Learnt from: bandhan-majumder
PR: #22359
File: packages/lib/server/locales/en/common.json:1336-1339
Timestamp: 2025-07-14T16:31:45.201Z
Learning: When making localization changes for new features, it's often safer to add new strings rather than modify existing ones to avoid breaking existing functionality that depends on the original strings. This approach allows for feature-specific customization while maintaining backward compatibility.
</retrieved_learning>

packages/prisma/schema.prisma (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
packages/app-store/exchangecalendar/lib/CalendarService.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.370Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
packages/features/eventtypes/components/tabs/advanced/GuestTeamMemberController.tsx (2)
Learnt from: alishaz-polymath
PR: calcom/cal.com#22304
File: packages/features/eventtypes/components/MultiplePrivateLinksController.tsx:92-94
Timestamp: 2025-07-16T06:42:27.001Z
Learning: In the MultiplePrivateLinksController component (packages/features/eventtypes/components/MultiplePrivateLinksController.tsx), the `currentLink.maxUsageCount ?? 1` fallback in the openSettingsDialog function is intentional. Missing maxUsageCount values indicate old/legacy private links that existed before the expiration feature was added, and they should default to single-use behavior (1) for backward compatibility.
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.341Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.
🧬 Code Graph Analysis (3)
packages/app-store/zohocalendar/lib/CalendarService.ts (1)
packages/types/Calendar.d.ts (1)
  • CalendarEvent (163-228)
packages/trpc/server/routers/viewer/eventTypes/update.handler.ts (1)
packages/platform/libraries/index.ts (2)
  • TRPCError (56-56)
  • SchedulingType (30-30)
packages/features/eventtypes/components/tabs/advanced/GuestTeamMemberController.tsx (2)
packages/features/eventtypes/lib/types.ts (2)
  • EventTypeSetup (25-25)
  • FormValues (69-168)
packages/features/eventtypes/components/CheckedTeamSelect.tsx (2)
  • CheckedTeamSelect (47-189)
  • CheckedSelectOption (20-29)
🔇 Additional comments (21)
packages/features/eventtypes/lib/types.ts (1)

167-167: LGTM! Type definition is appropriate for form handling.

The addition of optionalGuestTeamMembers as an array of objects with id fields is correct for form data handling, where you'd typically store selected team member IDs and enrich with additional details when building calendar events.

packages/lib/defaultEvents.ts (1)

147-147: LGTM! Appropriate default value for the new feature.

Setting an empty array as the default for optionalGuestTeamMembers is the correct approach, ensuring backward compatibility and providing a sensible default when no optional guests are selected.

packages/types/Calendar.d.ts (1)

224-227: LGTM! Appropriate type definition for calendar events.

The optionalGuestTeamMembers property is correctly defined with email and name fields needed for calendar invitations. Making it optional ensures backward compatibility, and allowing name to be null handles cases where team members may not have names set.

packages/features/bookings/lib/handleNewBooking.ts (1)

1155-1155: LGTM! Proper integration into the calendar event building flow.

The addition correctly integrates optional guest team members into the CalendarEventBuilder chain. Using the defensive || [] fallback ensures robustness, and the placement before .build() follows the established builder pattern.

packages/trpc/server/routers/viewer/eventTypes/types.ts (1)

89-92: LGTM! Schema definition correctly implements previous feedback.

The optionalGuestTeamMembers field is properly defined with both .nullable() and .optional() modifiers, which addresses the previous review feedback and maintains consistency with other optional fields in the schema. The array structure with id properties is appropriate for referencing team members.

packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts (1)

175-181: LGTM! Well-structured addition to support optional guest team members.

The addition of optionalGuestTeamMembers relation with appropriate field selection (name, email, id) follows the established pattern used for other user/member selections in this query. These fields provide the necessary data for downstream calendar invitation functionality.

packages/lib/server/repository/eventType.ts (1)

517-521: LGTM! Clean addition of optional guest team members to the selection.

The addition follows the existing pattern in the repository and appropriately selects only the id field for the optional guest team members, which aligns with the feature requirements.

packages/features/CalendarEventBuilder.ts (1)

264-275: LGTM! Well-implemented builder method following established patterns.

The new withOptionalGuestTeamMembers method correctly follows the builder pattern, handles the optional parameter appropriately by defaulting to an empty array, and maintains consistency with other methods in the class.

packages/platform/atoms/event-types/hooks/useEventTypeForm.ts (1)

58-58: LGTM! Consistent initialization pattern for optional guest team members.

The initialization follows the established pattern used for other optional array fields in the default values, ensuring the form always has a defined array for optionalGuestTeamMembers.

packages/features/eventtypes/components/tabs/advanced/EventAdvancedTab.tsx (2)

66-66: LGTM! Clean import addition for the new component.

The import follows the established pattern in the file.


1205-1207: LGTM! Proper conditional rendering with safe member access.

The conditional rendering correctly checks for both the existence of team?.members and its length before rendering the GuestTeamMemberController. This addresses the previous review concern about safe property access and follows React best practices.

packages/app-store/googlecalendar/lib/CalendarService.ts (1)

124-140: LGTM! Proper handling of optional guests.

The implementation correctly addresses the concerns from previous reviews:

  • Sets optional: true to properly mark guests as optional in Google Calendar
  • Filters out guests without email addresses
  • Deduplicates attendees using case-insensitive email comparison
  • Uses appropriate responseStatus: "needsAction" for optional guests
packages/app-store/feishucalendar/lib/CalendarService.ts (1)

402-446: LGTM! Excellent deduplication logic implementation.

The changes properly address the duplicate email issue by introducing separate sets to track mandatory and optional emails. The sequential processing ensures that:

  1. Main attendees are added as mandatory first
  2. Team members are added as mandatory only if not duplicates
  3. Optional guest team members are added only if not already present in either category

This implementation prevents the Feishu calendar service from receiving duplicate attendees with conflicting mandatory/optional status.

packages/app-store/exchange2013calendar/lib/CalendarService.ts (1)

83-87: Correct implementation for optional attendees.

The logic properly adds optional guest team members to the Exchange appointment's OptionalAttendees collection, ensuring they receive optional invitations without availability checks.

packages/prisma/schema.prisma (1)

333-333: Excellent fix for UTC timestamp handling.

The change from @default(now()) to @default(dbgenerated("now() AT TIME ZONE 'UTC'")) properly addresses the previous feedback about ensuring UTC timestamps in the database and follows the "Prevent Direct NOW() Usage in Database Queries" guideline.

packages/prisma/migrations/20250628001746_add_optional_guest_team_members/migration.sql (1)

1-17: Well-structured migration for many-to-many relation.

The migration correctly implements the join table for the optionalGuestTeamMembers relation with:

  • Proper foreign key constraints linking to EventType and users tables
  • CASCADE operations ensuring data integrity on deletions/updates
  • Appropriate indexes for performance (unique composite on A,B and single on B)
  • Standard Prisma naming convention for explicit many-to-many tables
packages/features/eventtypes/components/tabs/advanced/GuestTeamMemberController.tsx (2)

43-86: Well-structured UI implementation.

The component properly integrates with Cal.com's design system using SettingsToggle and CheckedTeamSelect. The conditional styling for rounded corners and responsive layout are well-implemented and follow established patterns.


17-92: Solid component implementation with good form integration.

The component demonstrates good practices:

  • Proper react-hook-form integration using Controller
  • Appropriate null checking and early return
  • State cleanup when disabling the feature (line 57)
  • Consistent naming with the form schema
packages/trpc/server/routers/viewer/eventTypes/update.handler.ts (3)

94-94: Proper default value assignment for optional guest team members.

The destructuring with default empty array ensures the field is always defined, preventing potential undefined reference errors in subsequent validation logic.


412-416: Host validation logic is correctly preserved.

The condition properly excludes organization sub-teams from strict host membership validation while maintaining security for regular teams. The logic correctly uses the negation to ensure all hosts are team members.


423-461: Enhanced hosts processing with proper array validation and comprehensive CRUD operations.

The refactored hosts logic introduces several improvements:

  1. Array validation: Added Array.isArray(hosts) check prevents runtime errors
  2. Efficient set operations: Uses Sets for O(1) lookups when categorizing hosts
  3. Comprehensive CRUD: Properly handles create, update, and delete operations for hosts
  4. Schedule ID handling: Added scheduleId to the update operation (line 457)

The implementation correctly handles the complex many-to-many relationship updates with proper Prisma operations.

Comment on lines +127 to +132
appointment.OptionalAttendees.Clear();
if (event.optionalGuestTeamMembers) {
event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
appointment.OptionalAttendees.Add(new Attendee(member.email));
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add email validation for consistency.

Apply the same email filtering logic here as suggested for the createEvent method.

      appointment.OptionalAttendees.Clear();
      if (event.optionalGuestTeamMembers) {
-        event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
+        event.optionalGuestTeamMembers.filter(member => !!member.email).forEach((member: { email: string }) => {
          appointment.OptionalAttendees.Add(new Attendee(member.email));
        });
      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
appointment.OptionalAttendees.Clear();
if (event.optionalGuestTeamMembers) {
event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
appointment.OptionalAttendees.Add(new Attendee(member.email));
});
}
appointment.OptionalAttendees.Clear();
if (event.optionalGuestTeamMembers) {
event.optionalGuestTeamMembers
.filter(member => !!member.email)
.forEach((member: { email: string }) => {
appointment.OptionalAttendees.Add(new Attendee(member.email));
});
}
🤖 Prompt for AI Agents
In packages/app-store/exchange2016calendar/lib/CalendarService.ts around lines
127 to 132, the code adds optional attendees without validating their email
addresses. To fix this, apply the same email validation logic used in the
createEvent method before adding each optional attendee. This ensures only valid
emails are added to appointment.OptionalAttendees.

Comment on lines +84 to +88
if (event.optionalGuestTeamMembers) {
event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
appointment.OptionalAttendees.Add(new Attendee(member.email));
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add email validation to prevent API errors.

Consider filtering out team members without email addresses before adding them as attendees to prevent potential Exchange API errors.

      if (event.optionalGuestTeamMembers) {
-        event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
+        event.optionalGuestTeamMembers.filter(member => !!member.email).forEach((member: { email: string }) => {
          appointment.OptionalAttendees.Add(new Attendee(member.email));
        });
      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (event.optionalGuestTeamMembers) {
event.optionalGuestTeamMembers.forEach((member: { email: string }) => {
appointment.OptionalAttendees.Add(new Attendee(member.email));
});
}
if (event.optionalGuestTeamMembers) {
event.optionalGuestTeamMembers
.filter(member => !!member.email)
.forEach((member: { email: string }) => {
appointment.OptionalAttendees.Add(new Attendee(member.email));
});
}
🤖 Prompt for AI Agents
In packages/app-store/exchange2016calendar/lib/CalendarService.ts around lines
84 to 88, the code adds optional guest team members as attendees without
validating their email addresses, which can cause API errors. Before adding each
member, check if the email property exists and is a valid non-empty string; only
add attendees with valid emails to prevent errors from the Exchange API.

Comment on lines +484 to +496
private getAttendees = (event: CalendarEvent) => {
const attendees = event.attendees.map((attendee) => ({ email: attendee.email }));
if (event.optionalGuestTeamMembers) {
attendees.push(
...event.optionalGuestTeamMembers.map((member) => ({
email: member.email,
// 2 is optional guest
attendance: 2,
}))
);
}
return attendees;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add email validation for robustness.

The refactoring into a separate method is excellent for maintainability. Consider adding email validation to prevent potential API errors when team members lack email addresses.

  private getAttendees = (event: CalendarEvent) => {
    const attendees = event.attendees.map((attendee) => ({ email: attendee.email }));
    if (event.optionalGuestTeamMembers) {
      attendees.push(
-        ...event.optionalGuestTeamMembers.map((member) => ({
+        ...event.optionalGuestTeamMembers.filter(member => !!member.email).map((member) => ({
          email: member.email,
          // 2 is optional guest
          attendance: 2,
        }))
      );
    }
    return attendees;
  };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private getAttendees = (event: CalendarEvent) => {
const attendees = event.attendees.map((attendee) => ({ email: attendee.email }));
if (event.optionalGuestTeamMembers) {
attendees.push(
...event.optionalGuestTeamMembers.map((member) => ({
email: member.email,
// 2 is optional guest
attendance: 2,
}))
);
}
return attendees;
};
private getAttendees = (event: CalendarEvent) => {
const attendees = event.attendees.map((attendee) => ({ email: attendee.email }));
if (event.optionalGuestTeamMembers) {
attendees.push(
...event.optionalGuestTeamMembers.filter(member => !!member.email).map((member) => ({
email: member.email,
// 2 is optional guest
attendance: 2,
}))
);
}
return attendees;
};
🤖 Prompt for AI Agents
In packages/app-store/zohocalendar/lib/CalendarService.ts around lines 484 to
496, the getAttendees method currently maps attendees and
optionalGuestTeamMembers without validating their email addresses. To fix this,
add a check to ensure each attendee and optional guest team member has a valid,
non-empty email before including them in the returned array. This validation
will prevent potential API errors caused by missing or invalid emails.

Comment on lines +396 to +408
if (optionalGuestTeamMembers && optionalGuestTeamMembers.length > 0) {
if (optionalGuestTeamMembers.every((each) => teamMemberIds.includes(each.id))) {
data.optionalGuestTeamMembers = {
set: [],
connect: optionalGuestTeamMembers.map(({ id }) => ({ id })),
};
} else {
throw new TRPCError({
code: "FORBIDDEN",
message: "You can only assign team members as optional guests.",
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Validate optional guest team members authorization and data integrity.

The validation logic correctly ensures that only accepted team members can be assigned as optional guests. However, consider the edge case where optionalGuestTeamMembers might contain duplicate IDs.


🏁 Script executed:

#!/bin/bash
# Description: Check if there are any deduplication mechanisms for optionalGuestTeamMembers in the schema or input validation
# Expected: Find validation logic that prevents duplicate IDs in the array

# Search for optionalGuestTeamMembers schema validation
ast-grep --pattern 'optionalGuestTeamMembers: $_'

# Look for array deduplication patterns in the codebase
rg -A 3 -B 3 "optionalGuestTeamMembers.*unique|unique.*optionalGuestTeamMembers"

Length of output: 134


Enforce deduplication for optionalGuestTeamMembers

No existing check prevents duplicate IDs in the optionalGuestTeamMembers array. Add a guard to reject or dedupe duplicates before connecting.

• File:
packages/trpc/server/routers/viewer/eventTypes/update.handler.ts (around lines 396–408)

Suggested diff:

     if (optionalGuestTeamMembers && optionalGuestTeamMembers.length > 0) {
+      // Deduplicate IDs to prevent duplicate connections
+      const ids = optionalGuestTeamMembers.map(({ id }) => id);
+      const uniqueIds = [...new Set(ids)];
+      if (uniqueIds.length !== ids.length) {
+        throw new TRPCError({
+          code: "BAD_REQUEST",
+          message: "Duplicate optional guest team members are not allowed.",
+        });
+      }
       if (optionalGuestTeamMembers.every((each) => teamMemberIds.includes(each.id))) {
-        data.optionalGuestTeamMembers = {
-          set: [],
-          connect: optionalGuestTeamMembers.map(({ id }) => ({ id })),
-        };
+        data.optionalGuestTeamMembers = {
+          set: [],
+          connect: uniqueIds.map((id) => ({ id })),
+        };
       } else {
         throw new TRPCError({
           code: "FORBIDDEN",
           message: "You can only assign team members as optional guests.",
         });
       }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (optionalGuestTeamMembers && optionalGuestTeamMembers.length > 0) {
if (optionalGuestTeamMembers.every((each) => teamMemberIds.includes(each.id))) {
data.optionalGuestTeamMembers = {
set: [],
connect: optionalGuestTeamMembers.map(({ id }) => ({ id })),
};
} else {
throw new TRPCError({
code: "FORBIDDEN",
message: "You can only assign team members as optional guests.",
});
}
}
if (optionalGuestTeamMembers && optionalGuestTeamMembers.length > 0) {
// Deduplicate IDs to prevent duplicate connections
const ids = optionalGuestTeamMembers.map(({ id }) => id);
const uniqueIds = [...new Set(ids)];
if (uniqueIds.length !== ids.length) {
throw new TRPCError({
code: "BAD_REQUEST",
message: "Duplicate optional guest team members are not allowed.",
});
}
if (optionalGuestTeamMembers.every((each) => teamMemberIds.includes(each.id))) {
data.optionalGuestTeamMembers = {
set: [],
connect: uniqueIds.map((id) => ({ id })),
};
} else {
throw new TRPCError({
code: "FORBIDDEN",
message: "You can only assign team members as optional guests.",
});
}
}
🤖 Prompt for AI Agents
In packages/trpc/server/routers/viewer/eventTypes/update.handler.ts around lines
396 to 408, the code does not check for duplicate IDs in the
optionalGuestTeamMembers array. Add a validation step before the existing checks
to either reject the input if duplicates are found or remove duplicates from
optionalGuestTeamMembers. This can be done by creating a Set of IDs and
comparing its size to the array length or by filtering duplicates out. Ensure
this deduplication or validation happens before setting
data.optionalGuestTeamMembers.

@github-actions github-actions bot removed the Stale label Jul 20, 2025
@kart1ka
Copy link
Contributor

kart1ka commented Jul 24, 2025

Hi @jayantpranjal0, could you pls add a loom showing your feature and resolve merge conflicts and coderabbit comments as well? Making it draft. Feel free to rfr once the comments are addressed.

@kart1ka kart1ka marked this pull request as draft July 24, 2025 14:44
@kart1ka
Copy link
Contributor

kart1ka commented Aug 13, 2025

Closing in favour of this #22651

@kart1ka kart1ka closed this Aug 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🙋 Bounty claim community Created by Linear-GitHub Sync event-types area: event types, event-types ✨ feature New feature or request Low priority Created by Linear-GitHub Sync ❗️ migrations contains migration files teams area: teams, round robin, collective, managed event-types $25

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CAL-5091] additional settings: "add team member as optional guest

5 participants