Website: Update contact record creation (#19922)

Closes: https://github.com/fleetdm/confidential/issues/6929

Changes:
- Updated the update-or-create-contact-and-account helper to search for
an existing contact by email address before searching for an account
with the information provided by the get-enriched helper. This change
will allow us to change the account that a contact is associated with in
the CRM without duplicate records getting (re)created.
This commit is contained in:
Eric 2024-06-21 17:12:01 -05:00 committed by GitHub
parent 8aa55549ad
commit 223e1f2362
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -45,6 +45,7 @@ module.exports = {
fn: async function ({emailAddress, linkedinUrl, firstName, lastName, organization, primaryBuyingSituation, psychologicalStage}) {
// Return undefined if we're not running in a production environment.
if(sails.config.environment !== 'production') {
sails.log.verbose('Skipping Salesforce integration...');
return {
@ -63,110 +64,23 @@ module.exports = {
throw new Error('UsageError: when updating or creating a contact and account in salesforce, either an email or linkedInUrl is required.');
}
if(linkedinUrl){
// If linkedinUrl was provided, strip the protocol and subdomain from the URL.
linkedinUrl = linkedinUrl.replace(sails.config.custom.RX_PROTOCOL_AND_COMMON_SUBDOMAINS, '');
}
// Send the information we have to the enrichment helper.
let enrichmentData = await sails.helpers.iq.getEnriched(emailAddress, linkedinUrl, firstName, lastName, organization);
// console.log(enrichmentData);
// Log in to Salesforce.
let jsforce = require('jsforce');
let salesforceConnection = new jsforce.Connection({
loginUrl : 'https://fleetdm.my.salesforce.com'
});
let salesforceAccountOwnerId;
await salesforceConnection.login(sails.config.custom.salesforceIntegrationUsername, sails.config.custom.salesforceIntegrationPasskey);
let salesforceAccountId;
if(!enrichmentData.employer || !enrichmentData.employer.emailDomain || !enrichmentData.employer.organization) {
// Special sacraficial meat cave where the contacts with no organization go.
// https://fleetdm.lightning.force.com/lightning/r/Account/0014x000025JC8DAAW/view
salesforceAccountId = '0014x000025JC8DAAW';
salesforceAccountOwnerId = '0054x00000735wDAAQ';// « "Integrations admin" user.
} else {
// Search for an existing Account record by the organization returned from the getEnriched helper.
let existingAccountRecord = await salesforceConnection.sobject('Account')
.findOne({
'Name': enrichmentData.employer.organization,
// 'LinkedIn_company_URL__c': enrichmentData.employer.linkedinCompanyPageUrl // TODO: if this information is not present on an existing account, nothing will be returned.
});
// If we didn't find an account that's name exaclty matches, we'll do another search using the provided email domain.
if(!existingAccountRecord){
existingAccountRecord = await salesforceConnection.sobject('Account')
.findOne({
'Website': enrichmentData.employer.emailDomain,
// 'LinkedIn_company_URL__c': enrichmentData.employer.linkedinCompanyPageUrl // TODO: if this information is not present on an existing account, nothing will be returned.
});
}
// console.log(existingAccountRecord);
// If we found an exisitng account, we'll use assign the new contact to the account owner.
if(existingAccountRecord) {
// Store the ID of the Account record we found.
salesforceAccountId = existingAccountRecord.Id;
salesforceAccountOwnerId = existingAccountRecord.OwnerId;
// console.log('exising account found!', salesforceAccountId);
} else {
// If no existing account record was found, create a new one.
// Create a timestamp to use for the new account's assigned date.
salesforceAccountOwnerId = '0054x00000735wDAAQ';// « "Integrations admin" user.
let today = new Date();
let nowOn = today.toISOString().replace('Z', '+0000');
let newAccountRecord = await salesforceConnection.sobject('Account')
.create({
Account_Assigned_date__c: nowOn,// eslint-disable-line camelcase
// eslint-disable-next-line camelcase
Current_Assignment_Reason__c: 'Inbound Lead',// TODO verify that this matters. if not, do not set it.
Prospect_Status__c: 'Assigned',// eslint-disable-line camelcase
Name: enrichmentData.employer.organization,// IFWMIH: We know organization exists
Website: enrichmentData.employer.emailDomain,
LinkedIn_company_URL__c: enrichmentData.employer.linkedinCompanyPageUrl,// eslint-disable-line camelcase
NumberOfEmployees: enrichmentData.employer.numberOfEmployees,
OwnerId: salesforceAccountOwnerId
});
salesforceAccountId = newAccountRecord.id;
}//fi
// console.log('New account created!', salesforceAccountId);
}//fi
// Now search for an existing Contact.
// FUTURE: expand this section to improve the searches.
let existingContactRecord;
if(emailAddress){
// console.log('searching for existing contact by emailAddress');
existingContactRecord = await salesforceConnection.sobject('Contact')
.findOne({
AccountId: salesforceAccountId,
Email: emailAddress,
});
} else if(linkedinUrl) {
// console.log('searching for existing contact by linkedInUrl');
existingContactRecord = await salesforceConnection.sobject('Contact')
.findOne({
AccountId: salesforceAccountId,
LinkedIn_profile__c: linkedinUrl // eslint-disable-line camelcase
});
} else {
existingContactRecord = undefined;
}//fi
let salesforceContactId;
let salesforceAccountId;
// Build a dictionary of values we'll update/create a contact record with.
let valuesToSet = {};
if(emailAddress){
valuesToSet.Email = emailAddress;
}
if(linkedinUrl || (enrichmentData.person && enrichmentData.person.linkedinUrl)){
valuesToSet.LinkedIn_profile__c = linkedinUrl || enrichmentData.person.linkedinUrl;// eslint-disable-line camelcase
}
if(enrichmentData.person && enrichmentData.person.title){
valuesToSet.Title = enrichmentData.person.title;
if(linkedinUrl){
valuesToSet.LinkedIn_profile__c = linkedinUrl;// eslint-disable-line camelcase
}
if(primaryBuyingSituation) {
valuesToSet.Primary_buying_situation__c = primaryBuyingSituation;// eslint-disable-line camelcase
@ -176,18 +90,102 @@ module.exports = {
}
if(existingContactRecord){
let existingContactRecord;
// Search for an existing Contact record using the provided email address or linkedIn profile URL.
if(emailAddress) {
existingContactRecord = await salesforceConnection.sobject('Contact')
.findOne({
Email: emailAddress,
});
} else if(linkedinUrl) {
existingContactRecord = await salesforceConnection.sobject('Contact')
.findOne({
LinkedIn_profile__c: linkedinUrl // eslint-disable-line camelcase
});
}
if(existingContactRecord) {
// console.log(`Exisitng contact found! ${existingContactRecord.Id}`);
// If we found an existing contact, we'll update it with the information provided.
salesforceContactId = existingContactRecord.Id;
// console.log(`existing contact record found! ${salesforceContactId}`);
// Update the existing contact with the information provided.
await salesforceConnection.sobject('Contact')
.update({
Id: salesforceContactId,
...valuesToSet,
});
salesforceAccountId = existingContactRecord.AccountId;
// console.log(`${salesforceContactId} updated!`);
} else {
// Otherwise create a new Contact record.
// Otherwise, we'll enrich the information we have, and check for an existing account.
if(linkedinUrl){
// If linkedinUrl was provided, strip the protocol and subdomain from the URL.
linkedinUrl = linkedinUrl.replace(sails.config.custom.RX_PROTOCOL_AND_COMMON_SUBDOMAINS, '');
}
// Send the information we have to the enrichment helper.
let enrichmentData = await sails.helpers.iq.getEnriched(emailAddress, linkedinUrl, firstName, lastName, organization);
// console.log(enrichmentData);
// Add information from the enrichmentData to the values to set on the new Contact record.
if(enrichmentData.person && enrichmentData.person.linkedinUrl){
valuesToSet.LinkedIn_profile__c = enrichmentData.person.linkedinUrl;// eslint-disable-line camelcase
}
if(enrichmentData.person && enrichmentData.person.title){
valuesToSet.Title = enrichmentData.person.title;
}
let salesforceAccountOwnerId;
if(!enrichmentData.employer || !enrichmentData.employer.emailDomain || !enrichmentData.employer.organization) {
// Special sacrificial meat cave where the contacts with no organization go.
// https://fleetdm.lightning.force.com/lightning/r/Account/0014x000025JC8DAAW/view
salesforceAccountId = '0014x000025JC8DAAW';
salesforceAccountOwnerId = '0054x00000735wDAAQ';// « "Integrations admin" user.
} else {
// Search for an existing Account record by the organization returned from the getEnriched helper.
let existingAccountRecord = await salesforceConnection.sobject('Account')
.findOne({
'Name': enrichmentData.employer.organization,
// 'LinkedIn_company_URL__c': enrichmentData.employer.linkedinCompanyPageUrl // TODO: if this information is not present on an existing account, nothing will be returned.
});
// If we didn't find an account that's name exaclty matches, we'll do another search using the provided email domain.
if(!existingAccountRecord){
existingAccountRecord = await salesforceConnection.sobject('Account')
.findOne({
'Website': enrichmentData.employer.emailDomain,
// 'LinkedIn_company_URL__c': enrichmentData.employer.linkedinCompanyPageUrl // TODO: if this information is not present on an existing account, nothing will be returned.
});
}
// console.log(existingAccountRecord);
// If we found an exisitng account, we'll assign the new contact to the account owner.
if(existingAccountRecord) {
// Store the ID of the Account record we found.
salesforceAccountId = existingAccountRecord.Id;
salesforceAccountOwnerId = existingAccountRecord.OwnerId;
// console.log('exising account found!', salesforceAccountId);
} else {
// If no existing account record was found, create a new one, and assign it to the "Integrations Admin" user.
salesforceAccountOwnerId = '0054x00000735wDAAQ';// « "Integrations admin" user.
// Create a timestamp to use for the new account's assigned date.
let today = new Date();
let nowOn = today.toISOString().replace('Z', '+0000');
let newAccountRecord = await salesforceConnection.sobject('Account')
.create({
Account_Assigned_date__c: nowOn,// eslint-disable-line camelcase
// eslint-disable-next-line camelcase
Current_Assignment_Reason__c: 'Inbound Lead',// TODO verify that this matters. if not, do not set it.
Prospect_Status__c: 'Assigned',// eslint-disable-line camelcase
Name: enrichmentData.employer.organization,// IFWMIH: We know organization exists
Website: enrichmentData.employer.emailDomain,
LinkedIn_company_URL__c: enrichmentData.employer.linkedinCompanyPageUrl,// eslint-disable-line camelcase
NumberOfEmployees: enrichmentData.employer.numberOfEmployees,
OwnerId: salesforceAccountOwnerId
});
salesforceAccountId = newAccountRecord.id;
}//fi
// console.log('New account created!', salesforceAccountId);
}//fi
// console.log(`creating new Contact record.`)
// Create a new Contact record for this person.
let newContactRecord = await salesforceConnection.sobject('Contact')
.create({
AccountId: salesforceAccountId,
@ -196,12 +194,10 @@ module.exports = {
LastName: lastName,
...valuesToSet,
});
// console.log(newContactRecord);
// console.log(`Created ${newContactRecord.id}`);
salesforceContactId = newContactRecord.id;
// console.log(`New contact record created! ${salesforceContactId}`);
}//fi
return {
salesforceAccountId,
salesforceContactId