n8n-nodes-idb2b 1.1.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nodes/IDB2B/IDB2B.refactored.node.js +46 -58
- package/dist/nodes/IDB2B/descriptions/leadProperties.js +343 -4
- package/dist/nodes/IDB2B/handlers/LeadOperations.d.ts +24 -0
- package/dist/nodes/IDB2B/handlers/LeadOperations.js +198 -0
- package/dist/nodes/IDB2B/interfaces/IDB2BCallLog.d.ts +13 -0
- package/dist/nodes/IDB2B/interfaces/IDB2BCallLog.js +2 -0
- package/dist/nodes/IDB2B/interfaces/IDB2BImport.d.ts +23 -0
- package/dist/nodes/IDB2B/interfaces/IDB2BImport.js +2 -0
- package/dist/nodes/IDB2B/services/LeadService.d.ts +77 -0
- package/dist/nodes/IDB2B/services/LeadService.js +241 -0
- package/package.json +2 -2
|
@@ -6,6 +6,8 @@ const authentication_1 = require("./methods/authentication");
|
|
|
6
6
|
const requests_1 = require("./methods/requests");
|
|
7
7
|
const validation_1 = require("./methods/validation");
|
|
8
8
|
const utils_1 = require("./methods/utils");
|
|
9
|
+
const LeadService_1 = require("./services/LeadService");
|
|
10
|
+
const LeadOperations_1 = require("./handlers/LeadOperations");
|
|
9
11
|
const sharedProperties_1 = require("./descriptions/sharedProperties");
|
|
10
12
|
const contactProperties_1 = require("./descriptions/contactProperties");
|
|
11
13
|
const leadProperties_1 = require("./descriptions/leadProperties");
|
|
@@ -123,36 +125,19 @@ class IDB2B {
|
|
|
123
125
|
}
|
|
124
126
|
// Handle Lead operations
|
|
125
127
|
else if (resource === 'lead') {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
endpoint = '/leads';
|
|
140
|
-
const name = this.getNodeParameter('name', i);
|
|
141
|
-
const additionalFields = this.getNodeParameter('additionalFields', i, {});
|
|
142
|
-
(0, validation_1.validateLeadData)(name);
|
|
143
|
-
body = { name: name.trim() };
|
|
144
|
-
// Add additional fields if provided
|
|
145
|
-
const fieldMappings = [
|
|
146
|
-
'owner_id', 'website', 'description', 'status_id', 'source_id',
|
|
147
|
-
'size_id', 'industry_id', 'main_contact_id', 'contact_name',
|
|
148
|
-
'contact_email', 'contact_phone_number'
|
|
149
|
-
];
|
|
150
|
-
fieldMappings.forEach(field => {
|
|
151
|
-
if (additionalFields[field]) {
|
|
152
|
-
body[field] = additionalFields[field];
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
128
|
+
const leadService = new LeadService_1.LeadService({
|
|
129
|
+
executeFunctions: this,
|
|
130
|
+
credentials,
|
|
131
|
+
accessToken,
|
|
132
|
+
itemIndex: i,
|
|
133
|
+
});
|
|
134
|
+
const leadOperations = new LeadOperations_1.LeadOperations(leadService, this, i);
|
|
135
|
+
const response = await leadOperations.execute(operation);
|
|
136
|
+
returnData.push({
|
|
137
|
+
json: response,
|
|
138
|
+
pairedItem: { item: i },
|
|
139
|
+
});
|
|
140
|
+
continue;
|
|
156
141
|
}
|
|
157
142
|
// Handle Custom operations
|
|
158
143
|
else if (resource === 'custom') {
|
|
@@ -173,36 +158,39 @@ class IDB2B {
|
|
|
173
158
|
const queryParameters = this.getNodeParameter('queryParameters', i, {});
|
|
174
159
|
qs = (0, utils_1.buildQueryString)(queryParameters);
|
|
175
160
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
161
|
+
// Only execute request for contact and custom operations
|
|
162
|
+
if (resource === 'contact' || resource === 'custom') {
|
|
163
|
+
const response = await (0, requests_1.makeRequestWithRetry)(this, {
|
|
164
|
+
method,
|
|
165
|
+
url: `${credentials.baseUrl}${endpoint}`,
|
|
166
|
+
headers: {
|
|
167
|
+
Authorization: `Bearer ${accessToken}`,
|
|
168
|
+
},
|
|
169
|
+
body,
|
|
170
|
+
qs,
|
|
171
|
+
json: true,
|
|
172
|
+
});
|
|
173
|
+
let processedResponse = response;
|
|
174
|
+
// Apply field filtering for contact getAll operations
|
|
175
|
+
if (resource === 'contact' && operation === 'getAll') {
|
|
176
|
+
const fieldsToReturn = this.getNodeParameter('fields', i, []);
|
|
177
|
+
if (fieldsToReturn.length > 0 && Array.isArray(response.data)) {
|
|
178
|
+
processedResponse = Object.assign(Object.assign({}, response), { data: response.data.map((item) => {
|
|
179
|
+
const filteredItem = {};
|
|
180
|
+
fieldsToReturn.forEach(field => {
|
|
181
|
+
if (field in item) {
|
|
182
|
+
filteredItem[field] = item[field];
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
return filteredItem;
|
|
186
|
+
}) });
|
|
187
|
+
}
|
|
200
188
|
}
|
|
189
|
+
returnData.push({
|
|
190
|
+
json: processedResponse,
|
|
191
|
+
pairedItem: { item: i },
|
|
192
|
+
});
|
|
201
193
|
}
|
|
202
|
-
returnData.push({
|
|
203
|
-
json: processedResponse,
|
|
204
|
-
pairedItem: { item: i },
|
|
205
|
-
});
|
|
206
194
|
}
|
|
207
195
|
catch (error) {
|
|
208
196
|
if (this.continueOnFail()) {
|
|
@@ -18,16 +18,125 @@ exports.leadOperations = {
|
|
|
18
18
|
action: 'Get all leads',
|
|
19
19
|
description: 'Retrieve all leads',
|
|
20
20
|
},
|
|
21
|
+
{
|
|
22
|
+
name: 'Get',
|
|
23
|
+
value: 'get',
|
|
24
|
+
action: 'Get a lead',
|
|
25
|
+
description: 'Get a single lead by ID',
|
|
26
|
+
},
|
|
21
27
|
{
|
|
22
28
|
name: 'Create',
|
|
23
29
|
value: 'create',
|
|
24
30
|
action: 'Create a lead',
|
|
25
31
|
description: 'Create a new lead',
|
|
26
32
|
},
|
|
33
|
+
{
|
|
34
|
+
name: 'Update',
|
|
35
|
+
value: 'update',
|
|
36
|
+
action: 'Update a lead',
|
|
37
|
+
description: 'Update an existing lead',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'Delete',
|
|
41
|
+
value: 'delete',
|
|
42
|
+
action: 'Delete a lead',
|
|
43
|
+
description: 'Delete a lead by ID',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Create Multiple',
|
|
47
|
+
value: 'createMultiple',
|
|
48
|
+
action: 'Create multiple leads',
|
|
49
|
+
description: 'Create multiple leads in bulk',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'Delete Multiple',
|
|
53
|
+
value: 'deleteMultiple',
|
|
54
|
+
action: 'Delete multiple leads',
|
|
55
|
+
description: 'Delete multiple leads by IDs',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'Get Call Logs',
|
|
59
|
+
value: 'getCallLogs',
|
|
60
|
+
action: 'Get lead call logs',
|
|
61
|
+
description: 'Get call logs for a specific lead',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'Assign New Contact',
|
|
65
|
+
value: 'assignNewContact',
|
|
66
|
+
action: 'Assign new contact to lead',
|
|
67
|
+
description: 'Create and assign a new contact to a lead',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'Assign Contacts',
|
|
71
|
+
value: 'assignContacts',
|
|
72
|
+
action: 'Assign contacts to lead',
|
|
73
|
+
description: 'Assign existing contacts to a lead',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'Remove Contact',
|
|
77
|
+
value: 'removeContact',
|
|
78
|
+
action: 'Remove contact from lead',
|
|
79
|
+
description: 'Remove a contact from a lead',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'Import',
|
|
83
|
+
value: 'import',
|
|
84
|
+
action: 'Import leads',
|
|
85
|
+
description: 'Import leads from CSV/Excel file',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'Get Import Template',
|
|
89
|
+
value: 'getImportTemplate',
|
|
90
|
+
action: 'Get import template',
|
|
91
|
+
description: 'Download import template for leads',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'Geocode',
|
|
95
|
+
value: 'geocode',
|
|
96
|
+
action: 'Geocode lead address',
|
|
97
|
+
description: 'Manually geocode a lead address',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'Search Nearby',
|
|
101
|
+
value: 'searchNearby',
|
|
102
|
+
action: 'Find leads near location',
|
|
103
|
+
description: 'Find leads near a specific location',
|
|
104
|
+
},
|
|
27
105
|
],
|
|
28
106
|
default: 'getAll',
|
|
29
107
|
};
|
|
30
108
|
exports.leadFields = [
|
|
109
|
+
// Lead ID field for operations that require it
|
|
110
|
+
{
|
|
111
|
+
displayName: 'Lead ID',
|
|
112
|
+
name: 'leadId',
|
|
113
|
+
type: 'string',
|
|
114
|
+
default: '',
|
|
115
|
+
required: true,
|
|
116
|
+
displayOptions: {
|
|
117
|
+
show: {
|
|
118
|
+
resource: ['lead'],
|
|
119
|
+
operation: ['get', 'update', 'delete', 'getCallLogs', 'assignNewContact', 'assignContacts', 'removeContact', 'geocode'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
description: 'ID of the lead',
|
|
123
|
+
},
|
|
124
|
+
// Contact ID field for remove contact operation
|
|
125
|
+
{
|
|
126
|
+
displayName: 'Contact ID',
|
|
127
|
+
name: 'contactId',
|
|
128
|
+
type: 'string',
|
|
129
|
+
default: '',
|
|
130
|
+
required: true,
|
|
131
|
+
displayOptions: {
|
|
132
|
+
show: {
|
|
133
|
+
resource: ['lead'],
|
|
134
|
+
operation: ['removeContact'],
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
description: 'ID of the contact to remove from the lead',
|
|
138
|
+
},
|
|
139
|
+
// Name field for create and update operations
|
|
31
140
|
{
|
|
32
141
|
displayName: 'Name',
|
|
33
142
|
name: 'name',
|
|
@@ -42,6 +151,93 @@ exports.leadFields = [
|
|
|
42
151
|
},
|
|
43
152
|
description: 'Lead name',
|
|
44
153
|
},
|
|
154
|
+
{
|
|
155
|
+
displayName: 'Name',
|
|
156
|
+
name: 'name',
|
|
157
|
+
type: 'string',
|
|
158
|
+
default: '',
|
|
159
|
+
displayOptions: {
|
|
160
|
+
show: {
|
|
161
|
+
resource: ['lead'],
|
|
162
|
+
operation: ['update'],
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
description: 'Lead name (leave empty to keep current value)',
|
|
166
|
+
},
|
|
167
|
+
// Lead IDs for bulk operations
|
|
168
|
+
{
|
|
169
|
+
displayName: 'Lead IDs',
|
|
170
|
+
name: 'leadIds',
|
|
171
|
+
type: 'string',
|
|
172
|
+
default: '',
|
|
173
|
+
required: true,
|
|
174
|
+
displayOptions: {
|
|
175
|
+
show: {
|
|
176
|
+
resource: ['lead'],
|
|
177
|
+
operation: ['deleteMultiple'],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
description: 'Comma-separated list of lead IDs to delete',
|
|
181
|
+
},
|
|
182
|
+
// Contact IDs for assign contacts operation
|
|
183
|
+
{
|
|
184
|
+
displayName: 'Contact IDs',
|
|
185
|
+
name: 'contactIds',
|
|
186
|
+
type: 'string',
|
|
187
|
+
default: '',
|
|
188
|
+
required: true,
|
|
189
|
+
displayOptions: {
|
|
190
|
+
show: {
|
|
191
|
+
resource: ['lead'],
|
|
192
|
+
operation: ['assignContacts'],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
description: 'Comma-separated list of contact IDs to assign to the lead',
|
|
196
|
+
},
|
|
197
|
+
// Leads data for bulk create
|
|
198
|
+
{
|
|
199
|
+
displayName: 'Leads Data',
|
|
200
|
+
name: 'leadsData',
|
|
201
|
+
type: 'json',
|
|
202
|
+
default: '[]',
|
|
203
|
+
required: true,
|
|
204
|
+
displayOptions: {
|
|
205
|
+
show: {
|
|
206
|
+
resource: ['lead'],
|
|
207
|
+
operation: ['createMultiple'],
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
description: 'Array of lead objects to create',
|
|
211
|
+
},
|
|
212
|
+
// Location fields for search nearby
|
|
213
|
+
{
|
|
214
|
+
displayName: 'Latitude',
|
|
215
|
+
name: 'latitude',
|
|
216
|
+
type: 'number',
|
|
217
|
+
default: 0,
|
|
218
|
+
required: true,
|
|
219
|
+
displayOptions: {
|
|
220
|
+
show: {
|
|
221
|
+
resource: ['lead'],
|
|
222
|
+
operation: ['searchNearby'],
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
description: 'Latitude for nearby search',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
displayName: 'Longitude',
|
|
229
|
+
name: 'longitude',
|
|
230
|
+
type: 'number',
|
|
231
|
+
default: 0,
|
|
232
|
+
required: true,
|
|
233
|
+
displayOptions: {
|
|
234
|
+
show: {
|
|
235
|
+
resource: ['lead'],
|
|
236
|
+
operation: ['searchNearby'],
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
description: 'Longitude for nearby search',
|
|
240
|
+
},
|
|
45
241
|
{
|
|
46
242
|
displayName: 'Additional Fields',
|
|
47
243
|
name: 'additionalFields',
|
|
@@ -51,7 +247,7 @@ exports.leadFields = [
|
|
|
51
247
|
displayOptions: {
|
|
52
248
|
show: {
|
|
53
249
|
resource: ['lead'],
|
|
54
|
-
operation: ['create'],
|
|
250
|
+
operation: ['create', 'update'],
|
|
55
251
|
},
|
|
56
252
|
},
|
|
57
253
|
options: [
|
|
@@ -134,16 +330,159 @@ exports.leadFields = [
|
|
|
134
330
|
},
|
|
135
331
|
],
|
|
136
332
|
},
|
|
333
|
+
// Additional fields for specialized operations
|
|
334
|
+
{
|
|
335
|
+
displayName: 'New Contact Data',
|
|
336
|
+
name: 'newContactData',
|
|
337
|
+
type: 'collection',
|
|
338
|
+
placeholder: 'Add Contact Field',
|
|
339
|
+
default: {},
|
|
340
|
+
displayOptions: {
|
|
341
|
+
show: {
|
|
342
|
+
resource: ['lead'],
|
|
343
|
+
operation: ['assignNewContact'],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
options: [
|
|
347
|
+
{
|
|
348
|
+
displayName: 'Name',
|
|
349
|
+
name: 'name',
|
|
350
|
+
type: 'string',
|
|
351
|
+
default: '',
|
|
352
|
+
required: true,
|
|
353
|
+
description: 'Contact name',
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
displayName: 'Email',
|
|
357
|
+
name: 'email',
|
|
358
|
+
type: 'string',
|
|
359
|
+
default: '',
|
|
360
|
+
required: true,
|
|
361
|
+
description: 'Contact email',
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
displayName: 'Phone Number',
|
|
365
|
+
name: 'phone_number',
|
|
366
|
+
type: 'string',
|
|
367
|
+
default: '',
|
|
368
|
+
description: 'Contact phone number',
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
displayName: 'Geocode Data',
|
|
374
|
+
name: 'geocodeData',
|
|
375
|
+
type: 'collection',
|
|
376
|
+
placeholder: 'Add Geocode Field',
|
|
377
|
+
default: {},
|
|
378
|
+
displayOptions: {
|
|
379
|
+
show: {
|
|
380
|
+
resource: ['lead'],
|
|
381
|
+
operation: ['geocode'],
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
options: [
|
|
385
|
+
{
|
|
386
|
+
displayName: 'Address',
|
|
387
|
+
name: 'address',
|
|
388
|
+
type: 'string',
|
|
389
|
+
default: '',
|
|
390
|
+
description: 'Address to geocode',
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
displayName: 'Latitude',
|
|
394
|
+
name: 'latitude',
|
|
395
|
+
type: 'number',
|
|
396
|
+
default: 0,
|
|
397
|
+
description: 'Latitude coordinate',
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
displayName: 'Longitude',
|
|
401
|
+
name: 'longitude',
|
|
402
|
+
type: 'number',
|
|
403
|
+
default: 0,
|
|
404
|
+
description: 'Longitude coordinate',
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
displayName: 'Import Data',
|
|
410
|
+
name: 'importData',
|
|
411
|
+
type: 'collection',
|
|
412
|
+
placeholder: 'Add Import Field',
|
|
413
|
+
default: {},
|
|
414
|
+
displayOptions: {
|
|
415
|
+
show: {
|
|
416
|
+
resource: ['lead'],
|
|
417
|
+
operation: ['import'],
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
options: [
|
|
421
|
+
{
|
|
422
|
+
displayName: 'File Path/URL',
|
|
423
|
+
name: 'file',
|
|
424
|
+
type: 'string',
|
|
425
|
+
default: '',
|
|
426
|
+
description: 'Path or URL to the import file (CSV/Excel)',
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
displayName: 'Field Mapping (JSON)',
|
|
430
|
+
name: 'mapping',
|
|
431
|
+
type: 'json',
|
|
432
|
+
default: '{}',
|
|
433
|
+
description: 'JSON object mapping CSV columns to lead fields',
|
|
434
|
+
},
|
|
435
|
+
],
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
displayName: 'Search Options',
|
|
439
|
+
name: 'searchOptions',
|
|
440
|
+
type: 'collection',
|
|
441
|
+
placeholder: 'Add Search Option',
|
|
442
|
+
default: {},
|
|
443
|
+
displayOptions: {
|
|
444
|
+
show: {
|
|
445
|
+
resource: ['lead'],
|
|
446
|
+
operation: ['searchNearby'],
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
options: [
|
|
450
|
+
{
|
|
451
|
+
displayName: 'Radius',
|
|
452
|
+
name: 'radius',
|
|
453
|
+
type: 'number',
|
|
454
|
+
default: 10,
|
|
455
|
+
description: 'Search radius',
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
displayName: 'Unit',
|
|
459
|
+
name: 'unit',
|
|
460
|
+
type: 'options',
|
|
461
|
+
default: 'km',
|
|
462
|
+
options: [
|
|
463
|
+
{
|
|
464
|
+
name: 'Kilometers',
|
|
465
|
+
value: 'km',
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
name: 'Miles',
|
|
469
|
+
value: 'miles',
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
description: 'Distance unit',
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
},
|
|
137
476
|
{
|
|
138
477
|
displayName: 'Limit',
|
|
139
478
|
name: 'limit',
|
|
140
479
|
type: 'number',
|
|
141
480
|
default: 50,
|
|
142
|
-
description: 'Maximum number of
|
|
481
|
+
description: 'Maximum number of records to return',
|
|
143
482
|
displayOptions: {
|
|
144
483
|
show: {
|
|
145
484
|
resource: ['lead'],
|
|
146
|
-
operation: ['getAll'],
|
|
485
|
+
operation: ['getAll', 'getCallLogs', 'searchNearby'],
|
|
147
486
|
},
|
|
148
487
|
},
|
|
149
488
|
},
|
|
@@ -156,7 +495,7 @@ exports.leadFields = [
|
|
|
156
495
|
displayOptions: {
|
|
157
496
|
show: {
|
|
158
497
|
resource: ['lead'],
|
|
159
|
-
operation: ['getAll'],
|
|
498
|
+
operation: ['getAll', 'getCallLogs', 'searchNearby'],
|
|
160
499
|
},
|
|
161
500
|
},
|
|
162
501
|
},
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
import { LeadService } from '../services/LeadService';
|
|
3
|
+
export declare class LeadOperations {
|
|
4
|
+
private leadService;
|
|
5
|
+
private executeFunctions;
|
|
6
|
+
private itemIndex;
|
|
7
|
+
constructor(leadService: LeadService, executeFunctions: IExecuteFunctions, itemIndex: number);
|
|
8
|
+
execute(operation: string): Promise<any>;
|
|
9
|
+
private handleGetAll;
|
|
10
|
+
private handleGet;
|
|
11
|
+
private handleCreate;
|
|
12
|
+
private handleUpdate;
|
|
13
|
+
private handleDelete;
|
|
14
|
+
private handleCreateMultiple;
|
|
15
|
+
private handleDeleteMultiple;
|
|
16
|
+
private handleGetCallLogs;
|
|
17
|
+
private handleAssignNewContact;
|
|
18
|
+
private handleAssignContacts;
|
|
19
|
+
private handleRemoveContact;
|
|
20
|
+
private handleImport;
|
|
21
|
+
private handleGetImportTemplate;
|
|
22
|
+
private handleGeocode;
|
|
23
|
+
private handleSearchNearby;
|
|
24
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LeadOperations = void 0;
|
|
4
|
+
const utils_1 = require("../methods/utils");
|
|
5
|
+
class LeadOperations {
|
|
6
|
+
constructor(leadService, executeFunctions, itemIndex) {
|
|
7
|
+
this.leadService = leadService;
|
|
8
|
+
this.executeFunctions = executeFunctions;
|
|
9
|
+
this.itemIndex = itemIndex;
|
|
10
|
+
}
|
|
11
|
+
async execute(operation) {
|
|
12
|
+
switch (operation) {
|
|
13
|
+
case 'getAll':
|
|
14
|
+
return this.handleGetAll();
|
|
15
|
+
case 'get':
|
|
16
|
+
return this.handleGet();
|
|
17
|
+
case 'create':
|
|
18
|
+
return this.handleCreate();
|
|
19
|
+
case 'update':
|
|
20
|
+
return this.handleUpdate();
|
|
21
|
+
case 'delete':
|
|
22
|
+
return this.handleDelete();
|
|
23
|
+
case 'createMultiple':
|
|
24
|
+
return this.handleCreateMultiple();
|
|
25
|
+
case 'deleteMultiple':
|
|
26
|
+
return this.handleDeleteMultiple();
|
|
27
|
+
case 'getCallLogs':
|
|
28
|
+
return this.handleGetCallLogs();
|
|
29
|
+
case 'assignNewContact':
|
|
30
|
+
return this.handleAssignNewContact();
|
|
31
|
+
case 'assignContacts':
|
|
32
|
+
return this.handleAssignContacts();
|
|
33
|
+
case 'removeContact':
|
|
34
|
+
return this.handleRemoveContact();
|
|
35
|
+
case 'import':
|
|
36
|
+
return this.handleImport();
|
|
37
|
+
case 'getImportTemplate':
|
|
38
|
+
return this.handleGetImportTemplate();
|
|
39
|
+
case 'geocode':
|
|
40
|
+
return this.handleGeocode();
|
|
41
|
+
case 'searchNearby':
|
|
42
|
+
return this.handleSearchNearby();
|
|
43
|
+
default:
|
|
44
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async handleGetAll() {
|
|
48
|
+
const limit = this.executeFunctions.getNodeParameter('limit', this.itemIndex, 50);
|
|
49
|
+
const page = this.executeFunctions.getNodeParameter('page', this.itemIndex, 1);
|
|
50
|
+
const fields = this.executeFunctions.getNodeParameter('fields', this.itemIndex, []);
|
|
51
|
+
const queryParameters = this.executeFunctions.getNodeParameter('queryParameters', this.itemIndex, {});
|
|
52
|
+
// Build query parameters
|
|
53
|
+
const queryParams = {};
|
|
54
|
+
if (queryParameters === null || queryParameters === void 0 ? void 0 : queryParameters.parameter) {
|
|
55
|
+
queryParameters.parameter.forEach((param) => {
|
|
56
|
+
if (param.name && param.value !== undefined) {
|
|
57
|
+
queryParams[param.name] = param.value;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return await this.leadService.getAll({
|
|
62
|
+
limit,
|
|
63
|
+
page,
|
|
64
|
+
fields,
|
|
65
|
+
queryParams,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async handleGet() {
|
|
69
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
70
|
+
return await this.leadService.getById(leadId);
|
|
71
|
+
}
|
|
72
|
+
async handleCreate() {
|
|
73
|
+
const name = this.executeFunctions.getNodeParameter('name', this.itemIndex);
|
|
74
|
+
const additionalFields = this.executeFunctions.getNodeParameter('additionalFields', this.itemIndex, {});
|
|
75
|
+
const leadData = {
|
|
76
|
+
name: name.trim(),
|
|
77
|
+
};
|
|
78
|
+
// Add additional fields
|
|
79
|
+
const optionalFields = [
|
|
80
|
+
'owner_id', 'website', 'description', 'status_id', 'source_id',
|
|
81
|
+
'size_id', 'industry_id', 'main_contact_id', 'contact_name',
|
|
82
|
+
'contact_email', 'contact_phone_number'
|
|
83
|
+
];
|
|
84
|
+
optionalFields.forEach(field => {
|
|
85
|
+
if (additionalFields[field] !== undefined) {
|
|
86
|
+
leadData[field] = additionalFields[field];
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return await this.leadService.create(leadData);
|
|
90
|
+
}
|
|
91
|
+
async handleUpdate() {
|
|
92
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
93
|
+
const name = this.executeFunctions.getNodeParameter('name', this.itemIndex, '');
|
|
94
|
+
const additionalFields = this.executeFunctions.getNodeParameter('additionalFields', this.itemIndex, {});
|
|
95
|
+
const updateData = {};
|
|
96
|
+
// Add name if provided
|
|
97
|
+
if (name && name.trim()) {
|
|
98
|
+
updateData.name = name.trim();
|
|
99
|
+
}
|
|
100
|
+
// Add additional fields
|
|
101
|
+
const optionalFields = [
|
|
102
|
+
'owner_id', 'website', 'description', 'status_id', 'source_id',
|
|
103
|
+
'size_id', 'industry_id', 'main_contact_id', 'contact_name',
|
|
104
|
+
'contact_email', 'contact_phone_number'
|
|
105
|
+
];
|
|
106
|
+
optionalFields.forEach(field => {
|
|
107
|
+
if (additionalFields[field] !== undefined) {
|
|
108
|
+
updateData[field] = additionalFields[field];
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
return await this.leadService.update(leadId, updateData);
|
|
112
|
+
}
|
|
113
|
+
async handleDelete() {
|
|
114
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
115
|
+
return await this.leadService.delete(leadId);
|
|
116
|
+
}
|
|
117
|
+
async handleCreateMultiple() {
|
|
118
|
+
const leadsDataString = this.executeFunctions.getNodeParameter('leadsData', this.itemIndex);
|
|
119
|
+
const leadsData = (0, utils_1.safeJsonParse)(leadsDataString, 'Leads Data');
|
|
120
|
+
if (!Array.isArray(leadsData)) {
|
|
121
|
+
throw new Error('Leads data must be an array');
|
|
122
|
+
}
|
|
123
|
+
return await this.leadService.bulkCreate(leadsData);
|
|
124
|
+
}
|
|
125
|
+
async handleDeleteMultiple() {
|
|
126
|
+
const leadIdsString = this.executeFunctions.getNodeParameter('leadIds', this.itemIndex);
|
|
127
|
+
const leadIds = leadIdsString.split(',').map(id => id.trim()).filter(id => id);
|
|
128
|
+
if (leadIds.length === 0) {
|
|
129
|
+
throw new Error('At least one lead ID is required');
|
|
130
|
+
}
|
|
131
|
+
return await this.leadService.bulkDelete(leadIds);
|
|
132
|
+
}
|
|
133
|
+
async handleGetCallLogs() {
|
|
134
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
135
|
+
const limit = this.executeFunctions.getNodeParameter('limit', this.itemIndex, 50);
|
|
136
|
+
const page = this.executeFunctions.getNodeParameter('page', this.itemIndex, 1);
|
|
137
|
+
return await this.leadService.getCallLogs(leadId, { limit, page });
|
|
138
|
+
}
|
|
139
|
+
async handleAssignNewContact() {
|
|
140
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
141
|
+
const newContactData = this.executeFunctions.getNodeParameter('newContactData', this.itemIndex, {});
|
|
142
|
+
return await this.leadService.assignNewContact(leadId, newContactData);
|
|
143
|
+
}
|
|
144
|
+
async handleAssignContacts() {
|
|
145
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
146
|
+
const contactIdsString = this.executeFunctions.getNodeParameter('contactIds', this.itemIndex);
|
|
147
|
+
const contactIds = contactIdsString.split(',').map(id => id.trim()).filter(id => id);
|
|
148
|
+
if (contactIds.length === 0) {
|
|
149
|
+
throw new Error('At least one contact ID is required');
|
|
150
|
+
}
|
|
151
|
+
return await this.leadService.assignContacts(leadId, contactIds);
|
|
152
|
+
}
|
|
153
|
+
async handleRemoveContact() {
|
|
154
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
155
|
+
const contactId = this.executeFunctions.getNodeParameter('contactId', this.itemIndex);
|
|
156
|
+
return await this.leadService.removeContact(leadId, contactId);
|
|
157
|
+
}
|
|
158
|
+
async handleImport() {
|
|
159
|
+
const importData = this.executeFunctions.getNodeParameter('importData', this.itemIndex, {});
|
|
160
|
+
const data = {};
|
|
161
|
+
if (importData.file) {
|
|
162
|
+
data.file = importData.file;
|
|
163
|
+
}
|
|
164
|
+
if (importData.mapping) {
|
|
165
|
+
data.mapping = (0, utils_1.safeJsonParse)(importData.mapping, 'Field Mapping');
|
|
166
|
+
}
|
|
167
|
+
return await this.leadService.import(data);
|
|
168
|
+
}
|
|
169
|
+
async handleGetImportTemplate() {
|
|
170
|
+
return await this.leadService.getImportTemplate();
|
|
171
|
+
}
|
|
172
|
+
async handleGeocode() {
|
|
173
|
+
const leadId = this.executeFunctions.getNodeParameter('leadId', this.itemIndex);
|
|
174
|
+
const geocodeData = this.executeFunctions.getNodeParameter('geocodeData', this.itemIndex, {});
|
|
175
|
+
return await this.leadService.geocode(leadId, geocodeData);
|
|
176
|
+
}
|
|
177
|
+
async handleSearchNearby() {
|
|
178
|
+
const latitude = this.executeFunctions.getNodeParameter('latitude', this.itemIndex);
|
|
179
|
+
const longitude = this.executeFunctions.getNodeParameter('longitude', this.itemIndex);
|
|
180
|
+
const limit = this.executeFunctions.getNodeParameter('limit', this.itemIndex, 50);
|
|
181
|
+
const page = this.executeFunctions.getNodeParameter('page', this.itemIndex, 1);
|
|
182
|
+
const searchOptions = this.executeFunctions.getNodeParameter('searchOptions', this.itemIndex, {});
|
|
183
|
+
const params = {
|
|
184
|
+
latitude,
|
|
185
|
+
longitude,
|
|
186
|
+
limit,
|
|
187
|
+
page,
|
|
188
|
+
};
|
|
189
|
+
if (searchOptions.radius !== undefined) {
|
|
190
|
+
params.radius = searchOptions.radius;
|
|
191
|
+
}
|
|
192
|
+
if (searchOptions.unit) {
|
|
193
|
+
params.unit = searchOptions.unit;
|
|
194
|
+
}
|
|
195
|
+
return await this.leadService.searchNearby(params);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.LeadOperations = LeadOperations;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface IDB2BCallLog {
|
|
2
|
+
id?: string;
|
|
3
|
+
lead_id?: string;
|
|
4
|
+
contact_id?: string;
|
|
5
|
+
user_id?: string;
|
|
6
|
+
type?: 'incoming' | 'outgoing' | 'missed';
|
|
7
|
+
duration?: number;
|
|
8
|
+
notes?: string;
|
|
9
|
+
recording_url?: string;
|
|
10
|
+
call_date?: string;
|
|
11
|
+
created_at?: string;
|
|
12
|
+
updated_at?: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface IDB2BImportResponse {
|
|
2
|
+
success: boolean;
|
|
3
|
+
message: string;
|
|
4
|
+
imported_count?: number;
|
|
5
|
+
failed_count?: number;
|
|
6
|
+
errors?: Array<{
|
|
7
|
+
row: number;
|
|
8
|
+
field: string;
|
|
9
|
+
error: string;
|
|
10
|
+
}>;
|
|
11
|
+
job_id?: string;
|
|
12
|
+
status?: 'pending' | 'processing' | 'completed' | 'failed';
|
|
13
|
+
}
|
|
14
|
+
export interface IDB2BImportTemplate {
|
|
15
|
+
fields: Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
type: string;
|
|
18
|
+
required: boolean;
|
|
19
|
+
description?: string;
|
|
20
|
+
}>;
|
|
21
|
+
sample_data?: Record<string, any>[];
|
|
22
|
+
format?: 'csv' | 'excel';
|
|
23
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
import { IDB2BLead } from '../interfaces/IDB2BLead';
|
|
3
|
+
export interface LeadServiceOptions {
|
|
4
|
+
executeFunctions: IExecuteFunctions;
|
|
5
|
+
credentials: any;
|
|
6
|
+
accessToken: string;
|
|
7
|
+
itemIndex: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PaginationParams {
|
|
10
|
+
limit?: number;
|
|
11
|
+
page?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface QueryParams {
|
|
14
|
+
[key: string]: string | number | boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface LeadGetOptions extends PaginationParams {
|
|
17
|
+
fields?: string[];
|
|
18
|
+
queryParams?: QueryParams;
|
|
19
|
+
}
|
|
20
|
+
export interface LeadCreateData {
|
|
21
|
+
name: string;
|
|
22
|
+
owner_id?: string;
|
|
23
|
+
website?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
status_id?: string;
|
|
26
|
+
source_id?: string;
|
|
27
|
+
size_id?: string;
|
|
28
|
+
industry_id?: string;
|
|
29
|
+
main_contact_id?: string;
|
|
30
|
+
contact_name?: string;
|
|
31
|
+
contact_email?: string;
|
|
32
|
+
contact_phone_number?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface LeadUpdateData extends Partial<LeadCreateData> {
|
|
35
|
+
}
|
|
36
|
+
export interface LeadImportData {
|
|
37
|
+
file?: string;
|
|
38
|
+
data?: IDB2BLead[];
|
|
39
|
+
mapping?: Record<string, string>;
|
|
40
|
+
}
|
|
41
|
+
export interface GeocodeData {
|
|
42
|
+
address?: string;
|
|
43
|
+
latitude?: number;
|
|
44
|
+
longitude?: number;
|
|
45
|
+
}
|
|
46
|
+
export interface NearbySearchParams extends PaginationParams {
|
|
47
|
+
latitude: number;
|
|
48
|
+
longitude: number;
|
|
49
|
+
radius?: number;
|
|
50
|
+
unit?: 'km' | 'miles';
|
|
51
|
+
}
|
|
52
|
+
export declare class LeadService {
|
|
53
|
+
private executeFunctions;
|
|
54
|
+
private credentials;
|
|
55
|
+
private accessToken;
|
|
56
|
+
private itemIndex;
|
|
57
|
+
private baseUrl;
|
|
58
|
+
constructor(options: LeadServiceOptions);
|
|
59
|
+
private makeRequest;
|
|
60
|
+
private validateLeadId;
|
|
61
|
+
private buildQueryString;
|
|
62
|
+
getAll(options?: LeadGetOptions): Promise<any>;
|
|
63
|
+
getById(leadId: string): Promise<any>;
|
|
64
|
+
create(leadData: LeadCreateData): Promise<any>;
|
|
65
|
+
update(leadId: string, updateData: LeadUpdateData): Promise<any>;
|
|
66
|
+
delete(leadId: string): Promise<any>;
|
|
67
|
+
bulkCreate(leads: LeadCreateData[]): Promise<any>;
|
|
68
|
+
bulkDelete(leadIds: string[]): Promise<any>;
|
|
69
|
+
getCallLogs(leadId: string, options?: PaginationParams): Promise<any>;
|
|
70
|
+
assignNewContact(leadId: string, contactData: any): Promise<any>;
|
|
71
|
+
assignContacts(leadId: string, contactIds: string[]): Promise<any>;
|
|
72
|
+
removeContact(leadId: string, contactId: string): Promise<any>;
|
|
73
|
+
import(importData: LeadImportData): Promise<any>;
|
|
74
|
+
getImportTemplate(): Promise<any>;
|
|
75
|
+
geocode(leadId: string, geocodeData: GeocodeData): Promise<any>;
|
|
76
|
+
searchNearby(params: NearbySearchParams): Promise<any>;
|
|
77
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LeadService = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const requests_1 = require("../methods/requests");
|
|
6
|
+
const validation_1 = require("../methods/validation");
|
|
7
|
+
class LeadService {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.executeFunctions = options.executeFunctions;
|
|
10
|
+
this.credentials = options.credentials;
|
|
11
|
+
this.accessToken = options.accessToken;
|
|
12
|
+
this.itemIndex = options.itemIndex;
|
|
13
|
+
this.baseUrl = this.credentials.baseUrl;
|
|
14
|
+
}
|
|
15
|
+
async makeRequest(options) {
|
|
16
|
+
const { method, endpoint, body, qs } = options;
|
|
17
|
+
return await (0, requests_1.makeRequestWithRetry)(this.executeFunctions, {
|
|
18
|
+
method,
|
|
19
|
+
url: `${this.baseUrl}${endpoint}`,
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
22
|
+
},
|
|
23
|
+
body,
|
|
24
|
+
qs,
|
|
25
|
+
json: true,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
validateLeadId(leadId) {
|
|
29
|
+
if (!leadId || typeof leadId !== 'string' || leadId.trim().length === 0) {
|
|
30
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), 'Lead ID is required and must be a non-empty string', { itemIndex: this.itemIndex });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
buildQueryString(queryParameters) {
|
|
34
|
+
const qs = {};
|
|
35
|
+
if (queryParameters === null || queryParameters === void 0 ? void 0 : queryParameters.parameter) {
|
|
36
|
+
queryParameters.parameter.forEach((param) => {
|
|
37
|
+
if (param.name && param.value !== undefined) {
|
|
38
|
+
qs[param.name] = param.value;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return qs;
|
|
43
|
+
}
|
|
44
|
+
async getAll(options = {}) {
|
|
45
|
+
const { limit = 50, page = 1, fields = [], queryParams = {} } = options;
|
|
46
|
+
const qs = { limit, page };
|
|
47
|
+
// Add additional query parameters
|
|
48
|
+
Object.assign(qs, queryParams);
|
|
49
|
+
const response = await this.makeRequest({
|
|
50
|
+
method: 'GET',
|
|
51
|
+
endpoint: '/leads',
|
|
52
|
+
qs,
|
|
53
|
+
});
|
|
54
|
+
// Apply field filtering if specified
|
|
55
|
+
if (fields.length > 0 && Array.isArray(response.data)) {
|
|
56
|
+
return Object.assign(Object.assign({}, response), { data: response.data.map((lead) => {
|
|
57
|
+
const filteredLead = {};
|
|
58
|
+
fields.forEach(field => {
|
|
59
|
+
if (field in lead) {
|
|
60
|
+
filteredLead[field] = lead[field];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return filteredLead;
|
|
64
|
+
}) });
|
|
65
|
+
}
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
async getById(leadId) {
|
|
69
|
+
this.validateLeadId(leadId);
|
|
70
|
+
return await this.makeRequest({
|
|
71
|
+
method: 'GET',
|
|
72
|
+
endpoint: `/leads/${leadId.trim()}`,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async create(leadData) {
|
|
76
|
+
(0, validation_1.validateLeadData)(leadData.name);
|
|
77
|
+
const body = {
|
|
78
|
+
name: leadData.name.trim(),
|
|
79
|
+
};
|
|
80
|
+
// Add optional fields
|
|
81
|
+
const optionalFields = [
|
|
82
|
+
'owner_id', 'website', 'description', 'status_id', 'source_id',
|
|
83
|
+
'size_id', 'industry_id', 'main_contact_id', 'contact_name',
|
|
84
|
+
'contact_email', 'contact_phone_number'
|
|
85
|
+
];
|
|
86
|
+
optionalFields.forEach(field => {
|
|
87
|
+
if (leadData[field]) {
|
|
88
|
+
body[field] = leadData[field];
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
return await this.makeRequest({
|
|
92
|
+
method: 'POST',
|
|
93
|
+
endpoint: '/leads',
|
|
94
|
+
body,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async update(leadId, updateData) {
|
|
98
|
+
this.validateLeadId(leadId);
|
|
99
|
+
if (updateData.name) {
|
|
100
|
+
(0, validation_1.validateLeadData)(updateData.name);
|
|
101
|
+
}
|
|
102
|
+
const body = {};
|
|
103
|
+
// Add fields to update
|
|
104
|
+
Object.keys(updateData).forEach(key => {
|
|
105
|
+
const value = updateData[key];
|
|
106
|
+
if (value !== undefined) {
|
|
107
|
+
if (key === 'name' && typeof value === 'string') {
|
|
108
|
+
body[key] = value.trim();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
body[key] = value;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
return await this.makeRequest({
|
|
116
|
+
method: 'PATCH',
|
|
117
|
+
endpoint: `/leads/${leadId.trim()}`,
|
|
118
|
+
body,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async delete(leadId) {
|
|
122
|
+
this.validateLeadId(leadId);
|
|
123
|
+
return await this.makeRequest({
|
|
124
|
+
method: 'DELETE',
|
|
125
|
+
endpoint: `/leads/${leadId.trim()}`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async bulkCreate(leads) {
|
|
129
|
+
if (!Array.isArray(leads) || leads.length === 0) {
|
|
130
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), 'Leads array is required and must not be empty', { itemIndex: this.itemIndex });
|
|
131
|
+
}
|
|
132
|
+
// Validate each lead
|
|
133
|
+
leads.forEach((lead, index) => {
|
|
134
|
+
try {
|
|
135
|
+
(0, validation_1.validateLeadData)(lead.name);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), `Lead at index ${index}: ${error instanceof Error ? error.message : 'Validation failed'}`, { itemIndex: this.itemIndex });
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return await this.makeRequest({
|
|
142
|
+
method: 'POST',
|
|
143
|
+
endpoint: '/leads/bulk',
|
|
144
|
+
body: { leads },
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
async bulkDelete(leadIds) {
|
|
148
|
+
if (!Array.isArray(leadIds) || leadIds.length === 0) {
|
|
149
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), 'Lead IDs array is required and must not be empty', { itemIndex: this.itemIndex });
|
|
150
|
+
}
|
|
151
|
+
// Validate each lead ID
|
|
152
|
+
leadIds.forEach((id, index) => {
|
|
153
|
+
if (!id || typeof id !== 'string' || id.trim().length === 0) {
|
|
154
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), `Invalid lead ID at index ${index}`, { itemIndex: this.itemIndex });
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return await this.makeRequest({
|
|
158
|
+
method: 'DELETE',
|
|
159
|
+
endpoint: '/leads/bulk',
|
|
160
|
+
body: { lead_ids: leadIds.map(id => id.trim()) },
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
async getCallLogs(leadId, options = {}) {
|
|
164
|
+
this.validateLeadId(leadId);
|
|
165
|
+
const { limit = 50, page = 1 } = options;
|
|
166
|
+
return await this.makeRequest({
|
|
167
|
+
method: 'GET',
|
|
168
|
+
endpoint: `/leads/${leadId.trim()}/call-logs`,
|
|
169
|
+
qs: { limit, page },
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async assignNewContact(leadId, contactData) {
|
|
173
|
+
this.validateLeadId(leadId);
|
|
174
|
+
return await this.makeRequest({
|
|
175
|
+
method: 'POST',
|
|
176
|
+
endpoint: `/leads/${leadId.trim()}/assign-new-contact`,
|
|
177
|
+
body: contactData,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
async assignContacts(leadId, contactIds) {
|
|
181
|
+
this.validateLeadId(leadId);
|
|
182
|
+
if (!Array.isArray(contactIds) || contactIds.length === 0) {
|
|
183
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), 'Contact IDs array is required and must not be empty', { itemIndex: this.itemIndex });
|
|
184
|
+
}
|
|
185
|
+
return await this.makeRequest({
|
|
186
|
+
method: 'POST',
|
|
187
|
+
endpoint: `/leads/${leadId.trim()}/assign-contacts`,
|
|
188
|
+
body: { contact_ids: contactIds },
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async removeContact(leadId, contactId) {
|
|
192
|
+
this.validateLeadId(leadId);
|
|
193
|
+
if (!contactId || typeof contactId !== 'string' || contactId.trim().length === 0) {
|
|
194
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), 'Contact ID is required and must be a non-empty string', { itemIndex: this.itemIndex });
|
|
195
|
+
}
|
|
196
|
+
return await this.makeRequest({
|
|
197
|
+
method: 'DELETE',
|
|
198
|
+
endpoint: `/leads/${leadId.trim()}/contacts/${contactId.trim()}`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
async import(importData) {
|
|
202
|
+
return await this.makeRequest({
|
|
203
|
+
method: 'POST',
|
|
204
|
+
endpoint: '/leads/import',
|
|
205
|
+
body: importData,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async getImportTemplate() {
|
|
209
|
+
return await this.makeRequest({
|
|
210
|
+
method: 'GET',
|
|
211
|
+
endpoint: '/leads/import/template',
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
async geocode(leadId, geocodeData) {
|
|
215
|
+
this.validateLeadId(leadId);
|
|
216
|
+
return await this.makeRequest({
|
|
217
|
+
method: 'POST',
|
|
218
|
+
endpoint: `/leads/${leadId.trim()}/geocode`,
|
|
219
|
+
body: geocodeData,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async searchNearby(params) {
|
|
223
|
+
const { latitude, longitude, radius = 10, unit = 'km', limit = 50, page = 1 } = params;
|
|
224
|
+
if (typeof latitude !== 'number' || typeof longitude !== 'number') {
|
|
225
|
+
throw new n8n_workflow_1.NodeOperationError(this.executeFunctions.getNode(), 'Latitude and longitude are required and must be numbers', { itemIndex: this.itemIndex });
|
|
226
|
+
}
|
|
227
|
+
return await this.makeRequest({
|
|
228
|
+
method: 'GET',
|
|
229
|
+
endpoint: '/leads/nearby/search',
|
|
230
|
+
qs: {
|
|
231
|
+
latitude,
|
|
232
|
+
longitude,
|
|
233
|
+
radius,
|
|
234
|
+
unit,
|
|
235
|
+
limit,
|
|
236
|
+
page,
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
exports.LeadService = LeadService;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-idb2b",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "n8n community node for IDB2B CRM",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dist/credentials/IDB2BApi.credentials.js"
|
|
21
21
|
],
|
|
22
22
|
"nodes": [
|
|
23
|
-
"dist/nodes/IDB2B/IDB2B.node.js"
|
|
23
|
+
"dist/nodes/IDB2B/IDB2B.refactored.node.js"
|
|
24
24
|
]
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|