@pegasuss/n8n-nodes-suitecrm 0.1.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/credentials/SuiteCRMApi.credentials.d.ts +8 -0
- package/dist/credentials/SuiteCRMApi.credentials.d.ts.map +1 -0
- package/dist/credentials/SuiteCRMApi.credentials.js +40 -0
- package/dist/credentials/SuiteCRMApi.credentials.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/SuiteCRM/SuiteCRM.node.d.ts +6 -0
- package/dist/nodes/SuiteCRM/SuiteCRM.node.d.ts.map +1 -0
- package/dist/nodes/SuiteCRM/SuiteCRM.node.js +1294 -0
- package/dist/nodes/SuiteCRM/SuiteCRM.node.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,1294 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SuiteCRM = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
// Helper: obtain OAuth2 access token
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
async function getAccessToken(context, baseUrl, clientId, clientSecret) {
|
|
9
|
+
const response = await context.helpers.request({
|
|
10
|
+
method: 'POST',
|
|
11
|
+
url: `${baseUrl}/api/v8/oauth/access_token`,
|
|
12
|
+
form: {
|
|
13
|
+
grant_type: 'client_credentials',
|
|
14
|
+
client_id: clientId,
|
|
15
|
+
client_secret: clientSecret,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
const parsed = typeof response === 'string' ? JSON.parse(response) : response;
|
|
19
|
+
if (!parsed.access_token) {
|
|
20
|
+
throw new Error(`SuiteCRM OAuth2 error: ${parsed.error || 'no access_token returned'}`);
|
|
21
|
+
}
|
|
22
|
+
return parsed.access_token;
|
|
23
|
+
}
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
// Helper: generic API call
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
async function apiRequest(context, token, baseUrl, method, endpoint, body, qs) {
|
|
28
|
+
var _a, _b, _c;
|
|
29
|
+
const options = {
|
|
30
|
+
method,
|
|
31
|
+
url: `${baseUrl}/api/v8${endpoint}`,
|
|
32
|
+
headers: {
|
|
33
|
+
Authorization: `Bearer ${token}`,
|
|
34
|
+
'Content-Type': 'application/vnd.api+json',
|
|
35
|
+
Accept: 'application/vnd.api+json',
|
|
36
|
+
},
|
|
37
|
+
json: true,
|
|
38
|
+
};
|
|
39
|
+
if (body)
|
|
40
|
+
options.body = body;
|
|
41
|
+
if (qs)
|
|
42
|
+
options.qs = qs;
|
|
43
|
+
try {
|
|
44
|
+
return await context.helpers.request(options);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const msg = ((_c = (_b = (_a = error === null || error === void 0 ? void 0 : error.error) === null || _a === void 0 ? void 0 : _a.errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.detail) ||
|
|
48
|
+
(error === null || error === void 0 ? void 0 : error.message) ||
|
|
49
|
+
JSON.stringify(error);
|
|
50
|
+
throw new n8n_workflow_1.NodeOperationError(context.getNode(), `SuiteCRM API error [${method} ${endpoint}]: ${msg}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
54
|
+
// Helper: build JSON:API create/update body
|
|
55
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
function buildJsonApiBody(moduleName, attributes, id) {
|
|
57
|
+
const data = {
|
|
58
|
+
type: moduleName,
|
|
59
|
+
attributes,
|
|
60
|
+
};
|
|
61
|
+
if (id)
|
|
62
|
+
data.id = id;
|
|
63
|
+
return { data };
|
|
64
|
+
}
|
|
65
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
66
|
+
// Helper: extract attributes from JSON:API response
|
|
67
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
68
|
+
function extractData(response) {
|
|
69
|
+
if (!response)
|
|
70
|
+
return {};
|
|
71
|
+
if (response.data) {
|
|
72
|
+
const { id, type, attributes } = response.data;
|
|
73
|
+
return { id, type, ...attributes };
|
|
74
|
+
}
|
|
75
|
+
return response;
|
|
76
|
+
}
|
|
77
|
+
function extractDataList(response) {
|
|
78
|
+
if (!(response === null || response === void 0 ? void 0 : response.data))
|
|
79
|
+
return [];
|
|
80
|
+
return response.data.map((item) => ({
|
|
81
|
+
id: item.id,
|
|
82
|
+
type: item.type,
|
|
83
|
+
...item.attributes,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
87
|
+
// Node definition
|
|
88
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
89
|
+
class SuiteCRM {
|
|
90
|
+
constructor() {
|
|
91
|
+
this.description = {
|
|
92
|
+
displayName: 'SuiteCRM',
|
|
93
|
+
name: 'suiteCRM',
|
|
94
|
+
icon: 'file:suitecrm.svg',
|
|
95
|
+
group: ['transform'],
|
|
96
|
+
version: 1,
|
|
97
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
98
|
+
description: 'Interact with SuiteCRM – open source enterprise CRM. Manage Contacts, Accounts, Leads, Opportunities and Activities via the V8 REST API.',
|
|
99
|
+
defaults: {
|
|
100
|
+
name: 'SuiteCRM',
|
|
101
|
+
},
|
|
102
|
+
inputs: ['main'],
|
|
103
|
+
outputs: ['main'],
|
|
104
|
+
credentials: [
|
|
105
|
+
{
|
|
106
|
+
name: 'suiteCRMApi',
|
|
107
|
+
required: true,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
properties: [
|
|
111
|
+
// ── Resource selector ────────────────────────────────────────────────
|
|
112
|
+
{
|
|
113
|
+
displayName: 'Resource',
|
|
114
|
+
name: 'resource',
|
|
115
|
+
type: 'options',
|
|
116
|
+
noDataExpression: true,
|
|
117
|
+
options: [
|
|
118
|
+
{ name: 'Account', value: 'account' },
|
|
119
|
+
{ name: 'Contact', value: 'contact' },
|
|
120
|
+
{ name: 'Lead', value: 'lead' },
|
|
121
|
+
{ name: 'Note / Activity', value: 'note' },
|
|
122
|
+
{ name: 'Opportunity', value: 'opportunity' },
|
|
123
|
+
],
|
|
124
|
+
default: 'contact',
|
|
125
|
+
},
|
|
126
|
+
// ════════════════════════════════════════════════════════════════════
|
|
127
|
+
// CONTACT operations
|
|
128
|
+
// ════════════════════════════════════════════════════════════════════
|
|
129
|
+
{
|
|
130
|
+
displayName: 'Operation',
|
|
131
|
+
name: 'operation',
|
|
132
|
+
type: 'options',
|
|
133
|
+
noDataExpression: true,
|
|
134
|
+
displayOptions: { show: { resource: ['contact'] } },
|
|
135
|
+
options: [
|
|
136
|
+
{
|
|
137
|
+
name: 'Create',
|
|
138
|
+
value: 'create',
|
|
139
|
+
description: 'Create a new contact',
|
|
140
|
+
action: 'Create a contact',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'Delete',
|
|
144
|
+
value: 'delete',
|
|
145
|
+
description: 'Delete a contact',
|
|
146
|
+
action: 'Delete a contact',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'Get',
|
|
150
|
+
value: 'get',
|
|
151
|
+
description: 'Get a contact by ID',
|
|
152
|
+
action: 'Get a contact',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: 'Get Many',
|
|
156
|
+
value: 'getMany',
|
|
157
|
+
description: 'Get multiple contacts',
|
|
158
|
+
action: 'Get many contacts',
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: 'Search',
|
|
162
|
+
value: 'search',
|
|
163
|
+
description: 'Search contacts by field',
|
|
164
|
+
action: 'Search contacts',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'Update',
|
|
168
|
+
value: 'update',
|
|
169
|
+
description: 'Update a contact',
|
|
170
|
+
action: 'Update a contact',
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
default: 'create',
|
|
174
|
+
},
|
|
175
|
+
// ════════════════════════════════════════════════════════════════════
|
|
176
|
+
// ACCOUNT operations
|
|
177
|
+
// ════════════════════════════════════════════════════════════════════
|
|
178
|
+
{
|
|
179
|
+
displayName: 'Operation',
|
|
180
|
+
name: 'operation',
|
|
181
|
+
type: 'options',
|
|
182
|
+
noDataExpression: true,
|
|
183
|
+
displayOptions: { show: { resource: ['account'] } },
|
|
184
|
+
options: [
|
|
185
|
+
{
|
|
186
|
+
name: 'Create',
|
|
187
|
+
value: 'create',
|
|
188
|
+
description: 'Create a new account',
|
|
189
|
+
action: 'Create an account',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'Delete',
|
|
193
|
+
value: 'delete',
|
|
194
|
+
description: 'Delete an account',
|
|
195
|
+
action: 'Delete an account',
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'Get',
|
|
199
|
+
value: 'get',
|
|
200
|
+
description: 'Get an account by ID',
|
|
201
|
+
action: 'Get an account',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: 'Get Many',
|
|
205
|
+
value: 'getMany',
|
|
206
|
+
description: 'Get multiple accounts',
|
|
207
|
+
action: 'Get many accounts',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'Search',
|
|
211
|
+
value: 'search',
|
|
212
|
+
description: 'Search accounts by field',
|
|
213
|
+
action: 'Search accounts',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: 'Update',
|
|
217
|
+
value: 'update',
|
|
218
|
+
description: 'Update an account',
|
|
219
|
+
action: 'Update an account',
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
default: 'create',
|
|
223
|
+
},
|
|
224
|
+
// ════════════════════════════════════════════════════════════════════
|
|
225
|
+
// LEAD operations
|
|
226
|
+
// ════════════════════════════════════════════════════════════════════
|
|
227
|
+
{
|
|
228
|
+
displayName: 'Operation',
|
|
229
|
+
name: 'operation',
|
|
230
|
+
type: 'options',
|
|
231
|
+
noDataExpression: true,
|
|
232
|
+
displayOptions: { show: { resource: ['lead'] } },
|
|
233
|
+
options: [
|
|
234
|
+
{
|
|
235
|
+
name: 'Convert',
|
|
236
|
+
value: 'convert',
|
|
237
|
+
description: 'Convert lead to Contact/Account/Opportunity',
|
|
238
|
+
action: 'Convert a lead',
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: 'Create',
|
|
242
|
+
value: 'create',
|
|
243
|
+
description: 'Create a new lead',
|
|
244
|
+
action: 'Create a lead',
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
name: 'Get',
|
|
248
|
+
value: 'get',
|
|
249
|
+
description: 'Get a lead by ID',
|
|
250
|
+
action: 'Get a lead',
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'Get Many',
|
|
254
|
+
value: 'getMany',
|
|
255
|
+
description: 'Get multiple leads',
|
|
256
|
+
action: 'Get many leads',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: 'Update',
|
|
260
|
+
value: 'update',
|
|
261
|
+
description: 'Update a lead',
|
|
262
|
+
action: 'Update a lead',
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
default: 'create',
|
|
266
|
+
},
|
|
267
|
+
// ════════════════════════════════════════════════════════════════════
|
|
268
|
+
// OPPORTUNITY operations
|
|
269
|
+
// ════════════════════════════════════════════════════════════════════
|
|
270
|
+
{
|
|
271
|
+
displayName: 'Operation',
|
|
272
|
+
name: 'operation',
|
|
273
|
+
type: 'options',
|
|
274
|
+
noDataExpression: true,
|
|
275
|
+
displayOptions: { show: { resource: ['opportunity'] } },
|
|
276
|
+
options: [
|
|
277
|
+
{
|
|
278
|
+
name: 'Create',
|
|
279
|
+
value: 'create',
|
|
280
|
+
description: 'Create a new opportunity',
|
|
281
|
+
action: 'Create an opportunity',
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: 'Delete',
|
|
285
|
+
value: 'delete',
|
|
286
|
+
description: 'Delete an opportunity',
|
|
287
|
+
action: 'Delete an opportunity',
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: 'Get',
|
|
291
|
+
value: 'get',
|
|
292
|
+
description: 'Get an opportunity by ID',
|
|
293
|
+
action: 'Get an opportunity',
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: 'Get Many',
|
|
297
|
+
value: 'getMany',
|
|
298
|
+
description: 'Get multiple opportunities',
|
|
299
|
+
action: 'Get many opportunities',
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: 'Update',
|
|
303
|
+
value: 'update',
|
|
304
|
+
description: 'Update an opportunity',
|
|
305
|
+
action: 'Update an opportunity',
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
default: 'create',
|
|
309
|
+
},
|
|
310
|
+
// ════════════════════════════════════════════════════════════════════
|
|
311
|
+
// NOTE / ACTIVITY operations
|
|
312
|
+
// ════════════════════════════════════════════════════════════════════
|
|
313
|
+
{
|
|
314
|
+
displayName: 'Operation',
|
|
315
|
+
name: 'operation',
|
|
316
|
+
type: 'options',
|
|
317
|
+
noDataExpression: true,
|
|
318
|
+
displayOptions: { show: { resource: ['note'] } },
|
|
319
|
+
options: [
|
|
320
|
+
{
|
|
321
|
+
name: 'Create Note',
|
|
322
|
+
value: 'createNote',
|
|
323
|
+
description: 'Create a note linked to a record',
|
|
324
|
+
action: 'Create a note',
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
name: 'List Activities',
|
|
328
|
+
value: 'listActivities',
|
|
329
|
+
description: 'List activities (Notes) for a parent record',
|
|
330
|
+
action: 'List activities',
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
default: 'createNote',
|
|
334
|
+
},
|
|
335
|
+
// ════════════════════════════════════════════════════════════════════
|
|
336
|
+
// SHARED: Record ID field
|
|
337
|
+
// ════════════════════════════════════════════════════════════════════
|
|
338
|
+
{
|
|
339
|
+
displayName: 'Record ID',
|
|
340
|
+
name: 'recordId',
|
|
341
|
+
type: 'string',
|
|
342
|
+
required: true,
|
|
343
|
+
default: '',
|
|
344
|
+
description: 'The unique ID of the record in SuiteCRM',
|
|
345
|
+
displayOptions: {
|
|
346
|
+
show: {
|
|
347
|
+
operation: ['get', 'update', 'delete', 'convert'],
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
// ════════════════════════════════════════════════════════════════════
|
|
352
|
+
// CONTACT: Create fields
|
|
353
|
+
// ════════════════════════════════════════════════════════════════════
|
|
354
|
+
{
|
|
355
|
+
displayName: 'First Name',
|
|
356
|
+
name: 'firstName',
|
|
357
|
+
type: 'string',
|
|
358
|
+
default: '',
|
|
359
|
+
displayOptions: {
|
|
360
|
+
show: { resource: ['contact'], operation: ['create'] },
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
displayName: 'Last Name',
|
|
365
|
+
name: 'lastName',
|
|
366
|
+
type: 'string',
|
|
367
|
+
required: true,
|
|
368
|
+
default: '',
|
|
369
|
+
displayOptions: {
|
|
370
|
+
show: { resource: ['contact'], operation: ['create'] },
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
displayName: 'Email',
|
|
375
|
+
name: 'email',
|
|
376
|
+
type: 'string',
|
|
377
|
+
placeholder: 'name@email.com',
|
|
378
|
+
default: '',
|
|
379
|
+
displayOptions: {
|
|
380
|
+
show: { resource: ['contact'], operation: ['create'] },
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
displayName: 'Phone',
|
|
385
|
+
name: 'phone',
|
|
386
|
+
type: 'string',
|
|
387
|
+
default: '',
|
|
388
|
+
displayOptions: {
|
|
389
|
+
show: { resource: ['contact'], operation: ['create'] },
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
displayName: 'Account ID',
|
|
394
|
+
name: 'accountId',
|
|
395
|
+
type: 'string',
|
|
396
|
+
default: '',
|
|
397
|
+
description: 'ID of the account to link this contact to',
|
|
398
|
+
displayOptions: {
|
|
399
|
+
show: { resource: ['contact'], operation: ['create'] },
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
displayName: 'Additional Fields',
|
|
404
|
+
name: 'contactAdditionalFields',
|
|
405
|
+
type: 'collection',
|
|
406
|
+
placeholder: 'Add Field',
|
|
407
|
+
default: {},
|
|
408
|
+
displayOptions: {
|
|
409
|
+
show: { resource: ['contact'], operation: ['create'] },
|
|
410
|
+
},
|
|
411
|
+
options: [
|
|
412
|
+
{ displayName: 'Department', name: 'department', type: 'string', default: '' },
|
|
413
|
+
{ displayName: 'Do Not Call', name: 'do_not_call', type: 'boolean', default: false },
|
|
414
|
+
{ displayName: 'Lead Source', name: 'lead_source', type: 'string', default: '' },
|
|
415
|
+
{ displayName: 'Mobile', name: 'phone_mobile', type: 'string', default: '' },
|
|
416
|
+
{ displayName: 'Salutation', name: 'salutation', type: 'string', default: '' },
|
|
417
|
+
{ displayName: 'Title', name: 'title', type: 'string', default: '' },
|
|
418
|
+
{
|
|
419
|
+
displayName: 'Billing City',
|
|
420
|
+
name: 'primary_address_city',
|
|
421
|
+
type: 'string',
|
|
422
|
+
default: '',
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
displayName: 'Billing Country',
|
|
426
|
+
name: 'primary_address_country',
|
|
427
|
+
type: 'string',
|
|
428
|
+
default: '',
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
displayName: 'Billing State',
|
|
432
|
+
name: 'primary_address_state',
|
|
433
|
+
type: 'string',
|
|
434
|
+
default: '',
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
displayName: 'Billing Street',
|
|
438
|
+
name: 'primary_address_street',
|
|
439
|
+
type: 'string',
|
|
440
|
+
default: '',
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
displayName: 'Billing Zip',
|
|
444
|
+
name: 'primary_address_postalcode',
|
|
445
|
+
type: 'string',
|
|
446
|
+
default: '',
|
|
447
|
+
},
|
|
448
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
449
|
+
],
|
|
450
|
+
},
|
|
451
|
+
// ════════════════════════════════════════════════════════════════════
|
|
452
|
+
// CONTACT: Update fields
|
|
453
|
+
// ════════════════════════════════════════════════════════════════════
|
|
454
|
+
{
|
|
455
|
+
displayName: 'Update Fields',
|
|
456
|
+
name: 'contactUpdateFields',
|
|
457
|
+
type: 'collection',
|
|
458
|
+
placeholder: 'Add Field',
|
|
459
|
+
default: {},
|
|
460
|
+
displayOptions: {
|
|
461
|
+
show: { resource: ['contact'], operation: ['update'] },
|
|
462
|
+
},
|
|
463
|
+
options: [
|
|
464
|
+
{ displayName: 'Account ID', name: 'account_id', type: 'string', default: '' },
|
|
465
|
+
{ displayName: 'Department', name: 'department', type: 'string', default: '' },
|
|
466
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
467
|
+
{ displayName: 'Email', name: 'email1', type: 'string', default: '' },
|
|
468
|
+
{ displayName: 'First Name', name: 'first_name', type: 'string', default: '' },
|
|
469
|
+
{ displayName: 'Last Name', name: 'last_name', type: 'string', default: '' },
|
|
470
|
+
{ displayName: 'Lead Source', name: 'lead_source', type: 'string', default: '' },
|
|
471
|
+
{ displayName: 'Mobile', name: 'phone_mobile', type: 'string', default: '' },
|
|
472
|
+
{ displayName: 'Phone', name: 'phone_work', type: 'string', default: '' },
|
|
473
|
+
{ displayName: 'Title', name: 'title', type: 'string', default: '' },
|
|
474
|
+
],
|
|
475
|
+
},
|
|
476
|
+
// ════════════════════════════════════════════════════════════════════
|
|
477
|
+
// ACCOUNT: Create fields
|
|
478
|
+
// ════════════════════════════════════════════════════════════════════
|
|
479
|
+
{
|
|
480
|
+
displayName: 'Account Name',
|
|
481
|
+
name: 'accountName',
|
|
482
|
+
type: 'string',
|
|
483
|
+
required: true,
|
|
484
|
+
default: '',
|
|
485
|
+
displayOptions: {
|
|
486
|
+
show: { resource: ['account'], operation: ['create'] },
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
displayName: 'Additional Fields',
|
|
491
|
+
name: 'accountAdditionalFields',
|
|
492
|
+
type: 'collection',
|
|
493
|
+
placeholder: 'Add Field',
|
|
494
|
+
default: {},
|
|
495
|
+
displayOptions: {
|
|
496
|
+
show: { resource: ['account'], operation: ['create'] },
|
|
497
|
+
},
|
|
498
|
+
options: [
|
|
499
|
+
{ displayName: 'Annual Revenue', name: 'annual_revenue', type: 'number', default: 0 },
|
|
500
|
+
{
|
|
501
|
+
displayName: 'Billing City',
|
|
502
|
+
name: 'billing_address_city',
|
|
503
|
+
type: 'string',
|
|
504
|
+
default: '',
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
displayName: 'Billing Country',
|
|
508
|
+
name: 'billing_address_country',
|
|
509
|
+
type: 'string',
|
|
510
|
+
default: '',
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
displayName: 'Billing State',
|
|
514
|
+
name: 'billing_address_state',
|
|
515
|
+
type: 'string',
|
|
516
|
+
default: '',
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
displayName: 'Billing Street',
|
|
520
|
+
name: 'billing_address_street',
|
|
521
|
+
type: 'string',
|
|
522
|
+
default: '',
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
displayName: 'Billing Zip',
|
|
526
|
+
name: 'billing_address_postalcode',
|
|
527
|
+
type: 'string',
|
|
528
|
+
default: '',
|
|
529
|
+
},
|
|
530
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
531
|
+
{ displayName: 'Email', name: 'email1', type: 'string', default: '' },
|
|
532
|
+
{ displayName: 'Employees', name: 'employees', type: 'number', default: 0 },
|
|
533
|
+
{ displayName: 'Industry', name: 'industry', type: 'string', default: '' },
|
|
534
|
+
{ displayName: 'Phone', name: 'phone_office', type: 'string', default: '' },
|
|
535
|
+
{ displayName: 'Rating', name: 'rating', type: 'string', default: '' },
|
|
536
|
+
{ displayName: 'Type', name: 'account_type', type: 'string', default: '' },
|
|
537
|
+
{ displayName: 'Website', name: 'website', type: 'string', default: '' },
|
|
538
|
+
],
|
|
539
|
+
},
|
|
540
|
+
// ACCOUNT: Update fields
|
|
541
|
+
{
|
|
542
|
+
displayName: 'Update Fields',
|
|
543
|
+
name: 'accountUpdateFields',
|
|
544
|
+
type: 'collection',
|
|
545
|
+
placeholder: 'Add Field',
|
|
546
|
+
default: {},
|
|
547
|
+
displayOptions: {
|
|
548
|
+
show: { resource: ['account'], operation: ['update'] },
|
|
549
|
+
},
|
|
550
|
+
options: [
|
|
551
|
+
{ displayName: 'Annual Revenue', name: 'annual_revenue', type: 'number', default: 0 },
|
|
552
|
+
{
|
|
553
|
+
displayName: 'Billing City',
|
|
554
|
+
name: 'billing_address_city',
|
|
555
|
+
type: 'string',
|
|
556
|
+
default: '',
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
displayName: 'Billing Country',
|
|
560
|
+
name: 'billing_address_country',
|
|
561
|
+
type: 'string',
|
|
562
|
+
default: '',
|
|
563
|
+
},
|
|
564
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
565
|
+
{ displayName: 'Email', name: 'email1', type: 'string', default: '' },
|
|
566
|
+
{ displayName: 'Industry', name: 'industry', type: 'string', default: '' },
|
|
567
|
+
{ displayName: 'Name', name: 'name', type: 'string', default: '' },
|
|
568
|
+
{ displayName: 'Phone', name: 'phone_office', type: 'string', default: '' },
|
|
569
|
+
{ displayName: 'Website', name: 'website', type: 'string', default: '' },
|
|
570
|
+
],
|
|
571
|
+
},
|
|
572
|
+
// ════════════════════════════════════════════════════════════════════
|
|
573
|
+
// LEAD: Create fields
|
|
574
|
+
// ════════════════════════════════════════════════════════════════════
|
|
575
|
+
{
|
|
576
|
+
displayName: 'First Name',
|
|
577
|
+
name: 'leadFirstName',
|
|
578
|
+
type: 'string',
|
|
579
|
+
default: '',
|
|
580
|
+
displayOptions: {
|
|
581
|
+
show: { resource: ['lead'], operation: ['create'] },
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
displayName: 'Last Name',
|
|
586
|
+
name: 'leadLastName',
|
|
587
|
+
type: 'string',
|
|
588
|
+
required: true,
|
|
589
|
+
default: '',
|
|
590
|
+
displayOptions: {
|
|
591
|
+
show: { resource: ['lead'], operation: ['create'] },
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
displayName: 'Company',
|
|
596
|
+
name: 'leadCompany',
|
|
597
|
+
type: 'string',
|
|
598
|
+
required: true,
|
|
599
|
+
default: '',
|
|
600
|
+
displayOptions: {
|
|
601
|
+
show: { resource: ['lead'], operation: ['create'] },
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
displayName: 'Email',
|
|
606
|
+
name: 'leadEmail',
|
|
607
|
+
type: 'string',
|
|
608
|
+
placeholder: 'name@email.com',
|
|
609
|
+
default: '',
|
|
610
|
+
displayOptions: {
|
|
611
|
+
show: { resource: ['lead'], operation: ['create'] },
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
displayName: 'Phone',
|
|
616
|
+
name: 'leadPhone',
|
|
617
|
+
type: 'string',
|
|
618
|
+
default: '',
|
|
619
|
+
displayOptions: {
|
|
620
|
+
show: { resource: ['lead'], operation: ['create'] },
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
displayName: 'Additional Fields',
|
|
625
|
+
name: 'leadAdditionalFields',
|
|
626
|
+
type: 'collection',
|
|
627
|
+
placeholder: 'Add Field',
|
|
628
|
+
default: {},
|
|
629
|
+
displayOptions: {
|
|
630
|
+
show: { resource: ['lead'], operation: ['create'] },
|
|
631
|
+
},
|
|
632
|
+
options: [
|
|
633
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
634
|
+
{ displayName: 'Do Not Call', name: 'do_not_call', type: 'boolean', default: false },
|
|
635
|
+
{ displayName: 'Lead Source', name: 'lead_source', type: 'string', default: '' },
|
|
636
|
+
{ displayName: 'Lead Source Description', name: 'lead_source_description', type: 'string', default: '' },
|
|
637
|
+
{ displayName: 'Mobile', name: 'phone_mobile', type: 'string', default: '' },
|
|
638
|
+
{ displayName: 'Referred By', name: 'refered_by', type: 'string', default: '' },
|
|
639
|
+
{ displayName: 'Salutation', name: 'salutation', type: 'string', default: '' },
|
|
640
|
+
{ displayName: 'Status', name: 'status', type: 'string', default: '' },
|
|
641
|
+
{ displayName: 'Title', name: 'title', type: 'string', default: '' },
|
|
642
|
+
{ displayName: 'Website', name: 'website', type: 'string', default: '' },
|
|
643
|
+
],
|
|
644
|
+
},
|
|
645
|
+
// LEAD: Update fields
|
|
646
|
+
{
|
|
647
|
+
displayName: 'Update Fields',
|
|
648
|
+
name: 'leadUpdateFields',
|
|
649
|
+
type: 'collection',
|
|
650
|
+
placeholder: 'Add Field',
|
|
651
|
+
default: {},
|
|
652
|
+
displayOptions: {
|
|
653
|
+
show: { resource: ['lead'], operation: ['update'] },
|
|
654
|
+
},
|
|
655
|
+
options: [
|
|
656
|
+
{ displayName: 'Company', name: 'account_name', type: 'string', default: '' },
|
|
657
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
658
|
+
{ displayName: 'Email', name: 'email1', type: 'string', default: '' },
|
|
659
|
+
{ displayName: 'First Name', name: 'first_name', type: 'string', default: '' },
|
|
660
|
+
{ displayName: 'Last Name', name: 'last_name', type: 'string', default: '' },
|
|
661
|
+
{ displayName: 'Lead Source', name: 'lead_source', type: 'string', default: '' },
|
|
662
|
+
{ displayName: 'Phone', name: 'phone_work', type: 'string', default: '' },
|
|
663
|
+
{ displayName: 'Status', name: 'status', type: 'string', default: '' },
|
|
664
|
+
{ displayName: 'Title', name: 'title', type: 'string', default: '' },
|
|
665
|
+
],
|
|
666
|
+
},
|
|
667
|
+
// LEAD: Convert fields
|
|
668
|
+
{
|
|
669
|
+
displayName: 'Create Contact',
|
|
670
|
+
name: 'convertCreateContact',
|
|
671
|
+
type: 'boolean',
|
|
672
|
+
default: true,
|
|
673
|
+
description: 'Whether to create a Contact from this lead',
|
|
674
|
+
displayOptions: {
|
|
675
|
+
show: { resource: ['lead'], operation: ['convert'] },
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
displayName: 'Create Account',
|
|
680
|
+
name: 'convertCreateAccount',
|
|
681
|
+
type: 'boolean',
|
|
682
|
+
default: true,
|
|
683
|
+
description: 'Whether to create an Account from this lead',
|
|
684
|
+
displayOptions: {
|
|
685
|
+
show: { resource: ['lead'], operation: ['convert'] },
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
displayName: 'Create Opportunity',
|
|
690
|
+
name: 'convertCreateOpportunity',
|
|
691
|
+
type: 'boolean',
|
|
692
|
+
default: false,
|
|
693
|
+
description: 'Whether to create an Opportunity from this lead',
|
|
694
|
+
displayOptions: {
|
|
695
|
+
show: { resource: ['lead'], operation: ['convert'] },
|
|
696
|
+
},
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
displayName: 'Opportunity Name',
|
|
700
|
+
name: 'convertOpportunityName',
|
|
701
|
+
type: 'string',
|
|
702
|
+
default: '',
|
|
703
|
+
description: 'Name of the opportunity to create (required if Create Opportunity is true)',
|
|
704
|
+
displayOptions: {
|
|
705
|
+
show: {
|
|
706
|
+
resource: ['lead'],
|
|
707
|
+
operation: ['convert'],
|
|
708
|
+
convertCreateOpportunity: [true],
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
displayName: 'Opportunity Close Date',
|
|
714
|
+
name: 'convertOpportunityCloseDate',
|
|
715
|
+
type: 'dateTime',
|
|
716
|
+
default: '',
|
|
717
|
+
displayOptions: {
|
|
718
|
+
show: {
|
|
719
|
+
resource: ['lead'],
|
|
720
|
+
operation: ['convert'],
|
|
721
|
+
convertCreateOpportunity: [true],
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
displayName: 'Opportunity Amount',
|
|
727
|
+
name: 'convertOpportunityAmount',
|
|
728
|
+
type: 'number',
|
|
729
|
+
default: 0,
|
|
730
|
+
displayOptions: {
|
|
731
|
+
show: {
|
|
732
|
+
resource: ['lead'],
|
|
733
|
+
operation: ['convert'],
|
|
734
|
+
convertCreateOpportunity: [true],
|
|
735
|
+
},
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
// ════════════════════════════════════════════════════════════════════
|
|
739
|
+
// OPPORTUNITY: Create fields
|
|
740
|
+
// ════════════════════════════════════════════════════════════════════
|
|
741
|
+
{
|
|
742
|
+
displayName: 'Opportunity Name',
|
|
743
|
+
name: 'opportunityName',
|
|
744
|
+
type: 'string',
|
|
745
|
+
required: true,
|
|
746
|
+
default: '',
|
|
747
|
+
displayOptions: {
|
|
748
|
+
show: { resource: ['opportunity'], operation: ['create'] },
|
|
749
|
+
},
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
displayName: 'Close Date',
|
|
753
|
+
name: 'closeDate',
|
|
754
|
+
type: 'dateTime',
|
|
755
|
+
required: true,
|
|
756
|
+
default: '',
|
|
757
|
+
displayOptions: {
|
|
758
|
+
show: { resource: ['opportunity'], operation: ['create'] },
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
displayName: 'Sales Stage',
|
|
763
|
+
name: 'salesStage',
|
|
764
|
+
type: 'options',
|
|
765
|
+
required: true,
|
|
766
|
+
default: 'Prospecting',
|
|
767
|
+
displayOptions: {
|
|
768
|
+
show: { resource: ['opportunity'], operation: ['create'] },
|
|
769
|
+
},
|
|
770
|
+
options: [
|
|
771
|
+
{ name: 'Closed Lost', value: 'Closed Lost' },
|
|
772
|
+
{ name: 'Closed Won', value: 'Closed Won' },
|
|
773
|
+
{ name: 'Id. Decision Makers', value: 'Id. Decision Makers' },
|
|
774
|
+
{ name: 'Needs Analysis', value: 'Needs Analysis' },
|
|
775
|
+
{ name: 'Perception Analysis', value: 'Perception Analysis' },
|
|
776
|
+
{ name: 'Proposal/Price Quote', value: 'Proposal/Price Quote' },
|
|
777
|
+
{ name: 'Prospecting', value: 'Prospecting' },
|
|
778
|
+
{ name: 'Qualification', value: 'Qualification' },
|
|
779
|
+
{ name: 'Value Proposition', value: 'Value Proposition' },
|
|
780
|
+
],
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
displayName: 'Additional Fields',
|
|
784
|
+
name: 'opportunityAdditionalFields',
|
|
785
|
+
type: 'collection',
|
|
786
|
+
placeholder: 'Add Field',
|
|
787
|
+
default: {},
|
|
788
|
+
displayOptions: {
|
|
789
|
+
show: { resource: ['opportunity'], operation: ['create'] },
|
|
790
|
+
},
|
|
791
|
+
options: [
|
|
792
|
+
{ displayName: 'Account ID', name: 'account_id', type: 'string', default: '' },
|
|
793
|
+
{ displayName: 'Amount', name: 'amount', type: 'number', default: 0 },
|
|
794
|
+
{ displayName: 'Assigned User ID', name: 'assigned_user_id', type: 'string', default: '' },
|
|
795
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
796
|
+
{ displayName: 'Lead Source', name: 'lead_source', type: 'string', default: '' },
|
|
797
|
+
{ displayName: 'Next Step', name: 'next_step', type: 'string', default: '' },
|
|
798
|
+
{ displayName: 'Probability', name: 'probability', type: 'number', default: 0 },
|
|
799
|
+
{ displayName: 'Type', name: 'opportunity_type', type: 'string', default: '' },
|
|
800
|
+
],
|
|
801
|
+
},
|
|
802
|
+
// OPPORTUNITY: Update fields
|
|
803
|
+
{
|
|
804
|
+
displayName: 'Update Fields',
|
|
805
|
+
name: 'opportunityUpdateFields',
|
|
806
|
+
type: 'collection',
|
|
807
|
+
placeholder: 'Add Field',
|
|
808
|
+
default: {},
|
|
809
|
+
displayOptions: {
|
|
810
|
+
show: { resource: ['opportunity'], operation: ['update'] },
|
|
811
|
+
},
|
|
812
|
+
options: [
|
|
813
|
+
{ displayName: 'Account ID', name: 'account_id', type: 'string', default: '' },
|
|
814
|
+
{ displayName: 'Amount', name: 'amount', type: 'number', default: 0 },
|
|
815
|
+
{
|
|
816
|
+
displayName: 'Close Date',
|
|
817
|
+
name: 'date_closed',
|
|
818
|
+
type: 'dateTime',
|
|
819
|
+
default: '',
|
|
820
|
+
},
|
|
821
|
+
{ displayName: 'Description', name: 'description', type: 'string', default: '' },
|
|
822
|
+
{ displayName: 'Name', name: 'name', type: 'string', default: '' },
|
|
823
|
+
{ displayName: 'Next Step', name: 'next_step', type: 'string', default: '' },
|
|
824
|
+
{ displayName: 'Probability', name: 'probability', type: 'number', default: 0 },
|
|
825
|
+
{
|
|
826
|
+
displayName: 'Sales Stage',
|
|
827
|
+
name: 'sales_stage',
|
|
828
|
+
type: 'options',
|
|
829
|
+
default: 'Prospecting',
|
|
830
|
+
options: [
|
|
831
|
+
{ name: 'Closed Lost', value: 'Closed Lost' },
|
|
832
|
+
{ name: 'Closed Won', value: 'Closed Won' },
|
|
833
|
+
{ name: 'Needs Analysis', value: 'Needs Analysis' },
|
|
834
|
+
{ name: 'Proposal/Price Quote', value: 'Proposal/Price Quote' },
|
|
835
|
+
{ name: 'Prospecting', value: 'Prospecting' },
|
|
836
|
+
{ name: 'Qualification', value: 'Qualification' },
|
|
837
|
+
],
|
|
838
|
+
},
|
|
839
|
+
],
|
|
840
|
+
},
|
|
841
|
+
// ════════════════════════════════════════════════════════════════════
|
|
842
|
+
// NOTE: Create fields
|
|
843
|
+
// ════════════════════════════════════════════════════════════════════
|
|
844
|
+
{
|
|
845
|
+
displayName: 'Note Name',
|
|
846
|
+
name: 'noteName',
|
|
847
|
+
type: 'string',
|
|
848
|
+
required: true,
|
|
849
|
+
default: '',
|
|
850
|
+
description: 'Short subject/title of the note',
|
|
851
|
+
displayOptions: {
|
|
852
|
+
show: { resource: ['note'], operation: ['createNote'] },
|
|
853
|
+
},
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
displayName: 'Note Content',
|
|
857
|
+
name: 'noteContent',
|
|
858
|
+
type: 'string',
|
|
859
|
+
typeOptions: { rows: 4 },
|
|
860
|
+
default: '',
|
|
861
|
+
displayOptions: {
|
|
862
|
+
show: { resource: ['note'], operation: ['createNote'] },
|
|
863
|
+
},
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
displayName: 'Parent Type',
|
|
867
|
+
name: 'noteParentType',
|
|
868
|
+
type: 'options',
|
|
869
|
+
default: 'Contacts',
|
|
870
|
+
description: 'Type of record to link this note to',
|
|
871
|
+
displayOptions: {
|
|
872
|
+
show: { resource: ['note'], operation: ['createNote'] },
|
|
873
|
+
},
|
|
874
|
+
options: [
|
|
875
|
+
{ name: 'Account', value: 'Accounts' },
|
|
876
|
+
{ name: 'Contact', value: 'Contacts' },
|
|
877
|
+
{ name: 'Lead', value: 'Leads' },
|
|
878
|
+
{ name: 'Opportunity', value: 'Opportunities' },
|
|
879
|
+
],
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
displayName: 'Parent ID',
|
|
883
|
+
name: 'noteParentId',
|
|
884
|
+
type: 'string',
|
|
885
|
+
default: '',
|
|
886
|
+
description: 'ID of the record to link this note to',
|
|
887
|
+
displayOptions: {
|
|
888
|
+
show: { resource: ['note'], operation: ['createNote'] },
|
|
889
|
+
},
|
|
890
|
+
},
|
|
891
|
+
// NOTE: List Activities fields
|
|
892
|
+
{
|
|
893
|
+
displayName: 'Parent Type',
|
|
894
|
+
name: 'listParentType',
|
|
895
|
+
type: 'options',
|
|
896
|
+
default: 'Contacts',
|
|
897
|
+
description: 'Type of parent record to list activities for',
|
|
898
|
+
displayOptions: {
|
|
899
|
+
show: { resource: ['note'], operation: ['listActivities'] },
|
|
900
|
+
},
|
|
901
|
+
options: [
|
|
902
|
+
{ name: 'Account', value: 'Accounts' },
|
|
903
|
+
{ name: 'Contact', value: 'Contacts' },
|
|
904
|
+
{ name: 'Lead', value: 'Leads' },
|
|
905
|
+
{ name: 'Opportunity', value: 'Opportunities' },
|
|
906
|
+
],
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
displayName: 'Parent ID',
|
|
910
|
+
name: 'listParentId',
|
|
911
|
+
type: 'string',
|
|
912
|
+
required: true,
|
|
913
|
+
default: '',
|
|
914
|
+
description: 'ID of the parent record',
|
|
915
|
+
displayOptions: {
|
|
916
|
+
show: { resource: ['note'], operation: ['listActivities'] },
|
|
917
|
+
},
|
|
918
|
+
},
|
|
919
|
+
// ════════════════════════════════════════════════════════════════════
|
|
920
|
+
// SEARCH fields (shared Contact + Account)
|
|
921
|
+
// ════════════════════════════════════════════════════════════════════
|
|
922
|
+
{
|
|
923
|
+
displayName: 'Search Field',
|
|
924
|
+
name: 'searchField',
|
|
925
|
+
type: 'string',
|
|
926
|
+
required: true,
|
|
927
|
+
default: 'email1',
|
|
928
|
+
placeholder: 'email1',
|
|
929
|
+
description: 'Field name to filter by (e.g. email1, phone_work, last_name)',
|
|
930
|
+
displayOptions: {
|
|
931
|
+
show: { operation: ['search'] },
|
|
932
|
+
},
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
displayName: 'Search Value',
|
|
936
|
+
name: 'searchValue',
|
|
937
|
+
type: 'string',
|
|
938
|
+
required: true,
|
|
939
|
+
default: '',
|
|
940
|
+
displayOptions: {
|
|
941
|
+
show: { operation: ['search'] },
|
|
942
|
+
},
|
|
943
|
+
},
|
|
944
|
+
// ════════════════════════════════════════════════════════════════════
|
|
945
|
+
// GET MANY options
|
|
946
|
+
// ════════════════════════════════════════════════════════════════════
|
|
947
|
+
{
|
|
948
|
+
displayName: 'Return All',
|
|
949
|
+
name: 'returnAll',
|
|
950
|
+
type: 'boolean',
|
|
951
|
+
default: false,
|
|
952
|
+
description: 'Whether to return all results or only up to a given limit',
|
|
953
|
+
displayOptions: {
|
|
954
|
+
show: { operation: ['getMany', 'listActivities'] },
|
|
955
|
+
},
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
displayName: 'Limit',
|
|
959
|
+
name: 'limit',
|
|
960
|
+
type: 'number',
|
|
961
|
+
typeOptions: { minValue: 1 },
|
|
962
|
+
default: 50,
|
|
963
|
+
description: 'Max number of results to return',
|
|
964
|
+
displayOptions: {
|
|
965
|
+
show: {
|
|
966
|
+
operation: ['getMany', 'listActivities'],
|
|
967
|
+
returnAll: [false],
|
|
968
|
+
},
|
|
969
|
+
},
|
|
970
|
+
},
|
|
971
|
+
],
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
975
|
+
// Execute
|
|
976
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
977
|
+
async execute() {
|
|
978
|
+
const items = this.getInputData();
|
|
979
|
+
const returnData = [];
|
|
980
|
+
const credentials = await this.getCredentials('suiteCRMApi');
|
|
981
|
+
const baseUrl = credentials.baseUrl.replace(/\/$/, '');
|
|
982
|
+
const clientId = credentials.clientId;
|
|
983
|
+
const clientSecret = credentials.clientSecret;
|
|
984
|
+
// Fetch one token per execution (cache across items)
|
|
985
|
+
const token = await getAccessToken(this, baseUrl, clientId, clientSecret);
|
|
986
|
+
for (let i = 0; i < items.length; i++) {
|
|
987
|
+
const resource = this.getNodeParameter('resource', i);
|
|
988
|
+
const operation = this.getNodeParameter('operation', i);
|
|
989
|
+
let result;
|
|
990
|
+
try {
|
|
991
|
+
// ──────────────────────────────────────────────────────────────
|
|
992
|
+
// CONTACT
|
|
993
|
+
// ──────────────────────────────────────────────────────────────
|
|
994
|
+
if (resource === 'contact') {
|
|
995
|
+
if (operation === 'create') {
|
|
996
|
+
const firstName = this.getNodeParameter('firstName', i, '');
|
|
997
|
+
const lastName = this.getNodeParameter('lastName', i);
|
|
998
|
+
const email = this.getNodeParameter('email', i, '');
|
|
999
|
+
const phone = this.getNodeParameter('phone', i, '');
|
|
1000
|
+
const accountId = this.getNodeParameter('accountId', i, '');
|
|
1001
|
+
const extra = this.getNodeParameter('contactAdditionalFields', i, {});
|
|
1002
|
+
const attributes = {
|
|
1003
|
+
first_name: firstName,
|
|
1004
|
+
last_name: lastName,
|
|
1005
|
+
...(email && { email1: email }),
|
|
1006
|
+
...(phone && { phone_work: phone }),
|
|
1007
|
+
...(accountId && { account_id: accountId }),
|
|
1008
|
+
...extra,
|
|
1009
|
+
};
|
|
1010
|
+
const body = buildJsonApiBody('Contacts', attributes);
|
|
1011
|
+
const res = await apiRequest(this, token, baseUrl, 'POST', '/modules/Contacts', body);
|
|
1012
|
+
result = extractData(res);
|
|
1013
|
+
}
|
|
1014
|
+
else if (operation === 'get') {
|
|
1015
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1016
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', `/modules/Contacts/${id}`);
|
|
1017
|
+
result = extractData(res);
|
|
1018
|
+
}
|
|
1019
|
+
else if (operation === 'getMany') {
|
|
1020
|
+
const returnAll = this.getNodeParameter('returnAll', i, false);
|
|
1021
|
+
const qs = {};
|
|
1022
|
+
if (!returnAll)
|
|
1023
|
+
qs['page[size]'] = this.getNodeParameter('limit', i, 50);
|
|
1024
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Contacts', undefined, qs);
|
|
1025
|
+
result = extractDataList(res);
|
|
1026
|
+
}
|
|
1027
|
+
else if (operation === 'update') {
|
|
1028
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1029
|
+
const updateFields = this.getNodeParameter('contactUpdateFields', i, {});
|
|
1030
|
+
const body = buildJsonApiBody('Contacts', updateFields, id);
|
|
1031
|
+
const res = await apiRequest(this, token, baseUrl, 'PATCH', `/modules/Contacts/${id}`, body);
|
|
1032
|
+
result = extractData(res);
|
|
1033
|
+
}
|
|
1034
|
+
else if (operation === 'delete') {
|
|
1035
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1036
|
+
await apiRequest(this, token, baseUrl, 'DELETE', `/modules/Contacts/${id}`);
|
|
1037
|
+
result = { success: true, id };
|
|
1038
|
+
}
|
|
1039
|
+
else if (operation === 'search') {
|
|
1040
|
+
const field = this.getNodeParameter('searchField', i);
|
|
1041
|
+
const value = this.getNodeParameter('searchValue', i);
|
|
1042
|
+
const qs = { [`filter[${field}][eq]`]: value };
|
|
1043
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Contacts', undefined, qs);
|
|
1044
|
+
result = extractDataList(res);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
// ──────────────────────────────────────────────────────────────
|
|
1048
|
+
// ACCOUNT
|
|
1049
|
+
// ──────────────────────────────────────────────────────────────
|
|
1050
|
+
else if (resource === 'account') {
|
|
1051
|
+
if (operation === 'create') {
|
|
1052
|
+
const name = this.getNodeParameter('accountName', i);
|
|
1053
|
+
const extra = this.getNodeParameter('accountAdditionalFields', i, {});
|
|
1054
|
+
const attributes = { name, ...extra };
|
|
1055
|
+
const body = buildJsonApiBody('Accounts', attributes);
|
|
1056
|
+
const res = await apiRequest(this, token, baseUrl, 'POST', '/modules/Accounts', body);
|
|
1057
|
+
result = extractData(res);
|
|
1058
|
+
}
|
|
1059
|
+
else if (operation === 'get') {
|
|
1060
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1061
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', `/modules/Accounts/${id}`);
|
|
1062
|
+
result = extractData(res);
|
|
1063
|
+
}
|
|
1064
|
+
else if (operation === 'getMany') {
|
|
1065
|
+
const returnAll = this.getNodeParameter('returnAll', i, false);
|
|
1066
|
+
const qs = {};
|
|
1067
|
+
if (!returnAll)
|
|
1068
|
+
qs['page[size]'] = this.getNodeParameter('limit', i, 50);
|
|
1069
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Accounts', undefined, qs);
|
|
1070
|
+
result = extractDataList(res);
|
|
1071
|
+
}
|
|
1072
|
+
else if (operation === 'update') {
|
|
1073
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1074
|
+
const updateFields = this.getNodeParameter('accountUpdateFields', i, {});
|
|
1075
|
+
const body = buildJsonApiBody('Accounts', updateFields, id);
|
|
1076
|
+
const res = await apiRequest(this, token, baseUrl, 'PATCH', `/modules/Accounts/${id}`, body);
|
|
1077
|
+
result = extractData(res);
|
|
1078
|
+
}
|
|
1079
|
+
else if (operation === 'delete') {
|
|
1080
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1081
|
+
await apiRequest(this, token, baseUrl, 'DELETE', `/modules/Accounts/${id}`);
|
|
1082
|
+
result = { success: true, id };
|
|
1083
|
+
}
|
|
1084
|
+
else if (operation === 'search') {
|
|
1085
|
+
const field = this.getNodeParameter('searchField', i);
|
|
1086
|
+
const value = this.getNodeParameter('searchValue', i);
|
|
1087
|
+
const qs = { [`filter[${field}][eq]`]: value };
|
|
1088
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Accounts', undefined, qs);
|
|
1089
|
+
result = extractDataList(res);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
// ──────────────────────────────────────────────────────────────
|
|
1093
|
+
// LEAD
|
|
1094
|
+
// ──────────────────────────────────────────────────────────────
|
|
1095
|
+
else if (resource === 'lead') {
|
|
1096
|
+
if (operation === 'create') {
|
|
1097
|
+
const firstName = this.getNodeParameter('leadFirstName', i, '');
|
|
1098
|
+
const lastName = this.getNodeParameter('leadLastName', i);
|
|
1099
|
+
const company = this.getNodeParameter('leadCompany', i);
|
|
1100
|
+
const email = this.getNodeParameter('leadEmail', i, '');
|
|
1101
|
+
const phone = this.getNodeParameter('leadPhone', i, '');
|
|
1102
|
+
const extra = this.getNodeParameter('leadAdditionalFields', i, {});
|
|
1103
|
+
const attributes = {
|
|
1104
|
+
first_name: firstName,
|
|
1105
|
+
last_name: lastName,
|
|
1106
|
+
account_name: company,
|
|
1107
|
+
...(email && { email1: email }),
|
|
1108
|
+
...(phone && { phone_work: phone }),
|
|
1109
|
+
...extra,
|
|
1110
|
+
};
|
|
1111
|
+
const body = buildJsonApiBody('Leads', attributes);
|
|
1112
|
+
const res = await apiRequest(this, token, baseUrl, 'POST', '/modules/Leads', body);
|
|
1113
|
+
result = extractData(res);
|
|
1114
|
+
}
|
|
1115
|
+
else if (operation === 'get') {
|
|
1116
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1117
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', `/modules/Leads/${id}`);
|
|
1118
|
+
result = extractData(res);
|
|
1119
|
+
}
|
|
1120
|
+
else if (operation === 'getMany') {
|
|
1121
|
+
const returnAll = this.getNodeParameter('returnAll', i, false);
|
|
1122
|
+
const qs = {};
|
|
1123
|
+
if (!returnAll)
|
|
1124
|
+
qs['page[size]'] = this.getNodeParameter('limit', i, 50);
|
|
1125
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Leads', undefined, qs);
|
|
1126
|
+
result = extractDataList(res);
|
|
1127
|
+
}
|
|
1128
|
+
else if (operation === 'update') {
|
|
1129
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1130
|
+
const updateFields = this.getNodeParameter('leadUpdateFields', i, {});
|
|
1131
|
+
const body = buildJsonApiBody('Leads', updateFields, id);
|
|
1132
|
+
const res = await apiRequest(this, token, baseUrl, 'PATCH', `/modules/Leads/${id}`, body);
|
|
1133
|
+
result = extractData(res);
|
|
1134
|
+
}
|
|
1135
|
+
else if (operation === 'convert') {
|
|
1136
|
+
// SuiteCRM Lead conversion: mark lead as converted and
|
|
1137
|
+
// create linked records via the Leads convert endpoint
|
|
1138
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1139
|
+
const createContact = this.getNodeParameter('convertCreateContact', i, true);
|
|
1140
|
+
const createAccount = this.getNodeParameter('convertCreateAccount', i, true);
|
|
1141
|
+
const createOpportunity = this.getNodeParameter('convertCreateOpportunity', i, false);
|
|
1142
|
+
// First, fetch the lead to get its data
|
|
1143
|
+
const leadRes = await apiRequest(this, token, baseUrl, 'GET', `/modules/Leads/${id}`);
|
|
1144
|
+
const leadData = extractData(leadRes);
|
|
1145
|
+
const conversionResults = { lead_id: id };
|
|
1146
|
+
if (createAccount) {
|
|
1147
|
+
const accountAttrs = {
|
|
1148
|
+
name: leadData.account_name || `${leadData.first_name} ${leadData.last_name}`,
|
|
1149
|
+
phone_office: leadData.phone_work,
|
|
1150
|
+
email1: leadData.email1,
|
|
1151
|
+
};
|
|
1152
|
+
const accountBody = buildJsonApiBody('Accounts', accountAttrs);
|
|
1153
|
+
const accountRes = await apiRequest(this, token, baseUrl, 'POST', '/modules/Accounts', accountBody);
|
|
1154
|
+
const account = extractData(accountRes);
|
|
1155
|
+
conversionResults.account = account;
|
|
1156
|
+
if (createContact) {
|
|
1157
|
+
const contactAttrs = {
|
|
1158
|
+
first_name: leadData.first_name,
|
|
1159
|
+
last_name: leadData.last_name,
|
|
1160
|
+
email1: leadData.email1,
|
|
1161
|
+
phone_work: leadData.phone_work,
|
|
1162
|
+
account_id: account.id,
|
|
1163
|
+
};
|
|
1164
|
+
const contactBody = buildJsonApiBody('Contacts', contactAttrs);
|
|
1165
|
+
const contactRes = await apiRequest(this, token, baseUrl, 'POST', '/modules/Contacts', contactBody);
|
|
1166
|
+
conversionResults.contact = extractData(contactRes);
|
|
1167
|
+
}
|
|
1168
|
+
if (createOpportunity) {
|
|
1169
|
+
const oppName = this.getNodeParameter('convertOpportunityName', i, '');
|
|
1170
|
+
const oppCloseDate = this.getNodeParameter('convertOpportunityCloseDate', i, '');
|
|
1171
|
+
const oppAmount = this.getNodeParameter('convertOpportunityAmount', i, 0);
|
|
1172
|
+
const oppAttrs = {
|
|
1173
|
+
name: oppName || `Opportunity - ${leadData.first_name} ${leadData.last_name}`,
|
|
1174
|
+
account_id: account.id,
|
|
1175
|
+
sales_stage: 'Prospecting',
|
|
1176
|
+
date_closed: oppCloseDate || new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
|
1177
|
+
amount: oppAmount,
|
|
1178
|
+
};
|
|
1179
|
+
const oppBody = buildJsonApiBody('Opportunities', oppAttrs);
|
|
1180
|
+
const oppRes = await apiRequest(this, token, baseUrl, 'POST', '/modules/Opportunities', oppBody);
|
|
1181
|
+
conversionResults.opportunity = extractData(oppRes);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
// Mark the lead as converted
|
|
1185
|
+
const convertBody = buildJsonApiBody('Leads', { converted: '1' }, id);
|
|
1186
|
+
await apiRequest(this, token, baseUrl, 'PATCH', `/modules/Leads/${id}`, convertBody);
|
|
1187
|
+
conversionResults.converted = true;
|
|
1188
|
+
result = conversionResults;
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
// ──────────────────────────────────────────────────────────────
|
|
1192
|
+
// OPPORTUNITY
|
|
1193
|
+
// ──────────────────────────────────────────────────────────────
|
|
1194
|
+
else if (resource === 'opportunity') {
|
|
1195
|
+
if (operation === 'create') {
|
|
1196
|
+
const name = this.getNodeParameter('opportunityName', i);
|
|
1197
|
+
const closeDate = this.getNodeParameter('closeDate', i);
|
|
1198
|
+
const salesStage = this.getNodeParameter('salesStage', i);
|
|
1199
|
+
const extra = this.getNodeParameter('opportunityAdditionalFields', i, {});
|
|
1200
|
+
const attributes = {
|
|
1201
|
+
name,
|
|
1202
|
+
date_closed: closeDate ? closeDate.split('T')[0] : closeDate,
|
|
1203
|
+
sales_stage: salesStage,
|
|
1204
|
+
...extra,
|
|
1205
|
+
};
|
|
1206
|
+
const body = buildJsonApiBody('Opportunities', attributes);
|
|
1207
|
+
const res = await apiRequest(this, token, baseUrl, 'POST', '/modules/Opportunities', body);
|
|
1208
|
+
result = extractData(res);
|
|
1209
|
+
}
|
|
1210
|
+
else if (operation === 'get') {
|
|
1211
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1212
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', `/modules/Opportunities/${id}`);
|
|
1213
|
+
result = extractData(res);
|
|
1214
|
+
}
|
|
1215
|
+
else if (operation === 'getMany') {
|
|
1216
|
+
const returnAll = this.getNodeParameter('returnAll', i, false);
|
|
1217
|
+
const qs = {};
|
|
1218
|
+
if (!returnAll)
|
|
1219
|
+
qs['page[size]'] = this.getNodeParameter('limit', i, 50);
|
|
1220
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Opportunities', undefined, qs);
|
|
1221
|
+
result = extractDataList(res);
|
|
1222
|
+
}
|
|
1223
|
+
else if (operation === 'update') {
|
|
1224
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1225
|
+
const updateFields = this.getNodeParameter('opportunityUpdateFields', i, {});
|
|
1226
|
+
const body = buildJsonApiBody('Opportunities', updateFields, id);
|
|
1227
|
+
const res = await apiRequest(this, token, baseUrl, 'PATCH', `/modules/Opportunities/${id}`, body);
|
|
1228
|
+
result = extractData(res);
|
|
1229
|
+
}
|
|
1230
|
+
else if (operation === 'delete') {
|
|
1231
|
+
const id = this.getNodeParameter('recordId', i);
|
|
1232
|
+
await apiRequest(this, token, baseUrl, 'DELETE', `/modules/Opportunities/${id}`);
|
|
1233
|
+
result = { success: true, id };
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
// ──────────────────────────────────────────────────────────────
|
|
1237
|
+
// NOTE / ACTIVITY
|
|
1238
|
+
// ──────────────────────────────────────────────────────────────
|
|
1239
|
+
else if (resource === 'note') {
|
|
1240
|
+
if (operation === 'createNote') {
|
|
1241
|
+
const name = this.getNodeParameter('noteName', i);
|
|
1242
|
+
const description = this.getNodeParameter('noteContent', i, '');
|
|
1243
|
+
const parentType = this.getNodeParameter('noteParentType', i);
|
|
1244
|
+
const parentId = this.getNodeParameter('noteParentId', i, '');
|
|
1245
|
+
const attributes = {
|
|
1246
|
+
name,
|
|
1247
|
+
description,
|
|
1248
|
+
...(parentType && { parent_type: parentType }),
|
|
1249
|
+
...(parentId && { parent_id: parentId }),
|
|
1250
|
+
};
|
|
1251
|
+
const body = buildJsonApiBody('Notes', attributes);
|
|
1252
|
+
const res = await apiRequest(this, token, baseUrl, 'POST', '/modules/Notes', body);
|
|
1253
|
+
result = extractData(res);
|
|
1254
|
+
}
|
|
1255
|
+
else if (operation === 'listActivities') {
|
|
1256
|
+
const parentType = this.getNodeParameter('listParentType', i);
|
|
1257
|
+
const parentId = this.getNodeParameter('listParentId', i);
|
|
1258
|
+
const returnAll = this.getNodeParameter('returnAll', i, false);
|
|
1259
|
+
const qs = {
|
|
1260
|
+
'filter[parent_type][eq]': parentType,
|
|
1261
|
+
'filter[parent_id][eq]': parentId,
|
|
1262
|
+
};
|
|
1263
|
+
if (!returnAll)
|
|
1264
|
+
qs['page[size]'] = this.getNodeParameter('limit', i, 50);
|
|
1265
|
+
const res = await apiRequest(this, token, baseUrl, 'GET', '/modules/Notes', undefined, qs);
|
|
1266
|
+
result = extractDataList(res);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
// Push result(s) to output
|
|
1270
|
+
if (Array.isArray(result)) {
|
|
1271
|
+
for (const item of result) {
|
|
1272
|
+
returnData.push({ json: item });
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
else if (result !== undefined) {
|
|
1276
|
+
returnData.push({ json: result });
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
catch (error) {
|
|
1280
|
+
if (this.continueOnFail()) {
|
|
1281
|
+
returnData.push({
|
|
1282
|
+
json: { error: error.message },
|
|
1283
|
+
pairedItem: { item: i },
|
|
1284
|
+
});
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
throw error;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return [returnData];
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
exports.SuiteCRM = SuiteCRM;
|
|
1294
|
+
//# sourceMappingURL=SuiteCRM.node.js.map
|