chore: Salesforce add more logging (#19106)
* Add more logs * Remove unused method * Fallback when creating an event * Type fix * Type fix * Type fix * Add more logging * More logging
This commit is contained in:
1 parent
3972972d57
commit
89033c0e9c
1 file changed
+83
-33
@@ -180,11 +180,14 @@ export default class SalesforceCRMService implements CRM {
|
||||
};
|
||||
|
||||
private salesforceCreateEvent = async (event: CalendarEvent, contacts: Contact[]) => {
|
||||
const log = logger.getSubLogger({ prefix: [`[salesforceCreateEvent]:${event.uid}`] });
|
||||
|
||||
const appOptions = this.getAppOptions();
|
||||
|
||||
const writeToEventRecord = await this.generateWriteToEventBody(event);
|
||||
log.info(`Writing to event fields: ${Object.keys(writeToEventRecord)} `);
|
||||
|
||||
let ownerId = null;
|
||||
let ownerId: string | undefined = undefined;
|
||||
if (event?.organizer?.email) {
|
||||
ownerId = await this.getSalesforceUserIdFromEmail(event.organizer.email);
|
||||
} else {
|
||||
@@ -201,8 +204,20 @@ export default class SalesforceCRMService implements CRM {
|
||||
this.log.warn("salesforceCreateEvent: No contacts found for event", event.uid, contacts);
|
||||
}
|
||||
|
||||
const eventWhoIds = contacts.reduce((contactIds, contact) => {
|
||||
if (contact?.id) {
|
||||
contactIds.push(contact.id);
|
||||
}
|
||||
|
||||
return contactIds;
|
||||
}, [] as string[]);
|
||||
|
||||
if (eventWhoIds.length !== contacts.length) {
|
||||
log.warn(`Not all contacts contain ids ${contacts}`);
|
||||
}
|
||||
|
||||
const createdEvent = await this.salesforceCreateEventApiCall(event, {
|
||||
EventWhoIds: contacts.map((contact) => contact.id),
|
||||
EventWhoIds: eventWhoIds,
|
||||
...writeToEventRecord,
|
||||
...(ownerId && { OwnerId: ownerId }),
|
||||
}).catch(async (reason) => {
|
||||
@@ -218,12 +233,27 @@ export default class SalesforceCRMService implements CRM {
|
||||
WhoId: firstContact,
|
||||
}).catch((reason) => Promise.reject(reason));
|
||||
}
|
||||
return Promise.reject(reason);
|
||||
log.error(`Error creating event: ${JSON.stringify(reason)}`);
|
||||
|
||||
// Try creating a simple object without additional records
|
||||
return await this.salesforceCreateEventApiCall(event, {
|
||||
EventWhoIds: eventWhoIds,
|
||||
...(ownerId && { OwnerId: ownerId }),
|
||||
}).catch((reason) => {
|
||||
log.error(`Error creating simple event: ${JSON.stringify(reason)}`);
|
||||
return Promise.reject(reason);
|
||||
});
|
||||
});
|
||||
// Check to see if we also need to change the record owner
|
||||
if (appOptions.onBookingChangeRecordOwner && appOptions.onBookingChangeRecordOwnerName && ownerId) {
|
||||
// TODO: firstContact id is assumed to not be undefined. But current code doesn't check for it.
|
||||
await this.checkRecordOwnerNameFromRecordId(firstContact.id, ownerId);
|
||||
if (appOptions.onBookingChangeRecordOwner && appOptions.onBookingChangeRecordOwnerName) {
|
||||
if (ownerId) {
|
||||
// TODO: firstContact id is assumed to not be undefined. But current code doesn't check for it.
|
||||
await this.checkRecordOwnerNameFromRecordId(firstContact.id, ownerId);
|
||||
} else {
|
||||
this.log.warn(
|
||||
`Could not find owner with email ${event.organizer.email} to change record ${firstContact.id} ownership to`
|
||||
);
|
||||
}
|
||||
}
|
||||
if (appOptions.onBookingWriteToRecord && appOptions.onBookingWriteToRecordFields) {
|
||||
await this.writeToPersonRecord(
|
||||
@@ -472,6 +502,7 @@ export default class SalesforceCRMService implements CRM {
|
||||
|
||||
if (!contactsToCreate[0]?.email) {
|
||||
this.log.warn(`createContact: no attendee email found `, contactsToCreate);
|
||||
return [];
|
||||
}
|
||||
|
||||
if (createEventOn === SalesforceRecordEnum.LEAD) {
|
||||
@@ -787,36 +818,44 @@ export default class SalesforceCRMService implements CRM {
|
||||
const conn = await this.conn;
|
||||
const appOptions = this.getAppOptions();
|
||||
|
||||
if (!appOptions?.createEventOn) {
|
||||
this.log.info(`Changing owner for record ${id}`);
|
||||
|
||||
const recordType = this.determineRecordTypeById(id);
|
||||
|
||||
if (!appOptions?.onBookingChangeRecordOwnerName) {
|
||||
this.log.warn(
|
||||
`No appOptions.createEventOn found for ${this.integrationName} on checkRecordOwnerNameFromRecordId`
|
||||
`No appOptions.onBookingChangeRecordOwnerName found for ${this.integrationName} on checkRecordOwnerNameFromRecordId`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 }[] };
|
||||
`SELECT OwnerId, Owner.Name FROM ${recordType} WHERE Id = '${id}'`
|
||||
)) as { records: { OwnerId: string; Owner: { Name: string } }[] };
|
||||
|
||||
if (!recordQuery || !recordQuery.records.length) return;
|
||||
if (!recordQuery || !recordQuery.records.length) {
|
||||
this.log.warn(`Could not find record for id ${id} and type ${recordType}`);
|
||||
}
|
||||
|
||||
const ownerId = recordQuery.records[0].OwnerId;
|
||||
const owner = recordQuery.records[0].Owner;
|
||||
|
||||
const ownerQuery = await this.getSalesforceUserFromUserId(ownerId);
|
||||
if (!appOptions.onBookingChangeRecordOwnerName.includes(owner?.Name)) {
|
||||
this.log.warn(
|
||||
`Current owner name ${owner?.Name} for record ${id} does not match the option ${appOptions.onBookingChangeRecordOwnerName}`
|
||||
);
|
||||
}
|
||||
|
||||
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({
|
||||
await conn
|
||||
.sobject(appOptions?.createEventOn)
|
||||
.update({
|
||||
// First field is there WHERE statement
|
||||
Id: id,
|
||||
OwnerId: newOwnerId,
|
||||
})
|
||||
.catch((error) => {
|
||||
this.log.warn(`Error changing owner name with error ${JSON.stringify(error)}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async getAccountIdBasedOnEmailDomainOfContacts(email: string) {
|
||||
@@ -901,9 +940,9 @@ export default class SalesforceCRMService implements CRM {
|
||||
bookingUid?: string | null
|
||||
) {
|
||||
const conn = await this.conn;
|
||||
const { createEventOn, onBookingWriteToRecordFields = {} } = this.getAppOptions();
|
||||
const { onBookingWriteToRecordFields = {} } = this.getAppOptions();
|
||||
// Determine record type (Contact or Lead)
|
||||
const personRecordType = this.determinePersonRecordType(createEventOn);
|
||||
const personRecordType = this.determineRecordTypeById(contactId);
|
||||
// Search the fields and ensure 1. they exist 2. they're the right type
|
||||
const fieldsToWriteOn = Object.keys(onBookingWriteToRecordFields);
|
||||
const existingFields = await this.ensureFieldsExistOnObject(fieldsToWriteOn, personRecordType);
|
||||
@@ -931,7 +970,9 @@ export default class SalesforceCRMService implements CRM {
|
||||
calEventResponses,
|
||||
});
|
||||
|
||||
this.log.info(`Final writeOnRecordBody contains fields ${Object.keys(writeOnRecordBody)}`);
|
||||
this.log.info(
|
||||
`Final writeOnRecordBody contains fields ${Object.keys(writeOnRecordBody)} for record ${contactId}`
|
||||
);
|
||||
|
||||
// Update the person record
|
||||
await conn
|
||||
@@ -970,7 +1011,7 @@ export default class SalesforceCRMService implements CRM {
|
||||
// Skip if field should only be written when empty and already has a value
|
||||
if (fieldConfig.whenToWrite === WhenToWriteToRecord.FIELD_EMPTY && personRecord[field.name]) {
|
||||
this.log.info(
|
||||
`Writing to field ${field.name} on contactId ${personRecord?.id} with value ${
|
||||
`Field ${field.name} on contactId ${personRecord?.Id} already exists with value ${
|
||||
personRecord[field.name]
|
||||
}`
|
||||
);
|
||||
@@ -1149,14 +1190,6 @@ export default class SalesforceCRMService implements CRM {
|
||||
return null;
|
||||
}
|
||||
|
||||
private determinePersonRecordType(createEventOn: string): SalesforceRecordEnum {
|
||||
return createEventOn === SalesforceRecordEnum.LEAD &&
|
||||
this.appOptions.createEventOnLeadCheckForContact &&
|
||||
this.getFallbackToContact()
|
||||
? SalesforceRecordEnum.CONTACT
|
||||
: this.appOptions.createEventOn;
|
||||
}
|
||||
|
||||
private async fetchPersonRecord(
|
||||
contactId: string,
|
||||
existingFields: Field[],
|
||||
@@ -1342,4 +1375,21 @@ export default class SalesforceCRMService implements CRM {
|
||||
throw new Error(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
/** All salesforce ids have a 3 character prefix associated with the record type
|
||||
* https://help.salesforce.com/s/articleView?id=000385203&type=1
|
||||
*/
|
||||
private determineRecordTypeById(id: string) {
|
||||
switch (id.substring(0, 3)) {
|
||||
case "003":
|
||||
return SalesforceRecordEnum.CONTACT;
|
||||
case "001":
|
||||
return SalesforceRecordEnum.ACCOUNT;
|
||||
case "00Q":
|
||||
return SalesforceRecordEnum.LEAD;
|
||||
default:
|
||||
this.log.warn(`Unhandled record id type ${id}`);
|
||||
return SalesforceRecordEnum.CONTACT;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user