@memberjunction/actions-bizapps-crm
Version:
CRM system integration actions for MemberJunction
298 lines (277 loc) • 10.8 kB
text/typescript
import { RegisterClass } from '@memberjunction/global';
import { HubSpotBaseAction } from '../hubspot-base.action';
import { ActionParam, ActionResultSimple, RunActionParams } from '@memberjunction/actions-base';
import { BaseAction } from '@memberjunction/actions';
/**
* Action to update an existing contact in HubSpot
*/
export class UpdateContactAction extends HubSpotBaseAction {
/**
* Update an existing contact
*/
protected async InternalRunAction(params: RunActionParams): Promise<ActionResultSimple> {
const { Params, ContextUser } = params;
this.params = Params; // Set params for base class to use
try {
// Extract and validate parameters
const contactId = this.getParamValue(Params, 'ContactId');
const email = this.getParamValue(Params, 'Email');
const firstName = this.getParamValue(Params, 'FirstName');
const lastName = this.getParamValue(Params, 'LastName');
const phone = this.getParamValue(Params, 'Phone');
const company = this.getParamValue(Params, 'Company');
const jobTitle = this.getParamValue(Params, 'JobTitle');
const lifecycleStage = this.getParamValue(Params, 'LifecycleStage');
const leadStatus = this.getParamValue(Params, 'LeadStatus');
const website = this.getParamValue(Params, 'Website');
const address = this.getParamValue(Params, 'Address');
const city = this.getParamValue(Params, 'City');
const state = this.getParamValue(Params, 'State');
const zip = this.getParamValue(Params, 'Zip');
const country = this.getParamValue(Params, 'Country');
const customProperties = this.getParamValue(Params, 'CustomProperties');
const clearFields = this.getParamValue(Params, 'ClearFields');
if (!contactId) {
return {
Success: false,
ResultCode: 'VALIDATION_ERROR',
Message: 'ContactId is required',
Params
};
}
// Prepare properties to update
const properties: any = {};
// Add fields to update (only include if provided)
if (email !== undefined && email !== null) {
if (!this.isValidEmail(email)) {
return {
Success: false,
ResultCode: 'VALIDATION_ERROR',
Message: 'Invalid email format',
Params
};
}
properties.email = email;
}
if (firstName !== undefined && firstName !== null) properties.firstname = firstName;
if (lastName !== undefined && lastName !== null) properties.lastname = lastName;
if (phone !== undefined && phone !== null) properties.phone = this.formatPhoneNumber(phone);
if (company !== undefined && company !== null) properties.company = company;
if (jobTitle !== undefined && jobTitle !== null) properties.jobtitle = jobTitle;
if (lifecycleStage !== undefined && lifecycleStage !== null) properties.lifecyclestage = lifecycleStage;
if (leadStatus !== undefined && leadStatus !== null) properties.lead_status = leadStatus;
if (website !== undefined && website !== null) properties.website = website;
if (address !== undefined && address !== null) properties.address = address;
if (city !== undefined && city !== null) properties.city = city;
if (state !== undefined && state !== null) properties.state = state;
if (zip !== undefined && zip !== null) properties.zip = zip;
if (country !== undefined && country !== null) properties.country = country;
// Add custom properties if provided
if (customProperties && typeof customProperties === 'object') {
Object.assign(properties, customProperties);
}
// Clear specific fields if requested
if (clearFields && Array.isArray(clearFields)) {
for (const field of clearFields) {
properties[field] = '';
}
}
// Check if there are any properties to update
if (Object.keys(properties).length === 0) {
return {
Success: false,
ResultCode: 'NO_CHANGES',
Message: 'No properties provided to update',
Params
};
}
// Get current contact data first
const currentContact = await this.makeHubSpotRequest<any>(
`objects/contacts/${contactId}`,
'GET',
undefined,
ContextUser
);
// Store before state
const beforeState = this.mapHubSpotProperties(currentContact);
// Update contact
const updatedContact = await this.makeHubSpotRequest<any>(
`objects/contacts/${contactId}`,
'PATCH',
{ properties },
ContextUser
);
// Format contact details
const afterState = this.mapHubSpotProperties(updatedContact);
// Create change summary
const changes: any[] = [];
for (const key in properties) {
if (beforeState[key] !== afterState[key]) {
changes.push({
field: key,
oldValue: beforeState[key],
newValue: afterState[key]
});
}
}
// Create summary
const summary = {
contactId: afterState.id,
email: afterState.email,
fullName: `${afterState.firstname || ''} ${afterState.lastname || ''}`.trim(),
fieldsUpdated: Object.keys(properties).length,
actualChanges: changes.length,
changes: changes,
updatedAt: afterState.updatedAt,
portalUrl: `https://app.hubspot.com/contacts/${afterState.id}`
};
// Update output parameters
const outputParams = [...Params];
const beforeStateParam = outputParams.find(p => p.Name === 'BeforeState');
if (beforeStateParam) beforeStateParam.Value = beforeState;
const afterStateParam = outputParams.find(p => p.Name === 'AfterState');
if (afterStateParam) afterStateParam.Value = afterState;
const summaryParam = outputParams.find(p => p.Name === 'Summary');
if (summaryParam) summaryParam.Value = summary;
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Successfully updated contact ${afterState.email || contactId}`,
Params: outputParams
};
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
// Check for not found error
if (errorMessage.includes('404') || errorMessage.includes('not found')) {
return {
Success: false,
ResultCode: 'CONTACT_NOT_FOUND',
Message: `Contact with ID ${this.getParamValue(Params, 'ContactId')} not found`,
Params
};
}
return {
Success: false,
ResultCode: 'ERROR',
Message: `Error updating contact: ${errorMessage}`,
Params
};
}
}
/**
* Define the parameters this action expects
*/
public get Params(): ActionParam[] {
const baseParams = this.getCommonCRMParams();
const specificParams: ActionParam[] = [
{
Name: 'ContactId',
Type: 'Input',
Value: null
},
{
Name: 'Email',
Type: 'Input',
Value: null
},
{
Name: 'FirstName',
Type: 'Input',
Value: null
},
{
Name: 'LastName',
Type: 'Input',
Value: null
},
{
Name: 'Phone',
Type: 'Input',
Value: null
},
{
Name: 'Company',
Type: 'Input',
Value: null
},
{
Name: 'JobTitle',
Type: 'Input',
Value: null
},
{
Name: 'LifecycleStage',
Type: 'Input',
Value: null
},
{
Name: 'LeadStatus',
Type: 'Input',
Value: null
},
{
Name: 'Website',
Type: 'Input',
Value: null
},
{
Name: 'Address',
Type: 'Input',
Value: null
},
{
Name: 'City',
Type: 'Input',
Value: null
},
{
Name: 'State',
Type: 'Input',
Value: null
},
{
Name: 'Zip',
Type: 'Input',
Value: null
},
{
Name: 'Country',
Type: 'Input',
Value: null
},
{
Name: 'CustomProperties',
Type: 'Input',
Value: null
},
{
Name: 'ClearFields',
Type: 'Input',
Value: null
},
{
Name: 'BeforeState',
Type: 'Output',
Value: null
},
{
Name: 'AfterState',
Type: 'Output',
Value: null
},
{
Name: 'Summary',
Type: 'Output',
Value: null
}
];
return [...baseParams, ...specificParams];
}
/**
* Metadata about this action
*/
public get Description(): string {
return 'Updates an existing contact in HubSpot with change tracking';
}
}