-
Notifications
You must be signed in to change notification settings - Fork 10.3k
feat: include record IDs in Salesforce assignment reason strings #22561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: include record IDs in Salesforce assignment reason strings #22561
Conversation
- Add recordId parameter to assignmentReasonHandler function - Include Contact ID, Lead ID, and Account ID in assignment reason strings - Update entire call chain to pass record IDs from CRM service - Maintain backward compatibility with optional recordId parameter Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
WalkthroughThis change set introduces a new CRM-related identifier, 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
packages/app-store/routing-forms/lib/handleResponse.test.tsOops! 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:
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. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 2 Skipped Deployments
|
✅ No security or compliance issues detected. Reviewed everything up to 4746867. Security Overview
Detected Code Changes
Reply to this PR with |
- Change Record<string, any> to Record<string, unknown> in BookingHandlerInput type - Remove unused eventTypeId variable in getAttributeRoutingConfig function Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
…dlerInput - Revert from Record<string, unknown> to Record<string, any> to maintain type compatibility - Add ESLint disable comment to suppress no-explicit-any warning - Maintains consistency with handleNewRecurringBooking.ts pattern Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
- Add crmRecordId field to booker store interface and initialization - Update mapBookingToMutationInput to include record ID from booker state - Modify handleNewBooking to extract record ID from bookingData parameter - Add crmRecordId to BookingCreateBody schema in Prisma layer - Follow existing pattern for CRM fields (teamMemberEmail, crmOwnerRecordType, crmAppSlug) - Ensures record ID flows: booker store → booking form → mapBookingToMutationInput → handleNewBooking This replaces the previous backend CRM service extraction approach with frontend booker state approach as requested by the user. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (07/17/25)1 reviewer was added to this PR based on Keith Williams's automation. "Add ready-for-e2e label" took an action on this PR • (07/18/25)1 label was added to this PR based on Keith Williams's automation. "Add foundation team as reviewer" took an action on this PR • (07/18/25)1 reviewer was added to this PR based on Keith Williams's automation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (20)
apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/queries.ts
(3 hunks)apps/web/lib/__tests__/getTeamMemberEmailFromCrm.test.ts
(1 hunks)apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx
(5 hunks)apps/web/modules/team/type-view.tsx
(2 hunks)packages/app-store/_utils/CRMRoundRobinSkip.ts
(2 hunks)packages/app-store/routing-forms/lib/crmRouting/routerGetCrmContactOwnerEmail.ts
(1 hunks)packages/app-store/routing-forms/lib/handleResponse.ts
(3 hunks)packages/app-store/salesforce/lib/assignmentReasonHandler.ts
(2 hunks)packages/app-store/salesforce/lib/routingFormBookingFormHandler.ts
(2 hunks)packages/features/bookings/Booker/store.ts
(8 hunks)packages/features/bookings/Booker/types.ts
(1 hunks)packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx
(3 hunks)packages/features/bookings/lib/handleNewBooking.ts
(3 hunks)packages/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder.ts
(1 hunks)packages/features/ee/round-robin/assignmentReason/appAssignmentReasonHandler.ts
(1 hunks)packages/lib/server/getTeamMemberEmailFromCrm.ts
(6 hunks)packages/platform/atoms/booker/BookerPlatformWrapper.tsx
(1 hunks)packages/platform/atoms/booker/BookerWebWrapper.tsx
(0 hunks)packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts
(2 hunks)packages/prisma/zod/custom/booking.ts
(1 hunks)
💤 Files with no reviewable changes (1)
- packages/platform/atoms/booker/BookerWebWrapper.tsx
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
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/ee/round-robin/assignmentReason/appAssignmentReasonHandler.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/platform/atoms/hooks/bookings/useHandleBookEvent.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/app-store/routing-forms/lib/crmRouting/routerGetCrmContactOwnerEmail.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.
apps/web/modules/team/type-view.tsx (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/book-event-form/booking-to-mutation-input-mapper.tsx (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/app-store/routing-forms/lib/handleResponse.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/prisma/zod/custom/booking.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: eunjae-lee
PR: calcom/cal.com#22106
File: packages/lib/server/service/insightsRouting.ts:367-368
Timestamp: 2025-07-15T13:02:17.359Z
Learning: In the InsightsRoutingService (packages/lib/server/service/insightsRouting.ts), multi-select filter data is already validated by zod before reaching the buildFormFieldSqlCondition method, so null/undefined values are not present in filterValue.data arrays and don't need to be filtered out.
packages/platform/atoms/booker/BookerPlatformWrapper.tsx (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/ee/round-robin/assignmentReason/AssignmentReasonRecorder.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/app-store/salesforce/lib/routingFormBookingFormHandler.ts (3)
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: eunjae-lee
PR: calcom/cal.com#22106
File: packages/lib/server/service/insightsRouting.ts:367-368
Timestamp: 2025-07-15T13:02:17.359Z
Learning: In the InsightsRoutingService (packages/lib/server/service/insightsRouting.ts), multi-select filter data is already validated by zod before reaching the buildFormFieldSqlCondition method, so null/undefined values are not present in filterValue.data arrays and don't need to be filtered out.
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/RoutingFunnel.tsx:15-17
Timestamp: 2025-07-15T12:58:40.497Z
Learning: In the insights routing funnel component (packages/features/insights/components/RoutingFunnel.tsx), the useColumnFilters exclusions are intentionally different from the general useInsightsParameters exclusions. RoutingFunnel specifically excludes only ["createdAt"] while useInsightsParameters excludes ["bookingUserId", "formId", "createdAt", "eventTypeId"]. This difference is by design.
packages/features/bookings/lib/handleNewBooking.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/app-store/salesforce/lib/assignmentReasonHandler.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/lib/server/getTeamMemberEmailFromCrm.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.
🧬 Code Graph Analysis (2)
packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts (1)
packages/features/bookings/Booker/store.ts (1)
useBookerStore
(179-444)
packages/app-store/salesforce/lib/routingFormBookingFormHandler.ts (2)
packages/lib/server/service/eventType.ts (1)
EventTypeService
(7-34)packages/lib/server/repository/credential.ts (1)
CredentialRepository
(29-232)
🪛 Biome (1.9.4)
packages/app-store/salesforce/lib/assignmentReasonHandler.ts
[error] 43-47: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Tests / Unit
- GitHub Check: Type check / check-types
- GitHub Check: Security Check
🔇 Additional comments (58)
packages/features/bookings/Booker/types.ts (1)
103-103
: LGTM! Consistent type definition.The
crmRecordId
field follows the same pattern as other CRM-related fields in the interface, with appropriate optional and nullable typing.packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts (2)
65-65
: LGTM! Consistent state selector pattern.The
crmRecordId
state selector follows the same pattern as other CRM fields extracted from the booker store.
112-112
: LGTM! Proper inclusion in booking input.The
crmRecordId
is correctly included in the booking input object, maintaining consistency with other CRM fields.packages/prisma/zod/custom/booking.ts (1)
26-26
: LGTM! Proper Zod schema definition.The
crmRecordId
field is correctly defined using.nullish()
which appropriately handles null, undefined, and string values. The positioning with other CRM fields maintains good organization.packages/features/ee/round-robin/assignmentReason/appAssignmentReasonHandler.ts (1)
8-8
: LGTM! Consistent type definition and parameter handling.The
recordId
parameter is properly added to both the destructured parameters and the type definition, maintaining consistency and type safety.Also applies to: 13-13
apps/web/lib/__tests__/getTeamMemberEmailFromCrm.test.ts (1)
32-32
: LGTM! Proper test mock updates.The mock responses are correctly updated to include
recordId: null
, maintaining consistency with the updated function interface while preserving test validity.Also applies to: 34-34
packages/app-store/routing-forms/lib/crmRouting/routerGetCrmContactOwnerEmail.ts (1)
43-53
: LGTM! Clean addition of recordId field.The
recordId
field is properly added to thecontactOwner
object type and initialized consistently with the existing CRM fields. The nullable string type aligns with the pattern used for other CRM properties.apps/web/modules/team/type-view.tsx (2)
37-37
: LGTM! Proper prop addition for crmRecordId.The
crmRecordId
prop is correctly added to the destructuring, following the established pattern for other CRM-related props.
68-68
: LGTM! Consistent prop passing to Booker component.The
crmRecordId
is properly passed to the Booker component alongside other CRM fields, maintaining consistency with the existing prop structure.packages/app-store/routing-forms/lib/handleResponse.ts (3)
99-99
: LGTM! Proper initialization of crmRecordId.The
crmRecordId
variable is correctly initialized asnull
, following the consistent pattern established for other CRM-related fields.
123-123
: LGTM! Safe assignment using optional chaining.The assignment properly uses optional chaining and nullish coalescing to safely extract the
recordId
from thecontactOwnerQuery
, maintaining null safety.
217-217
: LGTM! Consistent inclusion in return object.The
crmRecordId
is properly included in the returned object, maintaining consistency with the other CRM fields and ensuring the value is propagated to callers.packages/platform/atoms/booker/BookerPlatformWrapper.tsx (1)
161-161
: LGTM! Proper integration into booker store initialization.The
crmRecordId
prop is correctly passed to theuseInitializeBookerStore
hook, following the established pattern for other CRM-related fields. The explicit extraction fromprops.crmRecordId
ensures type safety and clarity.packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx (3)
30-30
: LGTM! Consistent type extension for crmRecordId.The
crmRecordId
field is properly added to theBookingOptions
type with the correct optional nullable string type, matching the pattern used for other CRM-related fields.
53-53
: LGTM! Proper parameter addition to function signature.The
crmRecordId
parameter is correctly added to themapBookingToMutationInput
function signature, maintaining consistency with the parameter order and naming conventions.
91-91
: LGTM! Consistent inclusion in mutation input.The
crmRecordId
is properly included in the returned mutation input object, ensuring the field is propagated through the booking flow to the backend handlers.packages/app-store/salesforce/lib/routingFormBookingFormHandler.ts (3)
19-19
: LGTM: Consistent addition of recordId fieldThe addition of
recordId: null
to the early return statement maintains consistency with the updated return type and aligns with the PR's objective of setting up the data flow plumbing.
27-27
: LGTM: Consistent addition of recordId fieldThe addition of
recordId: null
to the credential validation failure return maintains consistency with the updated return type.
37-42
: LGTM: Consistent addition of recordId fieldThe final return statement now includes
recordId: null
, maintaining consistency with the updated return type. This aligns with the PR's current implementation where actual record ID population is not yet implemented.packages/features/bookings/lib/handleNewBooking.ts (3)
381-381
: LGTM: Appropriate ESLint disable commentThe ESLint disable comment for explicit
any
type is appropriate given the existingRecord<string, any>
type forbookingData
property.
601-601
: LGTM: Consistent field extraction patternThe extraction of
crmRecordId
follows the same pattern as other fields in the function, with proper undefined fallback handling.
1395-1403
: LGTM: Correct parameter passing to assignment reason recorderThe
crmRecordId
is correctly passed as therecordId
parameter to theAssignmentReasonRecorder.CRMOwnership
method, maintaining consistency with the updated method signature.packages/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder.ts (2)
146-160
: LGTM: Proper addition of optional recordId parameterThe method signature correctly adds the optional
recordId
parameter with proper TypeScript typing (recordId?: string
). The parameter is properly destructured and will be passed to the app handler.
165-170
: LGTM: Correct parameter forwarding to app handlerThe
recordId
parameter is correctly passed to theappHandler
call, maintaining the data flow as intended by the PR.apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/queries.ts (5)
125-125
: LGTM: Consistent query parameter extractionThe extraction of
cal.crmRecordId
parameter follows the same pattern as other CRM-related parameters in the function.
132-132
: LGTM: Proper array handling for query parameterThe array handling for
crmRecordIdParam
is consistent with the pattern used for other query parameters in this function.
142-142
: LGTM: Correct destructuring of recordId from imported functionThe destructuring of
recordId
ascrmRecordIdQuery
from the imported function result is correct and follows the established pattern.
151-151
: LGTM: Proper fallback assignmentThe fallback assignment of
crmRecordId
from the imported function result follows the same pattern as other CRM fields.
158-158
: LGTM: Correct inclusion in return objectThe
crmRecordId
field is properly included in the return object, maintaining consistency with the function's purpose.packages/app-store/_utils/CRMRoundRobinSkip.ts (3)
13-18
: LGTM: Proper return type extensionThe return type is correctly extended to include the optional
recordId
field, maintaining consistency with the existing nullable string pattern for CRM-related fields.
19-19
: LGTM: Consistent null return valueThe
nullReturnValue
is properly updated to includerecordId: null
, maintaining consistency with the updated return type.
32-37
: LGTM: Correct recordId extraction from contactThe
recordId
field is correctly extracted fromcontact[0].id
with proper null handling using the nullish coalescing operator, following the same pattern as other fields in the return object.apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx (5)
95-95
: LGTM: Consistent parameter extraction patternThe new
crmRecordIdParam
extraction follows the same pattern as other CRM-related query parameters.
105-105
: LGTM: Proper array handling for query parametersThe array normalization logic is consistent with the handling of other CRM parameters above.
115-115
: LGTM: Consistent destructuring patternThe
recordId
destructuring is properly added to match the updated return type from the CRM utility function.
124-124
: LGTM: Fallback assignment logicThe fallback assignment follows the same pattern as other CRM fields, ensuring consistency in the data flow.
174-174
: LGTM: Props inclusionThe
crmRecordId
is properly included in the returned props, maintaining consistency with other CRM-related fields.packages/features/bookings/Booker/store.ts (8)
39-39
: LGTM: Type definition updated correctlyThe
crmRecordId
field is properly added to theStoreInitializeType
interface with the correct optional string type.
167-167
: LGTM: Store interface updatedThe
crmRecordId
field is consistently added to theBookerStore
interface.
311-311
: LGTM: Initialize function parameter addedThe
crmRecordId
parameter is properly added to the initialize function signature.
330-331
: LGTM: Equality check updatedThe equality check now includes
crmRecordId
to prevent unnecessary store re-initialization, which is important for performance.
354-354
: LGTM: State update includes new fieldThe
crmRecordId
is properly included in the state update when the store is initialized.
464-464
: LGTM: Hook parameter addedThe
crmRecordId
parameter is properly added to theuseInitializeBookerStore
hook.
488-488
: LGTM: Hook call updatedThe
crmRecordId
is properly passed to the store initialization call.
511-511
: LGTM: Dependency array updatedThe
crmRecordId
is correctly added to the dependency array to ensure the hook re-runs when the value changes.packages/app-store/salesforce/lib/assignmentReasonHandler.ts (6)
11-11
: LGTM: Function signature updated correctlyThe
recordId
parameter is properly added as an optional field to maintain backward compatibility.Also applies to: 16-16
22-27
: LGTM: Contact assignment reason enhancedThe assignment reason string now conditionally includes the Contact ID when available, providing better traceability.
29-34
: LGTM: Lead assignment reason enhancedThe assignment reason string now conditionally includes the Lead ID when available, consistent with the Contact case.
36-41
: LGTM: Account assignment reason enhancedThe assignment reason string now conditionally includes the Account ID when available, maintaining consistency across record types.
52-56
: LGTM: Helper function signature updatedThe
handleAccountLookupFieldReason
function signature is properly updated to include the optionalrecordId
parameter.
95-97
: LGTM: Account lookup field reason enhancedThe assignment reason string now conditionally includes the Account ID when available, consistent with other record types.
packages/lib/server/getTeamMemberEmailFromCrm.ts (7)
24-24
: LGTM: Null return value updatedThe
returnNullValue
constant is properly updated to includerecordId: null
, ensuring consistency across all return paths.
120-125
: LGTM: Return type updated for getOwnerEmailFromCrmThe return type is properly updated to include the
recordId
field, maintaining consistency with other CRM-related functions.
206-211
: LGTM: Return type updated for getTeamMemberEmailForResponseOrContactThe return type consistently includes the
recordId
field across all CRM lookup functions.
228-235
: LGTM: Destructuring updated to include recordIdThe destructuring properly includes
recordId
from the routing form handler result.
238-238
: LGTM: Return statement includes recordIdThe return statement is properly updated to include
recordId
in the response object.
255-260
: LGTM: Export function return type updatedThe exported function's return type is consistently updated to include
recordId
, completing the type propagation.
60-60
: LGTM: Cleanup of unused variableGood cleanup by removing the unused
eventTypeId
from the destructuring assignment.
const assignmentReason = await handleAccountLookupFieldReason( | ||
routingFormResponseId, | ||
teamMemberEmail, | ||
recordId | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix switch clause variable declaration issue
The static analysis tool correctly identifies a potential issue with variable declaration in the switch clause.
Apply this fix to wrap the variable declaration in a block:
case RoutingReasons.ACCOUNT_LOOKUP_FIELD:
- const assignmentReason = await handleAccountLookupFieldReason(
- routingFormResponseId,
- teamMemberEmail,
- recordId
- );
+ {
+ const assignmentReason = await handleAccountLookupFieldReason(
+ routingFormResponseId,
+ teamMemberEmail,
+ recordId
+ );
+ return { ...returnObject, assignmentReason };
+ }
- return { ...returnObject, assignmentReason };
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const assignmentReason = await handleAccountLookupFieldReason( | |
routingFormResponseId, | |
teamMemberEmail, | |
recordId | |
); | |
case RoutingReasons.ACCOUNT_LOOKUP_FIELD: | |
{ | |
const assignmentReason = await handleAccountLookupFieldReason( | |
routingFormResponseId, | |
teamMemberEmail, | |
recordId | |
); | |
return { ...returnObject, assignmentReason }; | |
} |
🧰 Tools
🪛 Biome (1.9.4)
[error] 43-47: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🤖 Prompt for AI Agents
In packages/app-store/salesforce/lib/assignmentReasonHandler.ts around lines 43
to 47, the switch statement has a variable declaration that may cause issues due
to scoping rules. To fix this, wrap the code inside each case of the switch
statement in curly braces to create a block scope for the variable declarations,
preventing redeclaration or scope leakage errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too many files had to be modified to add a single query param, but ok for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/lib/__tests__/getTeamMemberEmailFromCrm.test.ts
(2 hunks)packages/app-store/routing-forms/appBookingFormHandler.ts
(1 hunks)packages/lib/server/getTeamMemberEmailFromCrm.ts
(9 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/lib/tests/getTeamMemberEmailFromCrm.test.ts
- packages/lib/server/getTeamMemberEmailFromCrm.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
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/routing-forms/appBookingFormHandler.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.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Install dependencies / Yarn install & cache
- GitHub Check: Security Check
@@ -5,7 +5,7 @@ type AppBookingFormHandler = ( | |||
attendeeEmail: string, | |||
attributeRoutingConfig: AttributeRoutingConfig, | |||
eventTypeId: number | |||
) => Promise<{ email: string | null; recordType: string | null }>; | |||
) => Promise<{ email: string | null; recordType: string | null; recordId: string | null }>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify naming consistency and implementation updates.
The addition of recordId
to the return type is consistent with the CRM integration effort. However, there's a potential naming inconsistency - this property is named recordId
while other parts of the codebase use crmRecordId
. Also, ensure that all implementing handlers (currently routingFormBookingFormHandler
) have been updated to return the new recordId
property.
🏁 Script executed:
#!/bin/bash
# Verify that the Salesforce handler returns recordId and check for naming consistency
echo "Checking if routingFormBookingFormHandler returns recordId:"
ast-grep --pattern 'function routingFormBookingFormHandler($$$) {
$$$
return {
$$$
recordId: $$$
$$$
}
$$$
}'
echo -e "\nChecking for other references to recordId vs crmRecordId:"
rg -A 3 -B 3 "recordId.*string.*null|crmRecordId.*string.*null"
Length of output: 7864
Unify CRM record ID naming and update handler implementation.
The new recordId
field must be returned by the Salesforce handler and named consistently across the codebase. Right now some modules use recordId
(e.g. appBookingFormHandler.ts
, routerGetCrmContactOwnerEmail.ts
, CRMRoundRobinSkip.ts
, getTeamMemberEmailFromCrm.ts
), while others use crmRecordId
(e.g. handleResponse.ts
, Zod schema in prisma/zod/custom/booking.ts
, and several frontend stores/types).
Please:
- Choose one naming convention (we recommend
crmRecordId
for clarity) and apply it everywhere. - Update the return type in
packages/app-store/routing-forms/appBookingFormHandler.ts
accordingly:-) => Promise<{ email: string | null; recordType: string | null; recordId: string | null }>; +) => Promise<{ email: string | null; recordType: string | null; crmRecordId: string | null }>;
- Ensure the Salesforce implementation (
routingFormBookingFormHandler
inpackages/app-store/routing-forms/...
) actually returns the renamed field. - Refactor other references as needed:
•packages/app-store/routing-forms/lib/crmRouting/routerGetCrmContactOwnerEmail.ts
•packages/app-store/_utils/CRMRoundRobinSkip.ts
•packages/lib/server/getTeamMemberEmailFromCrm.ts
•packages/app-store/routing-forms/lib/handleResponse.ts
•packages/prisma/zod/custom/booking.ts
• Frontend stores/types inpackages/features/bookings/Booker/…
📝 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.
) => Promise<{ email: string | null; recordType: string | null; recordId: string | null }>; | |
) => Promise<{ email: string | null; recordType: string | null; crmRecordId: string | null }>; |
🤖 Prompt for AI Agents
In packages/app-store/routing-forms/appBookingFormHandler.ts at line 8, the
return type uses the field name recordId, which is inconsistent with other parts
of the codebase that use crmRecordId. Rename the return type field from recordId
to crmRecordId. Then, update the Salesforce handler implementation in
routingFormBookingFormHandler to return crmRecordId instead of recordId.
Finally, refactor all other references to this field in the listed files and
frontend stores/types to use crmRecordId consistently throughout the codebase.
E2E results are ready! |
) * feat: include record IDs in Salesforce assignment reason strings - Add recordId parameter to assignmentReasonHandler function - Include Contact ID, Lead ID, and Account ID in assignment reason strings - Update entire call chain to pass record IDs from CRM service - Maintain backward compatibility with optional recordId parameter Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: resolve lint warnings in assignment reason handler implementation - Change Record<string, any> to Record<string, unknown> in BookingHandlerInput type - Remove unused eventTypeId variable in getAttributeRoutingConfig function Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * fix: revert to Record<string, any> with ESLint disable for BookingHandlerInput - Revert from Record<string, unknown> to Record<string, any> to maintain type compatibility - Add ESLint disable comment to suppress no-explicit-any warning - Maintains consistency with handleNewRecurringBooking.ts pattern Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * feat: pass CRM record ID from booker state to handleNewBooking - Add crmRecordId field to booker store interface and initialization - Update mapBookingToMutationInput to include record ID from booker state - Modify handleNewBooking to extract record ID from bookingData parameter - Add crmRecordId to BookingCreateBody schema in Prisma layer - Follow existing pattern for CRM fields (teamMemberEmail, crmOwnerRecordType, crmAppSlug) - Ensures record ID flows: booker store → booking form → mapBookingToMutationInput → handleNewBooking This replaces the previous backend CRM service extraction approach with frontend booker state approach as requested by the user. Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Pass crmRecordId as prop --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com>
feat: pass CRM record ID from booker state to handleNewBooking
Note that the CRM functions were already returning the record id, this PR now just takes that id from
getServerSideProps
tohandleNewBooking
Summary
This PR implements the requested change to pass CRM record IDs from the booker state through to
handleNewBooking
instead of extracting them in the backend CRM service layer. The record ID now flows through the booking data parameter following the same pattern as other CRM fields (teamMemberEmail
,crmOwnerRecordType
,crmAppSlug
).Key Changes:
crmRecordId
field to booker store interface and initializationcrmRecordId
from booker state → booking form →mapBookingToMutationInput
→handleNewBooking
handleNewBooking
to extractcrmRecordId
from request body and pass it to assignment reason handlerscrmRecordId
to Prisma booking schema validationReview & Testing Checklist for Human
crmRecordId
in the booker state with real CRM record IDs (currently it's undefined/null)crmRecordId
is not providedstring | null | undefined
tostring | undefined
Recommended Test Plan:
crmRecordId
in booker state and verify it appears in assignment reasonsDiagram
Notes
Important: The current implementation creates the data flow plumbing but doesn't actually populate
crmRecordId
with real data - it remains undefined/null throughout. The upstream CRM integration logic that would set the record ID in the booker state still needs to be implemented.This change was requested by joe@cal.com (@joeauyeung) to move record ID handling from backend CRM service extraction to frontend booker state approach.
Link to Devin run: https://app.devin.ai/sessions/20cb4c4e57224b63bb0efe508ca34dec