* 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>
100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
import { zodRoutes } from "@calcom/app-store/routing-forms/zod";
|
|
import prisma from "@calcom/prisma";
|
|
import { AssignmentReasonEnum } from "@calcom/prisma/enums";
|
|
|
|
import { RoutingReasons, SalesforceRecordEnum } from "./enums";
|
|
|
|
export async function assignmentReasonHandler({
|
|
recordType,
|
|
teamMemberEmail,
|
|
routingFormResponseId,
|
|
recordId,
|
|
}: {
|
|
recordType: string;
|
|
teamMemberEmail: string;
|
|
routingFormResponseId: number;
|
|
recordId?: string;
|
|
}) {
|
|
const returnObject = { reasonEnum: AssignmentReasonEnum.SALESFORCE_ASSIGNMENT };
|
|
|
|
switch (recordType) {
|
|
case SalesforceRecordEnum.CONTACT:
|
|
return {
|
|
...returnObject,
|
|
assignmentReason: `Salesforce contact owner: ${teamMemberEmail}${
|
|
recordId ? ` (Contact ID: ${recordId})` : ""
|
|
}`,
|
|
};
|
|
case SalesforceRecordEnum.LEAD:
|
|
return {
|
|
...returnObject,
|
|
assignmentReason: `Salesforce lead owner: ${teamMemberEmail}${
|
|
recordId ? ` (Lead ID: ${recordId})` : ""
|
|
}`,
|
|
};
|
|
case SalesforceRecordEnum.ACCOUNT:
|
|
return {
|
|
...returnObject,
|
|
assignmentReason: `Salesforce account owner: ${teamMemberEmail}${
|
|
recordId ? ` (Account ID: ${recordId})` : ""
|
|
}`,
|
|
};
|
|
case RoutingReasons.ACCOUNT_LOOKUP_FIELD:
|
|
const assignmentReason = await handleAccountLookupFieldReason(
|
|
routingFormResponseId,
|
|
teamMemberEmail,
|
|
recordId
|
|
);
|
|
return { ...returnObject, assignmentReason };
|
|
}
|
|
}
|
|
|
|
async function handleAccountLookupFieldReason(
|
|
routingFormResponseId: number,
|
|
teamMemberEmail: string,
|
|
recordId?: string
|
|
) {
|
|
const routingFormResponse = await prisma.app_RoutingForms_FormResponse.findUnique({
|
|
where: {
|
|
id: routingFormResponseId,
|
|
},
|
|
select: {
|
|
chosenRouteId: true,
|
|
form: {
|
|
select: {
|
|
routes: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!routingFormResponse) return;
|
|
|
|
const { form } = routingFormResponse;
|
|
if (!form.routes) return;
|
|
|
|
const parsedRoutes = zodRoutes.safeParse(form.routes);
|
|
|
|
if (!parsedRoutes.success || !parsedRoutes.data) return;
|
|
|
|
const chosenRouteId = routingFormResponse.chosenRouteId;
|
|
|
|
const takenRoute = parsedRoutes.data.find((route) => route.id === chosenRouteId);
|
|
|
|
if (!takenRoute || !("attributeRoutingConfig" in takenRoute)) return;
|
|
|
|
const attributeRoutingConfig = takenRoute?.attributeRoutingConfig;
|
|
|
|
if (!attributeRoutingConfig) return;
|
|
|
|
const salesforceConfig = attributeRoutingConfig["salesforce"];
|
|
|
|
const accountLookupFieldName = salesforceConfig?.rrSKipToAccountLookupFieldName;
|
|
|
|
return accountLookupFieldName
|
|
? `Salesforce account lookup field: ${accountLookupFieldName} - ${teamMemberEmail}${
|
|
recordId ? ` (Account ID: ${recordId})` : ""
|
|
}`
|
|
: undefined;
|
|
}
|