feat: Salesforce change owner on booking [CAL-4641] (#17391)

* Let user set owner name to change

* Add backend logic

* Add message

* Type fixes
This commit is contained in:
Joe Au-Yeung authored and GitHub committed 2024-10-29 14:03:35 -04:00
1 parent 55671db5fd
commit 8605fb4518
4 files changed
+62 -3

No files matched your search

@@ -2720,5 +2720,6 @@
"attendee_timezone_info": "Attendee Timezone",
"event_start_time_in_attendee_timezone_info": "Event Start Time In Attendee Timezone",
"event_end_time_in_attendee_timezone_info": "Event End Time In Attendee Timezone",
"salesforce_owner_name_to_change": "Owner name to change",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
@@ -27,6 +27,8 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
const createEventOn = getAppData("createEventOn") ?? SalesforceRecordEnum.CONTACT;
const onBookingWriteToEventObject = getAppData("onBookingWriteToEventObject") ?? false;
const onBookingWriteToEventObjectMap = getAppData("onBookingWriteToEventObjectMap") ?? {};
const onBookingChangeRecordOwner = getAppData("onBookingChangeRecordOwner") ?? false;
const onBookingChangeRecordOwnerName = getAppData("onBookingChangeRecordOwnerName") ?? [];
const { t } = useLocale();
const recordOptions = [
@@ -208,6 +210,26 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
) : null}
</div>
<div className="mt-4">
<Switch
label="Change record owner on booking"
labelOnLeading
checked={onBookingChangeRecordOwner}
onCheckedChange={(checked) => {
setAppData("onBookingChangeRecordOwner", checked);
}}
/>
</div>
{onBookingChangeRecordOwner ? (
<div className="ml-2 mt-2">
<p className="mb-2">{t("salesforce_owner_name_to_change")}</p>
<InputField
value={onBookingChangeRecordOwnerName}
onChange={(e) => setAppData("onBookingChangeRecordOwnerName", e.target.value)}
/>
</div>
) : null}
{eventType.schedulingType === SchedulingType.ROUND_ROBIN ? (
<div className="mt-4">
<Switch
@@ -137,7 +137,7 @@ export default class SalesforceCRMService implements CRM {
private getSalesforceUserFromOwnerId = async (ownerId: string) => {
const conn = await this.conn;
return await conn.query(`SELECT Id, Email FROM User WHERE Id = '${ownerId}'`);
return await conn.query(`SELECT Id, Email, Name FROM User WHERE Id = '${ownerId}'`);
};
private getSalesforceEventBody = (event: CalendarEvent): string => {
@@ -153,7 +153,6 @@ export default class SalesforceCRMService implements CRM {
options: { [key: string]: unknown }
) => {
const conn = await this.conn;
const ownerId = await this.getSalesforceUserIdFromEmail(event.organizer.email);
return await conn.sobject("Event").create({
StartDateTime: new Date(event.startTime).toISOString(),
@@ -166,7 +165,6 @@ export default class SalesforceCRMService implements CRM {
IsRecurrence2: true,
Recurrence2PatternText: new RRule(event.recurringEvent).toString(),
}),
...(ownerId && { OwnerId: ownerId }),
});
};
@@ -188,9 +186,12 @@ export default class SalesforceCRMService implements CRM {
confirmedCustomFieldInputs[field] = appOptions.onBookingWriteToEventObjectMap[field];
}
const ownerId = await this.getSalesforceUserIdFromEmail(event.organizer.email);
const createdEvent = await this.salesforceCreateEventApiCall(event, {
EventWhoIds: contacts.map((contact) => contact.id),
...confirmedCustomFieldInputs,
...(ownerId && { OwnerId: ownerId }),
}).catch(async (reason) => {
if (reason === sfApiErrors.INVALID_EVENTWHOIDS) {
this.calWarnings.push(
@@ -207,6 +208,10 @@ export default class SalesforceCRMService implements CRM {
return Promise.reject();
}
});
// Check to see if we also need to change the record owner
if (appOptions.onBookingChangeRecordOwner && appOptions.onBookingChangeRecordOwnerName && ownerId) {
await this.checkRecordOwnerNameFromRecordId(contacts[0].id, ownerId);
}
return createdEvent;
};
@@ -573,6 +578,35 @@ export default class SalesforceCRMService implements CRM {
}
}
private async checkRecordOwnerNameFromRecordId(id: string, newOwnerId: string) {
const conn = await this.conn;
const appOptions = this.getAppOptions();
// Get the associated record that the event was created on
const recordQuery = (await conn.query(
`SELECT OwnerId FROM ${appOptions?.createEventOn} WHERE Id = '${id}'`
)) as { records: { OwnerId: string }[] };
if (!recordQuery || !recordQuery.records.length) return;
const ownerId = recordQuery.records[0].OwnerId;
const ownerQuery = await this.getSalesforceUserFromOwnerId(ownerId);
if (!ownerQuery || !ownerQuery.records.length) return;
const owner = ownerQuery.records[0] as { Name: string };
// Check that the owner name matches the names where we need to change the organizer
if (appOptions?.onBookingChangeRecordOwnerName.includes(owner.Name)) {
await conn.sobject(appOptions?.createEventOn).update({
// First field is there WHERE statement
Id: id,
OwnerId: newOwnerId,
});
}
}
private async getAccountIdBasedOnEmailDomainOfContacts(email: string) {
const conn = await this.conn;
const emailDomain = email.split("@")[1];
+2
View File
@@ -15,6 +15,8 @@ export const appDataSchema = eventTypeAppCardZod.extend({
createLeadIfAccountNull: z.boolean().optional(),
onBookingWriteToEventObject: z.boolean().optional(),
onBookingWriteToEventObjectMap: z.record(z.any()).optional(),
onBookingChangeRecordOwner: z.boolean().optional(),
onBookingChangeRecordOwnerName: z.string().optional(),
});
export const appKeysSchema = z.object({