feat: Salesforce - pass company booking response to the Lead field (#17860)
* Catch undefined app option properties * Add `getCompanyNameFromBookingResponse` method * Pass bookingResponse when Lead is being created * Pass bookingResponse from CRMManager * Handle empty company response * Return the company value
This commit is contained in:
@@ -431,7 +431,11 @@ export default class SalesforceCRMService implements CRM {
|
||||
: [];
|
||||
}
|
||||
|
||||
async createContacts(contactsToCreate: Attendee[], organizerEmail?: string) {
|
||||
async createContacts(
|
||||
contactsToCreate: Attendee[],
|
||||
organizerEmail?: string,
|
||||
calEventResponses?: CalEventResponses | null
|
||||
) {
|
||||
const conn = await this.conn;
|
||||
const appOptions = this.getAppOptions();
|
||||
const createEventOn = appOptions.createEventOn ?? SalesforceRecordEnum.CONTACT;
|
||||
@@ -474,11 +478,14 @@ export default class SalesforceCRMService implements CRM {
|
||||
}
|
||||
}
|
||||
|
||||
await this.createAttendeeRecord({ attendee, recordType: SalesforceRecordEnum.LEAD, organizerId }).then(
|
||||
(result) => {
|
||||
createdContacts.push(...result);
|
||||
}
|
||||
);
|
||||
await this.createAttendeeRecord({
|
||||
attendee,
|
||||
recordType: SalesforceRecordEnum.LEAD,
|
||||
organizerId,
|
||||
calEventResponses,
|
||||
}).then((result) => {
|
||||
createdContacts.push(...result);
|
||||
});
|
||||
}
|
||||
|
||||
if (createEventOn === SalesforceRecordEnum.ACCOUNT) {
|
||||
@@ -522,6 +529,7 @@ export default class SalesforceCRMService implements CRM {
|
||||
attendee,
|
||||
recordType: SalesforceRecordEnum.LEAD,
|
||||
organizerId,
|
||||
calEventResponses,
|
||||
})
|
||||
);
|
||||
if (result.success) {
|
||||
@@ -547,7 +555,7 @@ export default class SalesforceCRMService implements CRM {
|
||||
|
||||
async handleAttendeeNoShow(bookingUid: string, attendees: { email: string; noShow: boolean }[]) {
|
||||
const appOptions = this.getAppOptions();
|
||||
const { sendNoShowAttendeeData, sendNoShowAttendeeDataField } = appOptions;
|
||||
const { sendNoShowAttendeeData = false, sendNoShowAttendeeDataField = {} } = appOptions;
|
||||
const conn = await this.conn;
|
||||
// Check that no show is enabled
|
||||
if (!sendNoShowAttendeeData && !sendNoShowAttendeeDataField) {
|
||||
@@ -670,11 +678,13 @@ export default class SalesforceCRMService implements CRM {
|
||||
recordType,
|
||||
organizerId,
|
||||
accountId,
|
||||
calEventResponses,
|
||||
}: {
|
||||
attendee: Attendee;
|
||||
recordType: SalesforceRecordEnum;
|
||||
organizerId?: string;
|
||||
accountId?: string;
|
||||
calEventResponses?: CalEventResponses | null;
|
||||
}) {
|
||||
const conn = await this.conn;
|
||||
|
||||
@@ -685,6 +695,7 @@ export default class SalesforceCRMService implements CRM {
|
||||
attendee,
|
||||
recordType: recordType,
|
||||
organizerId,
|
||||
calEventResponses,
|
||||
}),
|
||||
AccountId: accountId,
|
||||
})
|
||||
@@ -705,16 +716,19 @@ export default class SalesforceCRMService implements CRM {
|
||||
attendee,
|
||||
recordType,
|
||||
organizerId,
|
||||
calEventResponses,
|
||||
}: {
|
||||
attendee: { email: string; name: string };
|
||||
recordType: SalesforceRecordEnum;
|
||||
organizerId?: string;
|
||||
/**Only Leads have the default company field */
|
||||
calEventResponses?: CalEventResponses | null;
|
||||
}) {
|
||||
const [FirstName, LastName] = attendee.name ? attendee.name.split(" ") : [attendee.email, ""];
|
||||
|
||||
// Assume that the first part of the email domain is the company title
|
||||
const company = attendee.email.split("@")[1].split(".")[0];
|
||||
|
||||
const company =
|
||||
this.getCompanyNameFromBookingResponse(calEventResponses) ?? attendee.email.split("@")[1].split(".")[0];
|
||||
return {
|
||||
LastName: LastName || "-",
|
||||
FirstName,
|
||||
@@ -805,7 +819,7 @@ export default class SalesforceCRMService implements CRM {
|
||||
bookingUid?: string | null
|
||||
) {
|
||||
const conn = await this.conn;
|
||||
const { createEventOn, onBookingWriteToRecordFields } = this.getAppOptions();
|
||||
const { createEventOn, onBookingWriteToRecordFields = {} } = this.getAppOptions();
|
||||
|
||||
// Determine record type (Contact or Lead)
|
||||
const personRecordType = this.determinePersonRecordType(createEventOn);
|
||||
@@ -885,7 +899,6 @@ export default class SalesforceCRMService implements CRM {
|
||||
|
||||
return writeOnRecordBody;
|
||||
}
|
||||
|
||||
private getTextFieldValue({
|
||||
fieldValue,
|
||||
fieldLength,
|
||||
@@ -896,13 +909,12 @@ export default class SalesforceCRMService implements CRM {
|
||||
calEventResponses?: CalEventResponses | null;
|
||||
}) {
|
||||
let valueToWrite = fieldValue.substring(0, fieldLength);
|
||||
|
||||
if (!calEventResponses) return valueToWrite;
|
||||
|
||||
// Check if we need to replace any values with values from the booking questions
|
||||
const regexValueToReplace = /\{(.*?)\}/g;
|
||||
valueToWrite = valueToWrite.replace(regexValueToReplace, (match, captured) => {
|
||||
return calEventResponses[captured]?.value.toString() ?? match;
|
||||
return calEventResponses[captured]?.value ? calEventResponses[captured].value.toString() : match;
|
||||
});
|
||||
|
||||
// Trim incase the replacement values increased the length
|
||||
@@ -1038,4 +1050,27 @@ export default class SalesforceCRMService implements CRM {
|
||||
return { email: user.Email, recordType: RoutingReasons.ACCOUNT_LOOKUP_FIELD };
|
||||
}
|
||||
}
|
||||
|
||||
/** Search the booking questions for the Company field value rather than relying on the email domain */
|
||||
private getCompanyNameFromBookingResponse(calEventResponses?: CalEventResponses | null) {
|
||||
const appOptions = this.getAppOptions();
|
||||
const companyFieldName = "Company";
|
||||
const defaultTextValueLength = 225;
|
||||
|
||||
const { onBookingWriteToRecordFields = undefined } = appOptions;
|
||||
|
||||
if (!onBookingWriteToRecordFields || !calEventResponses) return;
|
||||
|
||||
// Check that we're writing to the Company field
|
||||
if (!(companyFieldName in onBookingWriteToRecordFields)) return;
|
||||
|
||||
const companyValue = this.getTextFieldValue({
|
||||
fieldValue: onBookingWriteToRecordFields[companyFieldName].value,
|
||||
fieldLength: defaultTextValueLength,
|
||||
calEventResponses,
|
||||
});
|
||||
|
||||
if (companyValue === onBookingWriteToRecordFields[companyFieldName]) return;
|
||||
return companyValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import getCrm from "@calcom/app-store/_utils/getCrm";
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
import type { CalendarEvent, CalEventResponses } from "@calcom/types/Calendar";
|
||||
import type { CredentialPayload } from "@calcom/types/Credential";
|
||||
import type { CRM, ContactCreateInput } from "@calcom/types/CrmService";
|
||||
|
||||
@@ -42,7 +42,11 @@ export default class CrmManager {
|
||||
const contactsToCreate = event.attendees.filter(
|
||||
(attendee) => !contacts.some((contact) => contact.email === attendee.email)
|
||||
);
|
||||
const createdContacts = await this.createContacts(contactsToCreate, event.organizer?.email);
|
||||
const createdContacts = await this.createContacts(
|
||||
contactsToCreate,
|
||||
event.organizer?.email,
|
||||
event.responses
|
||||
);
|
||||
contacts = contacts.concat(createdContacts);
|
||||
return await crmService?.createEvent(event, contacts);
|
||||
}
|
||||
@@ -67,9 +71,14 @@ export default class CrmManager {
|
||||
return contacts;
|
||||
}
|
||||
|
||||
public async createContacts(contactsToCreate: ContactCreateInput[], organizerEmail?: string) {
|
||||
public async createContacts(
|
||||
contactsToCreate: ContactCreateInput[],
|
||||
organizerEmail?: string,
|
||||
calEventResponses?: CalEventResponses | null
|
||||
) {
|
||||
const crmService = await this.getCrmService(this.credential);
|
||||
const createdContacts = (await crmService?.createContacts(contactsToCreate, organizerEmail)) || [];
|
||||
const createdContacts =
|
||||
(await crmService?.createContacts(contactsToCreate, organizerEmail, calEventResponses)) || [];
|
||||
return createdContacts;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+6
-2
@@ -1,4 +1,4 @@
|
||||
import type { CalendarEvent } from "./Calendar";
|
||||
import type { CalendarEvent, CalEventResponses } from "./Calendar";
|
||||
|
||||
export interface CrmData {
|
||||
id: string;
|
||||
@@ -38,7 +38,11 @@ export interface CRM {
|
||||
includeOwner?: boolean;
|
||||
forRoundRobinSkip?: boolean;
|
||||
}) => Promise<Contact[]>;
|
||||
createContacts: (contactsToCreate: ContactCreateInput[], organizerEmail?: string) => Promise<Contact[]>;
|
||||
createContacts: (
|
||||
contactsToCreate: ContactCreateInput[],
|
||||
organizerEmail?: string,
|
||||
calEventResponses?: CalEventResponses | null
|
||||
) => Promise<Contact[]>;
|
||||
getAppOptions: () => any;
|
||||
handleAttendeeNoShow?: (
|
||||
bookingUid: string,
|
||||
|
||||
Reference in New Issue
Block a user