UNPKG

@memberjunction/actions-bizapps-crm

Version:

CRM system integration actions for MemberJunction

291 lines 12.7 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MergeContactsAction = void 0; const global_1 = require("@memberjunction/global"); const hubspot_base_action_1 = require("../hubspot-base.action"); const actions_1 = require("@memberjunction/actions"); /** * Action to merge duplicate contacts in HubSpot */ let MergeContactsAction = class MergeContactsAction extends hubspot_base_action_1.HubSpotBaseAction { /** * Merge duplicate contacts */ async InternalRunAction(params) { const { Params, ContextUser } = params; this.params = Params; // Set params for base class to use try { // Extract and validate parameters const primaryContactId = this.getParamValue(Params, 'PrimaryContactId'); const secondaryContactIds = this.getParamValue(Params, 'SecondaryContactIds'); const primaryEmail = this.getParamValue(Params, 'PrimaryEmail'); const secondaryEmails = this.getParamValue(Params, 'SecondaryEmails'); const mergeStrategy = this.getParamValue(Params, 'MergeStrategy') || 'NEWEST'; // Validate input if (!primaryContactId && !primaryEmail) { return { Success: false, ResultCode: 'VALIDATION_ERROR', Message: 'Either PrimaryContactId or PrimaryEmail is required', Params }; } if (!secondaryContactIds && !secondaryEmails) { return { Success: false, ResultCode: 'VALIDATION_ERROR', Message: 'Either SecondaryContactIds or SecondaryEmails is required', Params }; } // Resolve contact IDs if emails provided let primaryId = primaryContactId; let secondaryIds = secondaryContactIds || []; // Get primary contact ID from email if needed if (!primaryId && primaryEmail) { const primarySearch = await this.searchHubSpotObjects('contacts', [{ propertyName: 'email', operator: 'EQ', value: primaryEmail }], ['email', 'firstname', 'lastname'], ContextUser); if (primarySearch.length === 0) { return { Success: false, ResultCode: 'PRIMARY_NOT_FOUND', Message: `Primary contact with email ${primaryEmail} not found`, Params }; } primaryId = primarySearch[0].id; } // Get secondary contact IDs from emails if needed if (secondaryEmails && (!secondaryIds || secondaryIds.length === 0)) { const emailList = Array.isArray(secondaryEmails) ? secondaryEmails : [secondaryEmails]; secondaryIds = []; for (const email of emailList) { const secondarySearch = await this.searchHubSpotObjects('contacts', [{ propertyName: 'email', operator: 'EQ', value: email }], ['email', 'firstname', 'lastname'], ContextUser); if (secondarySearch.length > 0) { secondaryIds.push(secondarySearch[0].id); } } if (secondaryIds.length === 0) { return { Success: false, ResultCode: 'SECONDARY_NOT_FOUND', Message: 'No secondary contacts found with provided emails', Params }; } } // Ensure secondaryIds is an array if (!Array.isArray(secondaryIds)) { secondaryIds = [secondaryIds]; } // Get details of all contacts before merge const primaryBefore = await this.makeHubSpotRequest(`objects/contacts/${primaryId}`, 'GET', undefined, ContextUser); const secondaryDetailsBefore = []; for (const secondaryId of secondaryIds) { try { const contact = await this.makeHubSpotRequest(`objects/contacts/${secondaryId}`, 'GET', undefined, ContextUser); secondaryDetailsBefore.push(this.mapHubSpotProperties(contact)); } catch (error) { // Contact might not exist, skip } } // Perform the merge const mergeBody = { objectIdToMerge: secondaryIds[0], // HubSpot v3 API merges one at a time mergeProperties: mergeStrategy === 'NEWEST' }; // Track merge results const mergeResults = []; const failedMerges = []; // Merge each secondary contact for (const secondaryId of secondaryIds) { try { await this.makeHubSpotRequest(`objects/contacts/merge`, 'POST', { primaryObjectId: primaryId, objectIdToMerge: secondaryId }, ContextUser); mergeResults.push({ secondaryId: secondaryId, success: true, message: 'Successfully merged' }); } catch (mergeError) { const errorMessage = mergeError instanceof Error ? mergeError.message : 'Unknown error'; failedMerges.push({ secondaryId: secondaryId, success: false, error: errorMessage }); } } // Get the merged contact details const primaryAfter = await this.makeHubSpotRequest(`objects/contacts/${primaryId}`, 'GET', undefined, ContextUser); const mergedContactDetails = this.mapHubSpotProperties(primaryAfter); // Create summary const summary = { primaryContactId: primaryId, mergedContactEmail: mergedContactDetails.email, mergedContactName: `${mergedContactDetails.firstname || ''} ${mergedContactDetails.lastname || ''}`.trim(), totalContactsMerged: mergeResults.length + 1, // Including primary successfulMerges: mergeResults.length, failedMerges: failedMerges.length, mergeStrategy: mergeStrategy, timestamp: new Date().toISOString(), portalUrl: `https://app.hubspot.com/contacts/${primaryId}` }; // Update output parameters const outputParams = [...Params]; const primaryBeforeParam = outputParams.find(p => p.Name === 'PrimaryContactBefore'); if (primaryBeforeParam) primaryBeforeParam.Value = this.mapHubSpotProperties(primaryBefore); const secondaryContactsParam = outputParams.find(p => p.Name === 'SecondaryContactsBefore'); if (secondaryContactsParam) secondaryContactsParam.Value = secondaryDetailsBefore; const mergedContactParam = outputParams.find(p => p.Name === 'MergedContact'); if (mergedContactParam) mergedContactParam.Value = mergedContactDetails; const mergeResultsParam = outputParams.find(p => p.Name === 'MergeResults'); if (mergeResultsParam) mergeResultsParam.Value = mergeResults; const failedMergesParam = outputParams.find(p => p.Name === 'FailedMerges'); if (failedMergesParam) failedMergesParam.Value = failedMerges; const summaryParam = outputParams.find(p => p.Name === 'Summary'); if (summaryParam) summaryParam.Value = summary; if (failedMerges.length > 0 && mergeResults.length === 0) { return { Success: false, ResultCode: 'MERGE_FAILED', Message: 'All merge operations failed', Params: outputParams }; } const resultMessage = failedMerges.length > 0 ? `Merged ${mergeResults.length} of ${secondaryIds.length} contacts into primary contact` : `Successfully merged ${mergeResults.length} contacts into primary contact`; return { Success: true, ResultCode: failedMerges.length > 0 ? 'PARTIAL_SUCCESS' : 'SUCCESS', Message: resultMessage, Params: outputParams }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; // Check for specific error types if (errorMessage.includes('404') || errorMessage.includes('not found')) { return { Success: false, ResultCode: 'CONTACT_NOT_FOUND', Message: 'One or more contacts not found', Params }; } if (errorMessage.includes('409') || errorMessage.includes('conflict')) { return { Success: false, ResultCode: 'MERGE_CONFLICT', Message: 'Merge conflict - contacts may have already been merged', Params }; } return { Success: false, ResultCode: 'ERROR', Message: `Error merging contacts: ${errorMessage}`, Params }; } } /** * Define the parameters this action expects */ get Params() { const baseParams = this.getCommonCRMParams(); const specificParams = [ { Name: 'PrimaryContactId', Type: 'Input', Value: null }, { Name: 'SecondaryContactIds', Type: 'Input', Value: null }, { Name: 'PrimaryEmail', Type: 'Input', Value: null }, { Name: 'SecondaryEmails', Type: 'Input', Value: null }, { Name: 'MergeStrategy', Type: 'Input', Value: 'NEWEST' }, { Name: 'PrimaryContactBefore', Type: 'Output', Value: null }, { Name: 'SecondaryContactsBefore', Type: 'Output', Value: null }, { Name: 'MergedContact', Type: 'Output', Value: null }, { Name: 'MergeResults', Type: 'Output', Value: null }, { Name: 'FailedMerges', Type: 'Output', Value: null }, { Name: 'Summary', Type: 'Output', Value: null } ]; return [...baseParams, ...specificParams]; } /** * Metadata about this action */ get Description() { return 'Merges duplicate contacts in HubSpot, combining their data and associations'; } }; exports.MergeContactsAction = MergeContactsAction; exports.MergeContactsAction = MergeContactsAction = __decorate([ (0, global_1.RegisterClass)(actions_1.BaseAction, 'MergeContactsAction') ], MergeContactsAction); //# sourceMappingURL=merge-contacts.action.js.map