UNPKG

@memberjunction/actions-bizapps-crm

Version:

CRM system integration actions for MemberJunction

202 lines 7.78 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.BaseCRMAction = void 0; const actions_1 = require("@memberjunction/actions"); const global_1 = require("@memberjunction/global"); const core_1 = require("@memberjunction/core"); /** * Base class for all CRM-related actions. * Provides common functionality and patterns for interacting with Customer Relationship Management systems. */ let BaseCRMAction = class BaseCRMAction extends actions_1.BaseAction { /** * Cached company integration for the current execution */ _companyIntegration = null; /** * Common CRM parameters that many actions will need */ getCommonCRMParams() { return [ { Name: 'CompanyID', Type: 'Input', Value: null } ]; } /** * Gets the company integration record for the specified company and CRM */ async getCompanyIntegration(companyId, contextUser) { // Check cache first if (this._companyIntegration && this._companyIntegration.CompanyID === companyId) { return this._companyIntegration; } const rv = new core_1.RunView(); const result = await rv.RunView({ EntityName: 'Company Integrations', ExtraFilter: `CompanyID = '${companyId}' AND Integration.Name = '${this.integrationName}'`, ResultType: 'entity_object' }, contextUser); if (!result.Success) { throw new Error(`Failed to retrieve company integration: ${result.ErrorMessage}`); } if (!result.Results || result.Results.length === 0) { throw new Error(`No ${this.integrationName} integration found for company ${companyId}. Please configure the integration first.`); } this._companyIntegration = result.Results[0]; return this._companyIntegration; } /** * Gets credentials from environment variables * Format: BIZAPPS_{PROVIDER}_{COMPANY_ID}_{CREDENTIAL_TYPE} * Example: BIZAPPS_HUBSPOT_12345_API_KEY */ getCredentialFromEnv(companyId, credentialType) { const envKey = `BIZAPPS_${this.crmProvider.toUpperCase().replace(/\s+/g, '_')}_${companyId}_${credentialType.toUpperCase()}`; return process.env[envKey]; } /** * Gets API credentials - first tries environment variables, then falls back to database */ async getAPICredentials(integration) { const companyId = integration.CompanyID; // Try environment variables first const envApiKey = this.getCredentialFromEnv(companyId, 'API_KEY'); const envApiSecret = this.getCredentialFromEnv(companyId, 'API_SECRET'); const envAccessToken = this.getCredentialFromEnv(companyId, 'ACCESS_TOKEN'); const envRefreshToken = this.getCredentialFromEnv(companyId, 'REFRESH_TOKEN'); const envClientId = this.getCredentialFromEnv(companyId, 'CLIENT_ID'); const envClientSecret = this.getCredentialFromEnv(companyId, 'CLIENT_SECRET'); if (envApiKey || envAccessToken) { return { apiKey: envApiKey, apiSecret: envApiSecret, accessToken: envAccessToken, refreshToken: envRefreshToken, clientId: envClientId, clientSecret: envClientSecret }; } // Fall back to database (for backwards compatibility) if (!integration.APIKey && !integration.AccessToken) { throw new Error(`No API credentials found for ${this.integrationName} integration. Please set environment variables or configure in database.`); } return { apiKey: integration.APIKey || undefined, accessToken: integration.AccessToken || undefined, refreshToken: integration.RefreshToken || undefined }; } /** * Gets the base URL for API calls */ async getAPIBaseURL(integration) { // Check if custom URL is stored in the integration if (integration.CustomAttribute1) { return integration.CustomAttribute1; } // Return empty string - derived classes should override this return ''; } /** * Helper to get parameter value with type safety */ getParamValue(params, paramName) { const param = params.find(p => p.Name === paramName); return param?.Value; } /** * Standard date format for CRM systems (ISO 8601) */ formatCRMDate(date) { return date.toISOString(); } /** * Parse date from CRM format */ parseCRMDate(dateString) { return new Date(dateString); } /** * Format phone numbers to E.164 format if possible */ formatPhoneNumber(phone) { if (!phone) return ''; // Remove all non-numeric characters const cleaned = phone.replace(/\D/g, ''); // If it's a US number (10 digits), format it if (cleaned.length === 10) { return `+1${cleaned}`; } // If it already has country code if (cleaned.length === 11 && cleaned.startsWith('1')) { return `+${cleaned}`; } // Return cleaned version for other formats return cleaned; } /** * Validate email format */ isValidEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } /** * Helper to build consistent error messages for CRM operations */ buildCRMErrorMessage(operation, details, systemError) { let message = `CRM operation failed: ${operation}. ${details}`; if (systemError) { message += ` System error: ${systemError.message || systemError}`; } return message; } /** * Map deal/opportunity stages to common statuses */ mapDealStatus(stage) { const lowerStage = stage.toLowerCase(); if (lowerStage.includes('won') || lowerStage.includes('closed-won') || lowerStage.includes('success')) { return 'won'; } if (lowerStage.includes('lost') || lowerStage.includes('closed-lost') || lowerStage.includes('failed')) { return 'lost'; } if (lowerStage.includes('open') || lowerStage.includes('active') || lowerStage.includes('qualified')) { return 'open'; } return 'unknown'; } /** * Common activity types mapping */ mapActivityType(type) { const activityMap = { 'call': 'call', 'phone': 'call', 'email': 'email', 'meeting': 'meeting', 'appointment': 'meeting', 'task': 'task', 'todo': 'task', 'note': 'note', 'comment': 'note' }; return activityMap[type.toLowerCase()] || 'other'; } }; exports.BaseCRMAction = BaseCRMAction; exports.BaseCRMAction = BaseCRMAction = __decorate([ (0, global_1.RegisterClass)(actions_1.BaseAction, 'BaseCRMAction') ], BaseCRMAction); //# sourceMappingURL=base-crm.action.js.map