n8n-nodes-close-crm
Version:
N8N community node for Close CRM integration with comprehensive lead, opportunity, task, note, call management, and enhanced triggers for workflow automation
848 lines (847 loc) • 154 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Close = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const GenericFunctions_1 = require("./GenericFunctions");
const LeadDescription_1 = require("./descriptions/LeadDescription");
const LeadStatusDescription_1 = require("./descriptions/LeadStatusDescription");
const OpportunityDescription_1 = require("./descriptions/OpportunityDescription");
const OpportunityStatusDescription_1 = require("./descriptions/OpportunityStatusDescription");
const TaskDescription_1 = require("./descriptions/TaskDescription");
const NoteDescription_1 = require("./descriptions/NoteDescription");
const CallDescription_1 = require("./descriptions/CallDescription");
const EmailDescription_1 = require("./descriptions/EmailDescription");
const MeetingDescription_1 = require("./descriptions/MeetingDescription");
const SmsDescription_1 = require("./descriptions/SmsDescription");
const CustomActivityDescription_1 = require("./descriptions/CustomActivityDescription");
const ContactDescription_1 = require("./descriptions/ContactDescription");
const SequenceDescription_1 = require("./descriptions/SequenceDescription");
const BulkActionDescription_1 = require("./descriptions/BulkActionDescription");
const ExportDescription_1 = require("./descriptions/ExportDescription");
const FieldEnrichmentDescription_1 = require("./descriptions/FieldEnrichmentDescription");
const CustomFieldsDescription_1 = require("./descriptions/CustomFieldsDescription");
function removeNullishValues(payload) {
return Object.fromEntries(Object.entries(payload).filter(([, value]) => value !== null && value !== undefined));
}
function hasValue(value) {
return value !== null && value !== undefined;
}
function parseJsonParam(value, fieldName) {
if (value === undefined || value === null || value === '') {
return undefined;
}
if (typeof value === 'object') {
return value;
}
if (typeof value === 'string') {
const trimmed = value.trim();
if (!trimmed) {
return undefined;
}
try {
return JSON.parse(trimmed);
}
catch (error) {
throw new Error(`Invalid JSON in field "${fieldName}": ${error.message}`);
}
}
return value;
}
class Close {
constructor() {
this.description = {
displayName: 'Close CRM',
name: 'close',
icon: 'file:close.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Close CRM API',
defaults: {
name: 'Close CRM',
},
inputs: [{ type: 'main' }],
outputs: [{ type: 'main' }],
credentials: [
{
name: 'closeApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Lead',
value: 'lead',
},
{
name: 'Lead Status',
value: 'leadStatus',
},
{
name: 'Contact',
value: 'contact',
},
{
name: 'Opportunity',
value: 'opportunity',
},
{
name: 'Opportunity Status',
value: 'opportunityStatus',
},
{
name: 'Task',
value: 'task',
},
{
name: 'Note',
value: 'note',
},
{
name: 'Call',
value: 'call',
},
{
name: 'Email',
value: 'email',
},
{
name: 'Meeting',
value: 'meeting',
},
{
name: 'SMS',
value: 'sms',
},
{
name: 'Custom Activity',
value: 'customActivity',
},
{
name: 'Sequence (Automation & Bulk Actions)',
value: 'sequence',
},
{
name: 'Bulk Action (Automation & Bulk Actions)',
value: 'bulkAction',
},
{
name: 'Export (Automation & Bulk Actions)',
value: 'export',
},
{
name: 'Field Enrichment (Automation & Bulk Actions)',
value: 'fieldEnrichment',
},
],
default: 'lead',
},
...LeadDescription_1.leadOperations,
...LeadDescription_1.leadFields,
...LeadStatusDescription_1.leadStatusOperations,
...LeadStatusDescription_1.leadStatusFields,
...ContactDescription_1.contactOperations,
...ContactDescription_1.contactFields,
...OpportunityDescription_1.opportunityOperations,
...OpportunityDescription_1.opportunityFields,
...OpportunityStatusDescription_1.opportunityStatusOperations,
...OpportunityStatusDescription_1.opportunityStatusFields,
...TaskDescription_1.taskOperations,
...TaskDescription_1.taskFields,
...NoteDescription_1.noteOperations,
...NoteDescription_1.noteFields,
...CallDescription_1.callOperations,
...CallDescription_1.callFields,
...EmailDescription_1.emailOperations,
...EmailDescription_1.emailFields,
...MeetingDescription_1.meetingOperations,
...MeetingDescription_1.meetingFields,
...SmsDescription_1.smsOperations,
...SmsDescription_1.smsFields,
...CustomActivityDescription_1.customActivityOperations,
...CustomActivityDescription_1.customActivityFields,
...SequenceDescription_1.sequenceOperations,
...SequenceDescription_1.sequenceFields,
...BulkActionDescription_1.bulkActionOperations,
...BulkActionDescription_1.bulkActionFields,
...ExportDescription_1.exportOperations,
...ExportDescription_1.exportFields,
...FieldEnrichmentDescription_1.fieldEnrichmentOperations,
...FieldEnrichmentDescription_1.fieldEnrichmentFields,
...CustomFieldsDescription_1.customFieldsCreateSections,
...CustomFieldsDescription_1.customFieldsUpdateSections,
...CustomFieldsDescription_1.customActivityCustomFieldsCreateSections,
...CustomFieldsDescription_1.customActivityCustomFieldsUpdateSections,
],
};
this.methods = {
loadOptions: {
async getLeadStatuses() {
const returnData = [];
const statuses = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/status/lead/');
for (const status of statuses.data) {
returnData.push({
name: status.label,
value: status.id,
});
}
return returnData;
},
async getOpportunityStatuses() {
const returnData = [];
const statuses = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/status/opportunity/');
for (const status of statuses.data) {
returnData.push({
name: status.label,
value: status.id,
});
}
return returnData;
},
async getSmartViews() {
const returnData = [];
const views = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/saved_search/');
for (const view of views.data) {
returnData.push({
name: view.name,
value: view.id,
});
}
return returnData;
},
async getUsers() {
const returnData = [];
const users = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/user/');
for (const user of users.data) {
returnData.push({
name: `${user.first_name} ${user.last_name} (${user.email})`,
value: user.id,
});
}
return returnData;
},
// New Custom Fields Load Methods
async getSingleChoiceFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getChoiceSingleFields(this);
},
async getMultipleChoiceFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getChoiceMultipleFields(this);
},
async getTextFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getTextFields(this);
},
async getNumberFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getNumberFields(this);
},
async getDateFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getDateFields(this);
},
async getDateTimeFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getDateFields(this);
},
async getSingleUserFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getUserSingleFields(this);
},
async getMultipleUserFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getUserMultipleFields(this);
},
async getSingleContactFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactSingleFields(this);
},
async getMultipleContactFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactMultipleFields(this);
},
// New dynamic method for field type filtering
async getFieldsByType() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getFieldsByType(this);
},
async getFieldChoices() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getFieldChoices(this);
},
async getAllChoiceValues() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getAllChoiceValues(this);
},
async getCachedUsers() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getCachedUsers(this);
},
// Contact Custom Fields Load Methods
async getContactTextFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactTextFields(this);
},
async getContactNumberFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactNumberFields(this);
},
async getContactDateFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactDateFields(this);
},
async getContactSingleChoiceFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactSingleChoiceFields(this);
},
async getContactMultipleChoiceFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactMultipleChoiceFields(this);
},
async getContactAllChoiceValues() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactAllChoiceValues(this);
},
async getContactSingleUserFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactSingleUserFields(this);
},
async getContactMultipleUserFields() {
return CustomFieldsDescription_1.customFieldsLoadMethods.getContactMultipleUserFields(this);
},
async getCustomActivityTypes() {
const returnData = [];
const types = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/custom_activity/');
for (const type of types.data) {
returnData.push({
name: type.name,
value: type.id,
});
}
return returnData;
},
// Custom Activity Custom Fields Load Methods
async getCustomActivityTextFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityTextFields(this);
},
async getCustomActivityRichTextFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityRichTextFields(this);
},
async getCustomActivityNumberFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityNumberFields(this);
},
async getCustomActivityDateFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityDateFields(this);
},
async getCustomActivitySingleChoiceFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivitySingleChoiceFields(this);
},
async getCustomActivityMultipleChoiceFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityMultipleChoiceFields(this);
},
async getCustomActivityAllChoiceValues() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityAllChoiceValues(this);
},
async getCustomActivitySingleUserFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivitySingleUserFields(this);
},
async getCustomActivityMultipleUserFields() {
return CustomFieldsDescription_1.customActivityCustomFieldsLoadMethods.getCustomActivityMultipleUserFields(this);
},
},
};
}
async execute() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
const items = this.getInputData();
const returnData = [];
const length = items.length;
const qs = {};
let responseData;
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < length; i++) {
try {
// Input validation
if (!resource) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Resource is required');
}
if (!operation) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Operation is required');
}
if (resource === 'lead') {
if (operation === 'create') {
const name = this.getNodeParameter('name', i);
if (!name) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Lead name is required for create operation');
}
const body = {
name,
};
// Add additional fields if provided
const additionalFields = this.getNodeParameter('additionalFields', i);
if (hasValue(additionalFields.description) && additionalFields.description !== '') {
body.description = additionalFields.description;
}
if (hasValue(additionalFields.statusId) && additionalFields.statusId !== '') {
body.status_id = additionalFields.statusId;
}
if (hasValue(additionalFields.userId) && additionalFields.userId !== '') {
body.user_id = additionalFields.userId;
}
if (hasValue(additionalFields.url) && additionalFields.url !== '') {
body.url = additionalFields.url;
}
// Add contacts if provided
const contacts = this.getNodeParameter('contactsUi', i, {});
if ((_a = contacts.contactsValues) === null || _a === void 0 ? void 0 : _a.length) {
body.contacts = await Promise.all(contacts.contactsValues.map(async (contact) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
const contactObj = {};
if (contact.name)
contactObj.name = contact.name;
if (contact.email)
contactObj.emails = [{ type: 'office', email: contact.email }];
// Handle phones array with both office and mobile numbers
const phones = [];
if (contact.phone) {
phones.push({ type: 'office', phone: contact.phone });
}
if (contact.mobilePhone) {
phones.push({ type: 'mobile', phone: contact.mobilePhone });
}
if (phones.length > 0) {
contactObj.phones = phones;
}
if (contact.title)
contactObj.title = contact.title;
// Add custom fields for contact if provided
const hasCustomFields = ((_b = (_a = contact.contactCustomTextFields) === null || _a === void 0 ? void 0 : _a.textFields) === null || _b === void 0 ? void 0 : _b.length) ||
((_d = (_c = contact.contactCustomNumberFields) === null || _c === void 0 ? void 0 : _c.numberFields) === null || _d === void 0 ? void 0 : _d.length) ||
((_f = (_e = contact.contactCustomDateFields) === null || _e === void 0 ? void 0 : _e.dateFields) === null || _f === void 0 ? void 0 : _f.length) ||
((_h = (_g = contact.contactCustomChoiceSingleFields) === null || _g === void 0 ? void 0 : _g.choiceSingleFields) === null || _h === void 0 ? void 0 : _h.length) ||
((_k = (_j = contact.contactCustomChoiceMultipleFields) === null || _j === void 0 ? void 0 : _j.choiceMultipleFields) === null || _k === void 0 ? void 0 : _k.length) ||
((_m = (_l = contact.contactCustomUserSingleFields) === null || _l === void 0 ? void 0 : _l.userSingleFields) === null || _m === void 0 ? void 0 : _m.length) ||
((_p = (_o = contact.contactCustomUserMultipleFields) === null || _o === void 0 ? void 0 : _o.userMultipleFields) === null || _p === void 0 ? void 0 : _p.length);
if (hasCustomFields) {
try {
const contactFields = await CustomFieldsDescription_1.customFieldsLoadMethods.getCachedContactCustomFields(this);
const contactCustomFieldsPayload = (0, CustomFieldsDescription_1.constructContactCustomFieldsPayload)(contact, contactFields);
Object.assign(contactObj, contactCustomFieldsPayload);
}
catch (error) {
console.error('Error processing contact custom fields:', error);
}
}
return removeNullishValues(contactObj);
}));
}
// Add address if provided
const address = this.getNodeParameter('addressUi', i, {});
if (address &&
(address.street ||
address.city ||
address.state ||
address.zipcode ||
address.country)) {
const addressesArray = [];
const addressObj = { type: 'office' };
if (address.street)
addressObj.address_1 = address.street;
if (address.city)
addressObj.city = address.city;
if (address.state)
addressObj.state = address.state;
if (address.zipcode)
addressObj.zipcode = address.zipcode;
if (address.country)
addressObj.country = address.country;
addressesArray.push(removeNullishValues(addressObj));
body.addresses = addressesArray;
}
// Add custom fields if provided (backwards compatibility)
const customFields = this.getNodeParameter('customFieldsUi', i, {});
if ((_b = customFields.customFieldsValues) === null || _b === void 0 ? void 0 : _b.length) {
for (const field of customFields.customFieldsValues) {
// Parse the encoded field ID and type
const [actualFieldId, fieldType] = field.fieldId.split('|');
// Use the appropriate value based on field type
const value = fieldType === 'choices' ? field.fieldValueChoice : field.fieldValue;
if (value) {
body[`custom.${actualFieldId}`] = value;
}
}
}
// Add custom fields from the new structure
try {
// Collect custom fields data from the new dynamic structure
const customFieldsData = this.getNodeParameter('customFields', i, {});
// If we have custom fields, process them
if (customFieldsData && Object.keys(customFieldsData).length > 0) {
const fields = await CustomFieldsDescription_1.customFieldsLoadMethods.getCachedCustomFields(this);
const customFieldsPayload = (0, CustomFieldsDescription_1.constructCustomFieldsPayload)({ customFields: customFieldsData }, fields);
// Merge the custom fields payload into the body
Object.assign(body, customFieldsPayload);
}
}
catch (error) {
console.error('Error processing custom fields:', error);
// Continue with execution - don't fail the entire operation
}
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'POST', '/lead/', body);
}
if (operation === 'delete') {
const leadId = this.getNodeParameter('leadId', i);
if (!leadId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Lead ID is required for delete operation');
}
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'DELETE', `/lead/${leadId}/`);
}
if (operation === 'find') {
const leadId = this.getNodeParameter('leadId', i);
const companyName = this.getNodeParameter('companyName', i);
const companyUrl = this.getNodeParameter('companyUrl', i);
const email = this.getNodeParameter('email', i);
const phone = this.getNodeParameter('phone', i);
const statusId = this.getNodeParameter('statusId', i);
const returnAll = this.getNodeParameter('returnAll', i);
// If Lead ID is provided, get specific lead
if (leadId) {
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'GET', `/lead/${leadId}/`);
}
else {
// Build advanced filter query for precise field matching
const filterQueries = [];
// Always specify we're looking for leads
filterQueries.push({
type: 'object_type',
object_type: 'lead',
});
// Filter by status_id (Status Name)
if (statusId) {
filterQueries.push({
type: 'field_condition',
field: {
type: 'regular_field',
object_type: 'lead',
field_name: 'status_id',
},
condition: {
type: 'term',
values: [statusId],
},
});
}
// Filter by display_name (Company Name)
if (companyName) {
filterQueries.push({
type: 'field_condition',
field: {
type: 'regular_field',
object_type: 'lead',
field_name: 'display_name',
},
condition: {
type: 'text',
mode: 'full_words',
value: companyName,
},
});
}
// Filter by url (Company URL)
if (companyUrl) {
filterQueries.push({
type: 'field_condition',
field: {
type: 'regular_field',
object_type: 'lead',
field_name: 'url',
},
condition: {
type: 'text',
mode: 'full_words',
value: companyUrl,
},
});
}
// Filter by email (Contact Email) - nested relation: Lead -> Contact -> Email
if (email) {
filterQueries.push({
type: 'has_related',
this_object_type: 'lead',
related_object_type: 'contact',
related_query: {
type: 'has_related',
this_object_type: 'contact',
related_object_type: 'contact_email',
related_query: {
type: 'field_condition',
field: {
type: 'regular_field',
object_type: 'contact_email',
field_name: 'email',
},
condition: {
type: 'text',
value: email,
mode: 'phrase',
},
},
},
});
}
// Filter by phone (Contact Phone) - nested relation: Lead -> Contact -> Phone
if (phone) {
filterQueries.push({
type: 'has_related',
this_object_type: 'lead',
related_object_type: 'contact',
related_query: {
type: 'has_related',
this_object_type: 'contact',
related_object_type: 'contact_phone',
related_query: {
type: 'field_condition',
field: {
type: 'regular_field',
object_type: 'contact_phone',
field_name: 'phone',
},
condition: {
type: 'text',
value: phone,
mode: 'phrase',
},
},
},
});
}
// If no filters provided, use standard API to get all leads
if (filterQueries.length === 1) {
const searchQs = {};
if (returnAll) {
responseData = await GenericFunctions_1.closeApiRequestAllItems.call(this, 'data', 'GET', '/lead/', {}, searchQs);
}
else {
searchQs._limit = this.getNodeParameter('limit', i);
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/lead/', {}, searchQs);
responseData = responseData.data;
}
}
else {
// Build the final query for Advanced Filtering API
const searchBody = {
query: {
type: 'and',
queries: filterQueries,
},
// Request all fields to get complete lead data
_fields: {
lead: [
'id',
'display_name',
'name',
'description',
'url',
'status_id',
'status_label',
'contacts',
'addresses',
'created_by',
'date_created',
'date_updated',
'organization_id',
'tasks',
'opportunities',
],
},
};
// Add pagination - Advanced Filtering API uses results_limit
if (!returnAll) {
searchBody.results_limit = this.getNodeParameter('limit', i);
}
// Use Advanced Filtering API
if (returnAll) {
responseData = await GenericFunctions_1.closeApiRequestAllItems.call(this, 'data', 'POST', '/data/search/', searchBody, {});
}
else {
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'POST', '/data/search/', searchBody);
responseData = responseData.data;
}
}
}
}
if (operation === 'merge') {
const sourceLeadId = this.getNodeParameter('sourceLeadId', i);
const destinationLeadId = this.getNodeParameter('destinationLeadId', i);
if (!sourceLeadId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Source Lead ID is required for merge operation');
}
if (!destinationLeadId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Destination Lead ID is required for merge operation');
}
const body = {
source: sourceLeadId,
destination: destinationLeadId,
};
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'POST', '/lead/merge/', body);
}
if (operation === 'update') {
const leadId = this.getNodeParameter('leadId', i);
if (!leadId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Lead ID is required for update operation');
}
const updateFields = this.getNodeParameter('updateFields', i);
const body = {};
if (hasValue(updateFields.name) && updateFields.name !== '') {
body.name = updateFields.name;
}
if (hasValue(updateFields.description) && updateFields.description !== '') {
body.description = updateFields.description;
}
if (hasValue(updateFields.statusId) && updateFields.statusId !== '') {
body.status_id = updateFields.statusId;
}
if (hasValue(updateFields.userId) && updateFields.userId !== '') {
body.user_id = updateFields.userId;
}
if (hasValue(updateFields.url) && updateFields.url !== '') {
body.url = updateFields.url;
}
// Add contacts if provided
const contacts = this.getNodeParameter('contactsUi', i, {});
if ((_c = contacts.contactsValues) === null || _c === void 0 ? void 0 : _c.length) {
// Fetch the existing lead to get current contacts
const existingLead = await GenericFunctions_1.closeApiRequest.call(this, 'GET', `/lead/${leadId}/`);
const existingContacts = existingLead.contacts || [];
// Map contacts by position: first contact updates first existing contact, etc.
body.contacts = await Promise.all(contacts.contactsValues.map(async (contact, index) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _r;
const contactObj = {};
// If there's an existing contact at this position, include its ID for update
if ((_a = existingContacts[index]) === null || _a === void 0 ? void 0 : _a.id) {
contactObj.id = existingContacts[index].id;
}
if (contact.name)
contactObj.name = contact.name;
if (contact.email)
contactObj.emails = [{ type: 'office', email: contact.email }];
// Handle phones array with both office and mobile numbers
const phones = [];
if (contact.phone) {
phones.push({ type: 'office', phone: contact.phone });
}
if (contact.mobilePhone) {
phones.push({ type: 'mobile', phone: contact.mobilePhone });
}
if (phones.length > 0) {
contactObj.phones = phones;
}
if (contact.title)
contactObj.title = contact.title;
// Add custom fields for contact if provided
const hasCustomFields = ((_c = (_b = contact.contactCustomTextFields) === null || _b === void 0 ? void 0 : _b.textFields) === null || _c === void 0 ? void 0 : _c.length) ||
((_e = (_d = contact.contactCustomNumberFields) === null || _d === void 0 ? void 0 : _d.numberFields) === null || _e === void 0 ? void 0 : _e.length) ||
((_g = (_f = contact.contactCustomDateFields) === null || _f === void 0 ? void 0 : _f.dateFields) === null || _g === void 0 ? void 0 : _g.length) ||
((_j = (_h = contact.contactCustomChoiceSingleFields) === null || _h === void 0 ? void 0 : _h.choiceSingleFields) === null || _j === void 0 ? void 0 : _j.length) ||
((_l = (_k = contact.contactCustomChoiceMultipleFields) === null || _k === void 0 ? void 0 : _k.choiceMultipleFields) === null || _l === void 0 ? void 0 : _l.length) ||
((_o = (_m = contact.contactCustomUserSingleFields) === null || _m === void 0 ? void 0 : _m.userSingleFields) === null || _o === void 0 ? void 0 : _o.length) ||
((_r = (_p = contact.contactCustomUserMultipleFields) === null || _p === void 0 ? void 0 : _p.userMultipleFields) === null || _r === void 0 ? void 0 : _r.length);
if (hasCustomFields) {
try {
const contactFields = await CustomFieldsDescription_1.customFieldsLoadMethods.getCachedContactCustomFields(this);
const contactCustomFieldsPayload = (0, CustomFieldsDescription_1.constructContactCustomFieldsPayload)(contact, contactFields);
Object.assign(contactObj, contactCustomFieldsPayload);
}
catch (error) {
console.error('Error processing contact custom fields:', error);
}
}
return removeNullishValues(contactObj);
}));
}
// Add address if provided
const address = this.getNodeParameter('addressUi', i, {});
if (address &&
(address.street ||
address.city ||
address.state ||
address.zipcode ||
address.country)) {
const addressesArray = [];
const addressObj = { type: 'office' };
if (address.street)
addressObj.address_1 = address.street;
if (address.city)
addressObj.city = address.city;
if (address.state)
addressObj.state = address.state;
if (address.zipcode)
addressObj.zipcode = address.zipcode;
if (address.country)
addressObj.country = address.country;
addressesArray.push(removeNullishValues(addressObj));
body.addresses = addressesArray;
}
// Add custom fields if provided (backwards compatibility)
const customFields = this.getNodeParameter('customFieldsUi', i, {});
if ((_d = customFields.customFieldsValues) === null || _d === void 0 ? void 0 : _d.length) {
for (const field of customFields.customFieldsValues) {
// Parse the encoded field ID and type
const [actualFieldId, fieldType] = field.fieldId.split('|');
// Use the appropriate value based on field type
const value = fieldType === 'choices' ? field.fieldValueChoice : field.fieldValue;
if (value) {
body[`custom.${actualFieldId}`] = value;
}
}
}
// Add custom fields from the new structure
try {
// Collect custom fields data from the new dynamic structure
const customFieldsData = this.getNodeParameter('customFields', i, {});
// If we have custom fields, process them
if (customFieldsData && Object.keys(customFieldsData).length > 0) {
const fields = await CustomFieldsDescription_1.customFieldsLoadMethods.getCachedCustomFields(this);
const customFieldsPayload = (0, CustomFieldsDescription_1.constructCustomFieldsPayload)({ customFields: customFieldsData }, fields);
// Merge the custom fields payload into the body
Object.assign(body, customFieldsPayload);
}
}
catch (error) {
console.error('Error processing custom fields:', error);
// Continue with execution - don't fail the entire operation
}
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'PUT', `/lead/${leadId}/`, body);
}
}
if (resource === 'leadStatus') {
if (operation === 'list') {
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'GET', '/status/lead/');
responseData = responseData.data || responseData;
}
if (operation === 'create') {
const label = this.getNodeParameter('label', i);
if (!label) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Label is required for lead status creation');
}
const body = {
label,
};
// Add additional fields if provided
const additionalFields = this.getNodeParameter('additionalFields', i);
if (additionalFields.type) {
body.type = additionalFields.type;
}
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'POST', '/status/lead/', body);
}
if (operation === 'update') {
const statusId = this.getNodeParameter('statusId', i);
const label = this.getNodeParameter('label', i);
if (!statusId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Status ID is required for update operation');
}
if (!label) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Label is required for update operation');
}
const body = {
label,
};
// Add additional fields if provided
const additionalFields = this.getNodeParameter('additionalFields', i);
if (additionalFields.type) {
body.type = additionalFields.type;
}
responseData = await GenericFunctions_1.closeApiRequest.call(this, 'PUT', `/status/lead/${statusId}/`, body);
}
if (operation === 'delete') {
const statusId = this.getNodeParameter('statusId', i);
if (!statusId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Status ID is required for delete operation');
}