n8n-nodes-pragma-bitrix24 1.0.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/LICENSE +51 -0
- package/README.md +340 -0
- package/dist/credentials/Bitrix24Api.credentials.js +55 -0
- package/dist/nodes/Bitrix24/Bitrix24.node.js +1410 -0
- package/dist/nodes/Bitrix24/Company.js +17 -0
- package/dist/nodes/Bitrix24/Contact.js +31 -0
- package/dist/nodes/Bitrix24/Deal.js +17 -0
- package/dist/nodes/Bitrix24/Helpers.js +300 -0
- package/dist/nodes/Bitrix24/Lead.js +17 -0
- package/dist/nodes/Bitrix24/SmartProcess.js +1 -0
- package/dist/nodes/Bitrix24/bitrix24.svg +7 -0
- package/dist/nodes/Bitrix24/types.js +58 -0
- package/dist/nodes/Bitrix24AI/Bitrix24AI.node.js +205 -0
- package/dist/nodes/Bitrix24App/Bitrix24App.node.js +179 -0
- package/dist/nodes/Bitrix24Auxiliary/Bitrix24Auxiliary.node.js +566 -0
- package/dist/nodes/Bitrix24Booking/Bitrix24Booking.node.js +871 -0
- package/dist/nodes/Bitrix24Calendar/Bitrix24Calendar.node.js +471 -0
- package/dist/nodes/Bitrix24ChatBot/Bitrix24ChatBot.node.js +522 -0
- package/dist/nodes/Bitrix24Commerce/Bitrix24Commerce.node.js +431 -0
- package/dist/nodes/Bitrix24Department/Bitrix24Department.node.js +317 -0
- package/dist/nodes/Bitrix24Disk/Bitrix24Disk.node.js +334 -0
- package/dist/nodes/Bitrix24Document/Bitrix24Document.node.js +280 -0
- package/dist/nodes/Bitrix24Entity/Bitrix24Entity.node.js +263 -0
- package/dist/nodes/Bitrix24Group/Bitrix24Group.node.js +327 -0
- package/dist/nodes/Bitrix24Lists/Bitrix24Lists.node.js +406 -0
- package/dist/nodes/Bitrix24Log/Bitrix24Log.node.js +309 -0
- package/dist/nodes/Bitrix24Mail/Bitrix24Mail.node.js +109 -0
- package/dist/nodes/Bitrix24MessageService/Bitrix24MessageService.node.js +218 -0
- package/dist/nodes/Bitrix24OpenChannels/Bitrix24OpenChannels.node.js +379 -0
- package/dist/nodes/Bitrix24PaySystem/Bitrix24PaySystem.node.js +241 -0
- package/dist/nodes/Bitrix24Pipeline/Bitrix24Pipeline.node.js +553 -0
- package/dist/nodes/Bitrix24Pipeline/bitrix24.svg +7 -0
- package/dist/nodes/Bitrix24Sale/Bitrix24Sale.node.js +391 -0
- package/dist/nodes/Bitrix24Scrum/Bitrix24Scrum.node.js +555 -0
- package/dist/nodes/Bitrix24Scrum/bitrix24.svg +7 -0
- package/dist/nodes/Bitrix24Sign/Bitrix24Sign.node.js +132 -0
- package/dist/nodes/Bitrix24Social/Bitrix24Social.node.js +224 -0
- package/dist/nodes/Bitrix24Task/Bitrix24Task.node.js +444 -0
- package/dist/nodes/Bitrix24Telephony/Bitrix24Telephony.node.js +511 -0
- package/dist/nodes/Bitrix24Timeman/Bitrix24Timeman.node.js +196 -0
- package/dist/nodes/Bitrix24Tool/Bitrix24Tool.node.js +1035 -0
- package/dist/nodes/Bitrix24Tool/bitrix24.svg +7 -0
- package/dist/nodes/Bitrix24Trigger/Bitrix24Trigger.node.js +184 -0
- package/dist/nodes/Bitrix24User/Bitrix24User.node.js +351 -0
- package/dist/nodes/Bitrix24UserField/Bitrix24UserField.node.js +386 -0
- package/dist/nodes/Bitrix24UserField/bitrix24.svg +7 -0
- package/dist/nodes/shared/bitrix24.svg +7 -0
- package/dist/nodes/shared/localization.js +189 -0
- package/dist/nodes/shared/types.js +22 -0
- package/index.js +10 -0
- package/package.json +108 -0
|
@@ -0,0 +1,1035 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bitrix24 Tool — AI-реди операции для LLM
|
|
4
|
+
*
|
|
5
|
+
* Bitrix24 PRAGMA.by nodes for n8n
|
|
6
|
+
* Профессиональная интеграция с Битрикс24.
|
|
7
|
+
*
|
|
8
|
+
* @author PRAGMA & Азбука Решений
|
|
9
|
+
* @copyright 2026 PRAGMA (https://pragma.by/) & Азбука Решений (https://abc-solution.ru/)
|
|
10
|
+
*
|
|
11
|
+
* Контакты:
|
|
12
|
+
* 🇧🇾 PRAGMA: +375 (44) 702-70-90 | https://pragma.by/
|
|
13
|
+
* 🇷🇺 Азбука Решений: +7 (939) 555-19-60 | https://abc-solution.ru/
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.Bitrix24Tool = void 0;
|
|
17
|
+
const Helpers_1 = require("../Bitrix24/Helpers");
|
|
18
|
+
class Bitrix24Tool {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.description = {
|
|
21
|
+
displayName: 'Bitrix24 AI Инструмент',
|
|
22
|
+
name: 'pragmaBitrix24Tool',
|
|
23
|
+
icon: 'file:bitrix24.svg',
|
|
24
|
+
group: ['transform'],
|
|
25
|
+
version: 2,
|
|
26
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
27
|
+
description: 'AI-операции для LLM: поиск CRM, создание сущностей, бизнес-процессы, аналитика',
|
|
28
|
+
defaults: {
|
|
29
|
+
name: 'Bitrix24 AI Tool',
|
|
30
|
+
},
|
|
31
|
+
inputs: ['main'],
|
|
32
|
+
outputs: ['main'],
|
|
33
|
+
credentials: [
|
|
34
|
+
{
|
|
35
|
+
name: 'bitrix24Api',
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
properties: [
|
|
40
|
+
{
|
|
41
|
+
displayName: 'Operation',
|
|
42
|
+
name: 'operation',
|
|
43
|
+
type: 'options',
|
|
44
|
+
noDataExpression: true,
|
|
45
|
+
options: [
|
|
46
|
+
{
|
|
47
|
+
name: 'Search CRM',
|
|
48
|
+
value: 'searchCrm',
|
|
49
|
+
description: 'Search Leads, Deals, Contacts, Companies by text',
|
|
50
|
+
action: 'Search CRM entities',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Get Entity Details',
|
|
54
|
+
value: 'getEntity',
|
|
55
|
+
description: 'Get full details of a specific entity (CRM, Task, etc.)',
|
|
56
|
+
action: 'Get entity details',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'Create Entity (AI)',
|
|
60
|
+
value: 'createEntity',
|
|
61
|
+
description: 'Create Task, Deal, or Lead with simplified input',
|
|
62
|
+
action: 'Create an entity',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'Find User',
|
|
66
|
+
value: 'findUser',
|
|
67
|
+
description: 'Find a user by name or email',
|
|
68
|
+
action: 'Find user',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Call API Method',
|
|
72
|
+
value: 'callMethod',
|
|
73
|
+
description: 'Execute any Bitrix24 REST API method (Advanced)',
|
|
74
|
+
action: 'Call API method',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Check Availability (Calendar)',
|
|
78
|
+
value: 'checkAvailability',
|
|
79
|
+
description: 'Check if users are free (for scheduling)',
|
|
80
|
+
action: 'Check user availability',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'Get History (Context)',
|
|
84
|
+
value: 'getHistory',
|
|
85
|
+
description: 'Get recent activities/timeline for an entity',
|
|
86
|
+
action: 'Get entity history',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'Send Message (Notify)',
|
|
90
|
+
value: 'sendMessage',
|
|
91
|
+
description: 'Send a message or notification to a user',
|
|
92
|
+
action: 'Send message',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Start Workflow (Bizproc)',
|
|
96
|
+
value: 'startWorkflow',
|
|
97
|
+
description: 'Trigger a Business Process on an entity',
|
|
98
|
+
action: 'Start workflow',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Handle Workflow Task',
|
|
102
|
+
value: 'handleWorkflowTask',
|
|
103
|
+
description: 'Complete/Approve/Reject a Business Process task',
|
|
104
|
+
action: 'Handle workflow task',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'Forecast Deal (AI)',
|
|
108
|
+
value: 'forecastDeal',
|
|
109
|
+
description: 'Predict deal win probability',
|
|
110
|
+
action: 'Forecast deal',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'Create Segment (Marketing)',
|
|
114
|
+
value: 'createMarketingSegment',
|
|
115
|
+
description: 'Create a new CRM Marketing segment',
|
|
116
|
+
action: 'Create marketing segment',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'Create Campaign (Marketing)',
|
|
120
|
+
value: 'createMarketingCampaign',
|
|
121
|
+
description: 'Start an Email/SMS campaign',
|
|
122
|
+
action: 'Create marketing campaign',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'Get Funnel Structure (Analytics)',
|
|
126
|
+
value: 'getFunnelStructure',
|
|
127
|
+
description: 'Get Sales Funnels and Stages for analysis',
|
|
128
|
+
action: 'Get funnel structure',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'Register Ad Source (Tracking)',
|
|
132
|
+
value: 'registerAdSource',
|
|
133
|
+
description: 'Register a new traffic source',
|
|
134
|
+
action: 'Register ad source',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'Find Duplicates',
|
|
138
|
+
value: 'findDuplicates',
|
|
139
|
+
description: 'Check for duplicate entities',
|
|
140
|
+
action: 'Find duplicates',
|
|
141
|
+
},
|
|
142
|
+
// System Operations
|
|
143
|
+
{
|
|
144
|
+
name: 'Get Scope',
|
|
145
|
+
value: 'getScope',
|
|
146
|
+
action: 'Check auth scope',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'Get Features',
|
|
150
|
+
value: 'getFeatures',
|
|
151
|
+
action: 'Check enabled features',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'List Offline Events',
|
|
155
|
+
value: 'listOffline',
|
|
156
|
+
action: 'List offline events',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'Add CRM Status',
|
|
160
|
+
value: 'addCrmStatus',
|
|
161
|
+
description: 'Add comment to a task',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'Find Duplicates',
|
|
165
|
+
value: 'findDuplicates',
|
|
166
|
+
description: 'Check for duplicate entities',
|
|
167
|
+
action: 'Find duplicates',
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
default: 'searchCrm',
|
|
171
|
+
},
|
|
172
|
+
// ----------------------------------
|
|
173
|
+
// Operation: Search CRM
|
|
174
|
+
// ----------------------------------
|
|
175
|
+
{
|
|
176
|
+
displayName: 'Entity Type',
|
|
177
|
+
name: 'entityType',
|
|
178
|
+
type: 'options',
|
|
179
|
+
displayOptions: {
|
|
180
|
+
show: {
|
|
181
|
+
operation: ['searchCrm'],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
options: [
|
|
185
|
+
{ name: 'All CRM', value: 'all' },
|
|
186
|
+
{ name: 'Lead', value: 'lead' },
|
|
187
|
+
{ name: 'Deal', value: 'deal' },
|
|
188
|
+
{ name: 'Contact', value: 'contact' },
|
|
189
|
+
{ name: 'Company', value: 'company' },
|
|
190
|
+
],
|
|
191
|
+
default: 'all',
|
|
192
|
+
description: 'Type of entity to search for',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
displayName: 'Query',
|
|
196
|
+
name: 'query',
|
|
197
|
+
type: 'string',
|
|
198
|
+
displayOptions: {
|
|
199
|
+
show: {
|
|
200
|
+
operation: ['searchCrm'],
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
default: '',
|
|
204
|
+
description: 'Search string (name, email, phone, title)',
|
|
205
|
+
},
|
|
206
|
+
// ----------------------------------
|
|
207
|
+
// Operation: Get Entity
|
|
208
|
+
// ----------------------------------
|
|
209
|
+
{
|
|
210
|
+
displayName: 'Entity Type',
|
|
211
|
+
name: 'entityTypeGet',
|
|
212
|
+
type: 'options',
|
|
213
|
+
displayOptions: {
|
|
214
|
+
show: {
|
|
215
|
+
operation: ['getEntity'],
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
options: [
|
|
219
|
+
{ name: 'Lead', value: 'crm.lead' },
|
|
220
|
+
{ name: 'Deal', value: 'crm.deal' },
|
|
221
|
+
{ name: 'Contact', value: 'crm.contact' },
|
|
222
|
+
{ name: 'Company', value: 'crm.company' },
|
|
223
|
+
{ name: 'Task', value: 'tasks.task' },
|
|
224
|
+
{ name: 'User', value: 'user' },
|
|
225
|
+
],
|
|
226
|
+
default: 'crm.deal',
|
|
227
|
+
description: 'Type of entity to retrieve',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
displayName: 'ID',
|
|
231
|
+
name: 'id',
|
|
232
|
+
type: 'string',
|
|
233
|
+
displayOptions: {
|
|
234
|
+
show: {
|
|
235
|
+
operation: ['getEntity'],
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
default: '',
|
|
239
|
+
description: 'ID of the entity',
|
|
240
|
+
},
|
|
241
|
+
// ----------------------------------
|
|
242
|
+
// Operation: Create Entity (AI)
|
|
243
|
+
// ----------------------------------
|
|
244
|
+
{
|
|
245
|
+
displayName: 'Entity Type',
|
|
246
|
+
name: 'createEntityType',
|
|
247
|
+
type: 'options',
|
|
248
|
+
displayOptions: {
|
|
249
|
+
show: {
|
|
250
|
+
operation: ['createEntity'],
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
options: [
|
|
254
|
+
{ name: 'Task', value: 'tasks.task' },
|
|
255
|
+
{ name: 'Lead', value: 'crm.lead' },
|
|
256
|
+
{ name: 'Deal', value: 'crm.deal' },
|
|
257
|
+
],
|
|
258
|
+
default: 'tasks.task',
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
displayName: 'Title',
|
|
262
|
+
name: 'title',
|
|
263
|
+
type: 'string',
|
|
264
|
+
displayOptions: {
|
|
265
|
+
show: {
|
|
266
|
+
operation: ['createEntity'],
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
default: '',
|
|
270
|
+
description: 'Title of the entity',
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
displayName: 'Description',
|
|
274
|
+
name: 'description',
|
|
275
|
+
type: 'string',
|
|
276
|
+
displayOptions: {
|
|
277
|
+
show: {
|
|
278
|
+
operation: ['createEntity'],
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
default: '',
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
displayName: 'Responsible User ID',
|
|
285
|
+
name: 'responsibleId',
|
|
286
|
+
type: 'string',
|
|
287
|
+
displayOptions: {
|
|
288
|
+
show: {
|
|
289
|
+
operation: ['createEntity'],
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
default: '',
|
|
293
|
+
description: 'ID of the user responsible',
|
|
294
|
+
},
|
|
295
|
+
// ----------------------------------
|
|
296
|
+
// Operation: Find User
|
|
297
|
+
// ----------------------------------
|
|
298
|
+
{
|
|
299
|
+
displayName: 'Search String',
|
|
300
|
+
name: 'userQuery',
|
|
301
|
+
type: 'string',
|
|
302
|
+
displayOptions: {
|
|
303
|
+
show: {
|
|
304
|
+
operation: ['findUser'],
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
default: '',
|
|
308
|
+
description: 'Name or email to search for',
|
|
309
|
+
},
|
|
310
|
+
// ----------------------------------
|
|
311
|
+
// Operation: Check Availability
|
|
312
|
+
// ----------------------------------
|
|
313
|
+
{
|
|
314
|
+
displayName: 'User IDs',
|
|
315
|
+
name: 'users',
|
|
316
|
+
type: 'string',
|
|
317
|
+
displayOptions: {
|
|
318
|
+
show: {
|
|
319
|
+
operation: ['checkAvailability'],
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
default: '',
|
|
323
|
+
description: 'Comma-separated user IDs to check',
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
displayName: 'From (Date)',
|
|
327
|
+
name: 'dateFrom',
|
|
328
|
+
type: 'dateTime',
|
|
329
|
+
displayOptions: {
|
|
330
|
+
show: {
|
|
331
|
+
operation: ['checkAvailability'],
|
|
332
|
+
},
|
|
333
|
+
},
|
|
334
|
+
default: '',
|
|
335
|
+
description: 'Start of check period',
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
displayName: 'To (Date)',
|
|
339
|
+
name: 'dateTo',
|
|
340
|
+
type: 'dateTime',
|
|
341
|
+
displayOptions: {
|
|
342
|
+
show: {
|
|
343
|
+
operation: ['checkAvailability'],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
default: '',
|
|
347
|
+
description: 'End of check period',
|
|
348
|
+
},
|
|
349
|
+
// ----------------------------------
|
|
350
|
+
// Operation: Get History
|
|
351
|
+
// ----------------------------------
|
|
352
|
+
{
|
|
353
|
+
displayName: 'Entity Type',
|
|
354
|
+
name: 'historyEntityType',
|
|
355
|
+
type: 'options',
|
|
356
|
+
displayOptions: {
|
|
357
|
+
show: {
|
|
358
|
+
operation: ['getHistory'],
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
options: [
|
|
362
|
+
{ name: 'Lead', value: '1' },
|
|
363
|
+
{ name: 'Deal', value: '2' },
|
|
364
|
+
{ name: 'Contact', value: '3' },
|
|
365
|
+
{ name: 'Company', value: '4' },
|
|
366
|
+
],
|
|
367
|
+
default: '2',
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
displayName: 'Entity ID',
|
|
371
|
+
name: 'historyEntityId',
|
|
372
|
+
type: 'string',
|
|
373
|
+
displayOptions: {
|
|
374
|
+
show: {
|
|
375
|
+
operation: ['getHistory'],
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
default: '',
|
|
379
|
+
},
|
|
380
|
+
// ----------------------------------
|
|
381
|
+
// Operation: Send Message
|
|
382
|
+
// ----------------------------------
|
|
383
|
+
{
|
|
384
|
+
displayName: 'Recipient ID',
|
|
385
|
+
name: 'messageUserId',
|
|
386
|
+
type: 'string',
|
|
387
|
+
displayOptions: {
|
|
388
|
+
show: {
|
|
389
|
+
operation: ['sendMessage'],
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
default: '',
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
displayName: 'Message',
|
|
396
|
+
name: 'messageBody',
|
|
397
|
+
type: 'string',
|
|
398
|
+
displayOptions: {
|
|
399
|
+
show: {
|
|
400
|
+
operation: ['sendMessage'],
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
default: '',
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
displayName: 'Type',
|
|
407
|
+
name: 'messageType',
|
|
408
|
+
type: 'options',
|
|
409
|
+
options: [
|
|
410
|
+
{ name: 'System Notification', value: 'notify' },
|
|
411
|
+
{ name: 'Chat Message', value: 'chat' },
|
|
412
|
+
],
|
|
413
|
+
displayOptions: {
|
|
414
|
+
show: {
|
|
415
|
+
operation: ['sendMessage'],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
default: 'chat',
|
|
419
|
+
},
|
|
420
|
+
// ----------------------------------
|
|
421
|
+
// Operation: Start Workflow
|
|
422
|
+
// ----------------------------------
|
|
423
|
+
{
|
|
424
|
+
displayName: 'Template ID',
|
|
425
|
+
name: 'bizprocTemplateId',
|
|
426
|
+
type: 'string',
|
|
427
|
+
displayOptions: {
|
|
428
|
+
show: {
|
|
429
|
+
operation: ['startWorkflow'],
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
default: '',
|
|
433
|
+
description: 'ID of the Workflow Template (Bizproc)',
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
displayName: 'Document ID (Entity)',
|
|
437
|
+
name: 'bizprocDocumentId',
|
|
438
|
+
type: 'string',
|
|
439
|
+
displayOptions: {
|
|
440
|
+
show: {
|
|
441
|
+
operation: ['startWorkflow'],
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
default: '',
|
|
445
|
+
description: 'ID of the entity (e.g. "DEAL_123" or just "123" if type selected implies it)',
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
displayName: 'Document Type',
|
|
449
|
+
name: 'bizprocDocumentType',
|
|
450
|
+
type: 'options',
|
|
451
|
+
options: [
|
|
452
|
+
{ name: 'Lead', value: 'crm_lead' },
|
|
453
|
+
{ name: 'Deal', value: 'crm_deal' },
|
|
454
|
+
{ name: 'Contact', value: 'crm_contact' },
|
|
455
|
+
{ name: 'Company', value: 'crm_company' },
|
|
456
|
+
{ name: 'Task', value: 'tasks' }, // Complex in B24, usually tasks have separate runner
|
|
457
|
+
],
|
|
458
|
+
displayOptions: {
|
|
459
|
+
show: {
|
|
460
|
+
operation: ['startWorkflow'],
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
default: 'crm_deal',
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
displayName: 'Parameters (JSON)',
|
|
467
|
+
name: 'bizprocParams',
|
|
468
|
+
type: 'json',
|
|
469
|
+
displayOptions: {
|
|
470
|
+
show: {
|
|
471
|
+
operation: ['startWorkflow'],
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
default: '{}',
|
|
475
|
+
description: 'Input parameters for the workflow',
|
|
476
|
+
},
|
|
477
|
+
// ----------------------------------
|
|
478
|
+
// Operation: Handle Workflow Task
|
|
479
|
+
// ----------------------------------
|
|
480
|
+
{
|
|
481
|
+
displayName: 'Task ID',
|
|
482
|
+
name: 'bizprocTaskId',
|
|
483
|
+
type: 'string',
|
|
484
|
+
displayOptions: {
|
|
485
|
+
show: {
|
|
486
|
+
operation: ['handleWorkflowTask'],
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
default: '',
|
|
490
|
+
description: 'ID of the extensive task (not regular task)',
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
displayName: 'Status',
|
|
494
|
+
name: 'bizprocStatus',
|
|
495
|
+
type: 'options',
|
|
496
|
+
options: [
|
|
497
|
+
{ name: 'Approve (1)', value: '1' },
|
|
498
|
+
{ name: 'Reject (2)', value: '2' },
|
|
499
|
+
{ name: 'Ok (3)', value: '3' },
|
|
500
|
+
{ name: 'Custom (4)', value: '4' },
|
|
501
|
+
],
|
|
502
|
+
displayOptions: {
|
|
503
|
+
show: {
|
|
504
|
+
operation: ['handleWorkflowTask'],
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
default: '1',
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
displayName: 'Comment',
|
|
511
|
+
name: 'bizprocComment',
|
|
512
|
+
type: 'string',
|
|
513
|
+
displayOptions: {
|
|
514
|
+
show: {
|
|
515
|
+
operation: ['handleWorkflowTask'],
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
default: '',
|
|
519
|
+
},
|
|
520
|
+
// ----------------------------------
|
|
521
|
+
// Operation: Forecast Deal
|
|
522
|
+
// ----------------------------------
|
|
523
|
+
{
|
|
524
|
+
displayName: 'Deal ID',
|
|
525
|
+
name: 'forecastDealId',
|
|
526
|
+
type: 'string',
|
|
527
|
+
displayOptions: {
|
|
528
|
+
show: {
|
|
529
|
+
operation: ['forecastDeal'],
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
default: '',
|
|
533
|
+
},
|
|
534
|
+
// ----------------------------------
|
|
535
|
+
// Operation: Marketing (Segment & Campaign)
|
|
536
|
+
// ----------------------------------
|
|
537
|
+
{
|
|
538
|
+
displayName: 'Name',
|
|
539
|
+
name: 'marketingName',
|
|
540
|
+
type: 'string',
|
|
541
|
+
displayOptions: {
|
|
542
|
+
show: {
|
|
543
|
+
operation: ['createMarketingSegment', 'createMarketingCampaign'],
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
default: '',
|
|
547
|
+
description: 'Name of the segment or campaign',
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
displayName: 'Type',
|
|
551
|
+
name: 'campaignType',
|
|
552
|
+
type: 'options',
|
|
553
|
+
options: [
|
|
554
|
+
{ name: 'Email', value: 'email' },
|
|
555
|
+
{ name: 'SMS', value: 'sms' },
|
|
556
|
+
{ name: 'Voice Broadcasting', value: 'voice' },
|
|
557
|
+
],
|
|
558
|
+
displayOptions: {
|
|
559
|
+
show: {
|
|
560
|
+
operation: ['createMarketingCampaign'],
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
default: 'email',
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
displayName: 'Segment ID',
|
|
567
|
+
name: 'campaignSegmentId',
|
|
568
|
+
type: 'string',
|
|
569
|
+
displayOptions: {
|
|
570
|
+
show: {
|
|
571
|
+
operation: ['createMarketingCampaign'],
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
default: '',
|
|
575
|
+
description: 'ID of the segment to target',
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
displayName: 'Message Body',
|
|
579
|
+
name: 'campaignBody',
|
|
580
|
+
type: 'string',
|
|
581
|
+
displayOptions: {
|
|
582
|
+
show: {
|
|
583
|
+
operation: ['createMarketingCampaign'],
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
default: '',
|
|
587
|
+
},
|
|
588
|
+
// ----------------------------------
|
|
589
|
+
// Operation: Call Method
|
|
590
|
+
// ----------------------------------
|
|
591
|
+
{
|
|
592
|
+
displayName: 'Method',
|
|
593
|
+
name: 'method',
|
|
594
|
+
type: 'string',
|
|
595
|
+
displayOptions: {
|
|
596
|
+
show: {
|
|
597
|
+
operation: ['callMethod'],
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
default: 'server.time',
|
|
601
|
+
description: 'Bitrix24 REST method (e.g. crm.deal.list)',
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
displayName: 'Parameters (JSON)',
|
|
605
|
+
name: 'paramsJson',
|
|
606
|
+
type: 'json',
|
|
607
|
+
displayOptions: {
|
|
608
|
+
show: {
|
|
609
|
+
operation: ['callMethod'],
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
default: '{}',
|
|
613
|
+
description: 'Parameters for the method',
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
async execute() {
|
|
619
|
+
const items = this.getInputData();
|
|
620
|
+
const returnData = [];
|
|
621
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
622
|
+
for (let i = 0; i < items.length; i++) {
|
|
623
|
+
try {
|
|
624
|
+
if (operation === 'searchCrm') {
|
|
625
|
+
const entityType = this.getNodeParameter('entityType', i);
|
|
626
|
+
const query = this.getNodeParameter('query', i);
|
|
627
|
+
const types = entityType === 'all' ? ['lead', 'deal', 'contact', 'company'] : [entityType];
|
|
628
|
+
const results = [];
|
|
629
|
+
for (const type of types) {
|
|
630
|
+
// crm.X.list with fuzzy search logic
|
|
631
|
+
// Bitrix search is weird. %QUERY% works for strings.
|
|
632
|
+
const filter = { 'LOGIC': 'OR' };
|
|
633
|
+
// Add fields based on common patterns
|
|
634
|
+
filter['%TITLE'] = query;
|
|
635
|
+
if (type === 'contact' || type === 'lead') {
|
|
636
|
+
filter['%NAME'] = query;
|
|
637
|
+
filter['%LAST_NAME'] = query;
|
|
638
|
+
// Phones/Emails are complex to wildcard search in some B24 versions, usually requires exact.
|
|
639
|
+
// But we try.
|
|
640
|
+
filter['%EMAIL'] = query; // might not work directly but worth trying
|
|
641
|
+
filter['PHONE'] = query; // Phone usually exact
|
|
642
|
+
}
|
|
643
|
+
try {
|
|
644
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', `crm.${type}.list`, {
|
|
645
|
+
select: ['ID', 'TITLE', 'NAME', 'LAST_NAME', 'PHONE', 'EMAIL'],
|
|
646
|
+
filter
|
|
647
|
+
});
|
|
648
|
+
const list = response.result || [];
|
|
649
|
+
list.forEach(item => results.push({ ...item, _type: type }));
|
|
650
|
+
}
|
|
651
|
+
catch (e) {
|
|
652
|
+
// Ignore sub-search errors
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
returnData.push({
|
|
656
|
+
json: {
|
|
657
|
+
tool_call_result: results.slice(0, 20), // Limit context
|
|
658
|
+
summary: `Found ${results.length} results for "${query}"`
|
|
659
|
+
},
|
|
660
|
+
pairedItem: { item: i }
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
if (operation === 'createEntity') {
|
|
664
|
+
const entityType = this.getNodeParameter('createEntityType', i);
|
|
665
|
+
const title = this.getNodeParameter('title', i);
|
|
666
|
+
const description = this.getNodeParameter('description', i);
|
|
667
|
+
const responsibleId = this.getNodeParameter('responsibleId', i);
|
|
668
|
+
let method = `${entityType}.add`;
|
|
669
|
+
let params = {};
|
|
670
|
+
if (entityType === 'tasks.task') {
|
|
671
|
+
params = { fields: { TITLE: title, DESCRIPTION: description } };
|
|
672
|
+
if (responsibleId)
|
|
673
|
+
params.fields.RESPONSIBLE_ID = responsibleId;
|
|
674
|
+
}
|
|
675
|
+
else if (entityType === 'crm.lead' || entityType === 'crm.deal') {
|
|
676
|
+
params = { fields: { TITLE: title, COMMENTS: description } };
|
|
677
|
+
if (responsibleId)
|
|
678
|
+
params.fields.ASSIGNED_BY_ID = responsibleId;
|
|
679
|
+
}
|
|
680
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', method, params);
|
|
681
|
+
returnData.push({
|
|
682
|
+
json: {
|
|
683
|
+
tool_call_result: { id: response.result, success: true },
|
|
684
|
+
summary: `Created ${entityType} with ID ${response.result}`
|
|
685
|
+
},
|
|
686
|
+
pairedItem: { item: i }
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
if (operation === 'getEntity') {
|
|
690
|
+
const entityType = this.getNodeParameter('entityTypeGet', i);
|
|
691
|
+
const id = this.getNodeParameter('id', i);
|
|
692
|
+
let start = 0;
|
|
693
|
+
// Handle slight API diffs
|
|
694
|
+
let method = `${entityType}.get`;
|
|
695
|
+
let params = { id };
|
|
696
|
+
if (entityType === 'tasks.task') {
|
|
697
|
+
params = { taskId: id, select: ['*', 'UF_*'] };
|
|
698
|
+
}
|
|
699
|
+
else if (entityType === 'user') {
|
|
700
|
+
params = { ID: id };
|
|
701
|
+
}
|
|
702
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', method, params);
|
|
703
|
+
// Optimize output - remove nulls?
|
|
704
|
+
const data = response.result;
|
|
705
|
+
// Maybe flatten or clean up data for LLM?
|
|
706
|
+
// For now, raw is fine but maybe strict selection later.
|
|
707
|
+
returnData.push({
|
|
708
|
+
json: {
|
|
709
|
+
tool_call_result: data
|
|
710
|
+
},
|
|
711
|
+
pairedItem: { item: i }
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
if (operation === 'findUser') {
|
|
715
|
+
const query = this.getNodeParameter('userQuery', i);
|
|
716
|
+
// user.search method exists? user.get with filter.
|
|
717
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'user.get', {
|
|
718
|
+
FILTER: {
|
|
719
|
+
'LOGIC': 'OR',
|
|
720
|
+
'%NAME': query,
|
|
721
|
+
'%LAST_NAME': query,
|
|
722
|
+
'%EMAIL': query,
|
|
723
|
+
'%WORK_POSITION': query
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
const users = response.result || [];
|
|
727
|
+
const simplified = users.map(u => ({
|
|
728
|
+
id: u.ID,
|
|
729
|
+
name: `${u.NAME} ${u.LAST_NAME}`,
|
|
730
|
+
email: u.EMAIL,
|
|
731
|
+
position: u.WORK_POSITION,
|
|
732
|
+
active: u.ACTIVE
|
|
733
|
+
}));
|
|
734
|
+
returnData.push({ json: { tool_call_result: simplified }, pairedItem: { item: i } });
|
|
735
|
+
}
|
|
736
|
+
if (operation === 'callMethod') {
|
|
737
|
+
const method = this.getNodeParameter('method', i);
|
|
738
|
+
const paramsJson = this.getNodeParameter('paramsJson', i, '{}');
|
|
739
|
+
const params = JSON.parse(paramsJson);
|
|
740
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', method, params);
|
|
741
|
+
returnData.push({ json: { tool_call_result: response.result }, pairedItem: { item: i } });
|
|
742
|
+
}
|
|
743
|
+
if (operation === 'checkAvailability') {
|
|
744
|
+
const usersStr = this.getNodeParameter('users', i);
|
|
745
|
+
const users = usersStr.split(',').map(s => s.trim());
|
|
746
|
+
const from = this.getNodeParameter('dateFrom', i);
|
|
747
|
+
const to = this.getNodeParameter('dateTo', i);
|
|
748
|
+
// calendar.accessibility.get
|
|
749
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'calendar.accessibility.get', {
|
|
750
|
+
from: from, // Yyyy-mm-dd format usually needed or ISO?
|
|
751
|
+
to: to,
|
|
752
|
+
users: users
|
|
753
|
+
});
|
|
754
|
+
// Return raw for AI to parse.
|
|
755
|
+
returnData.push({ json: { tool_call_result: response.result }, pairedItem: { item: i } });
|
|
756
|
+
}
|
|
757
|
+
if (operation === 'getHistory') {
|
|
758
|
+
const ownerTypeId = this.getNodeParameter('historyEntityType', i);
|
|
759
|
+
const ownerId = this.getNodeParameter('historyEntityId', i);
|
|
760
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.activity.list', {
|
|
761
|
+
filter: {
|
|
762
|
+
OWNER_TYPE_ID: ownerTypeId,
|
|
763
|
+
OWNER_ID: ownerId,
|
|
764
|
+
},
|
|
765
|
+
select: ['ID', 'SUBJECT', 'DESCRIPTION', 'CREATED', 'COMPLETED', 'AUTHOR_ID', 'DIRECTION'],
|
|
766
|
+
order: { CREATED: 'DESC' }
|
|
767
|
+
});
|
|
768
|
+
// AI needs concise history
|
|
769
|
+
const activities = response.result || [];
|
|
770
|
+
const summary = activities.slice(0, 10).map(a => `[${a.CREATED}] ${a.SUBJECT} (${a.DIRECTION === '1' ? 'Incoming' : 'Outgoing'}) - ${a.DESCRIPTION}`).join('\n');
|
|
771
|
+
returnData.push({
|
|
772
|
+
json: {
|
|
773
|
+
tool_call_result: activities.slice(0, 10),
|
|
774
|
+
summary: summary
|
|
775
|
+
},
|
|
776
|
+
pairedItem: { item: i }
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
if (operation === 'sendMessage') {
|
|
780
|
+
const userId = this.getNodeParameter('messageUserId', i);
|
|
781
|
+
const message = this.getNodeParameter('messageBody', i);
|
|
782
|
+
const type = this.getNodeParameter('messageType', i);
|
|
783
|
+
if (type === 'notify') {
|
|
784
|
+
await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'im.notify.system.add', {
|
|
785
|
+
TO_USER_ID: userId,
|
|
786
|
+
MESSAGE: message
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'im.message.add', {
|
|
791
|
+
DIALOG_ID: userId,
|
|
792
|
+
MESSAGE: message
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
returnData.push({ json: { tool_call_result: { success: true } }, pairedItem: { item: i } });
|
|
796
|
+
}
|
|
797
|
+
if (operation === 'startWorkflow') {
|
|
798
|
+
const templateId = this.getNodeParameter('bizprocTemplateId', i);
|
|
799
|
+
const docId = this.getNodeParameter('bizprocDocumentId', i);
|
|
800
|
+
const docType = this.getNodeParameter('bizprocDocumentType', i);
|
|
801
|
+
const params = this.getNodeParameter('bizprocParams', i, '{}');
|
|
802
|
+
// Construct complex document ID for B24
|
|
803
|
+
// LEAD: ['crm', 'CCrmDocumentLead', 'LEAD_ID']
|
|
804
|
+
let complexDocId = [];
|
|
805
|
+
if (docType === 'crm_lead')
|
|
806
|
+
complexDocId = ['crm', 'CCrmDocumentLead', 'LEAD_' + docId];
|
|
807
|
+
if (docType === 'crm_deal')
|
|
808
|
+
complexDocId = ['crm', 'CCrmDocumentDeal', 'DEAL_' + docId];
|
|
809
|
+
if (docType === 'crm_contact')
|
|
810
|
+
complexDocId = ['crm', 'CCrmDocumentContact', 'CONTACT_' + docId];
|
|
811
|
+
if (docType === 'crm_company')
|
|
812
|
+
complexDocId = ['crm', 'CCrmDocumentCompany', 'COMPANY_' + docId];
|
|
813
|
+
// bizproc.workflow.start
|
|
814
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'bizproc.workflow.start', {
|
|
815
|
+
TEMPLATE_ID: templateId,
|
|
816
|
+
DOCUMENT_ID: complexDocId,
|
|
817
|
+
PARAMETERS: JSON.parse(params) // Values for BP
|
|
818
|
+
});
|
|
819
|
+
returnData.push({
|
|
820
|
+
json: {
|
|
821
|
+
tool_call_result: {
|
|
822
|
+
workflowId: response.result,
|
|
823
|
+
success: true
|
|
824
|
+
},
|
|
825
|
+
summary: `Started Workflow ${templateId} on ${docType} ${docId}`
|
|
826
|
+
},
|
|
827
|
+
pairedItem: { item: i }
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
if (operation === 'handleWorkflowTask') {
|
|
831
|
+
const taskId = this.getNodeParameter('bizprocTaskId', i);
|
|
832
|
+
const status = this.getNodeParameter('bizprocStatus', i);
|
|
833
|
+
const comment = this.getNodeParameter('bizprocComment', i);
|
|
834
|
+
// bizproc.task.complete
|
|
835
|
+
await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'bizproc.task.complete', {
|
|
836
|
+
TASK_ID: taskId,
|
|
837
|
+
STATUS: status,
|
|
838
|
+
COMMENT: comment
|
|
839
|
+
});
|
|
840
|
+
returnData.push({
|
|
841
|
+
json: {
|
|
842
|
+
tool_call_result: { success: true },
|
|
843
|
+
summary: `Completed workflow task ${taskId} with status ${status}`
|
|
844
|
+
},
|
|
845
|
+
pairedItem: { item: i }
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
if (operation === 'forecastDeal') {
|
|
849
|
+
const dealId = this.getNodeParameter('forecastDealId', i);
|
|
850
|
+
// Get deal history and current state
|
|
851
|
+
const deal = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.deal.get', { id: dealId });
|
|
852
|
+
const dealResult = deal.result;
|
|
853
|
+
// Just a mock "AI" logic here for V19
|
|
854
|
+
// Real implementation would check stage history duration
|
|
855
|
+
const amount = parseFloat(dealResult?.OPPORTUNITY || '0');
|
|
856
|
+
let probability = 'Medium';
|
|
857
|
+
let reason = 'Standard deal flow.';
|
|
858
|
+
const stageId = dealResult?.STAGE_ID || '';
|
|
859
|
+
if (stageId.includes('WON')) {
|
|
860
|
+
probability = 'Won';
|
|
861
|
+
reason = 'Deal is already won.';
|
|
862
|
+
}
|
|
863
|
+
else if (amount > 10000) {
|
|
864
|
+
probability = 'High';
|
|
865
|
+
reason = 'High value deal, usually prioritized.';
|
|
866
|
+
}
|
|
867
|
+
else if (!dealResult?.ASSIGNED_BY_ID) {
|
|
868
|
+
probability = 'Low';
|
|
869
|
+
reason = 'No assigned manager.';
|
|
870
|
+
}
|
|
871
|
+
returnData.push({
|
|
872
|
+
json: {
|
|
873
|
+
tool_call_result: {
|
|
874
|
+
dealId,
|
|
875
|
+
probability,
|
|
876
|
+
reason,
|
|
877
|
+
amount,
|
|
878
|
+
currency: dealResult?.CURRENCY_ID
|
|
879
|
+
},
|
|
880
|
+
summary: `Deal Forecast: ${probability} (Reason: ${reason})`
|
|
881
|
+
},
|
|
882
|
+
pairedItem: { item: i }
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
if (operation === 'createMarketingSegment') {
|
|
886
|
+
const name = this.getNodeParameter('marketingName', i);
|
|
887
|
+
// Basic segment creation
|
|
888
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.marketing.segment.add', {
|
|
889
|
+
fields: {
|
|
890
|
+
NAME: name,
|
|
891
|
+
active: 'Y'
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
returnData.push({
|
|
895
|
+
json: {
|
|
896
|
+
tool_call_result: {
|
|
897
|
+
segmentId: response.result,
|
|
898
|
+
name
|
|
899
|
+
},
|
|
900
|
+
summary: `Created Marketing Segment "${name}" (ID: ${response.result})`
|
|
901
|
+
},
|
|
902
|
+
pairedItem: { item: i }
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
if (operation === 'createMarketingCampaign') {
|
|
906
|
+
const name = this.getNodeParameter('marketingName', i);
|
|
907
|
+
const type = this.getNodeParameter('campaignType', i);
|
|
908
|
+
const segmentId = this.getNodeParameter('campaignSegmentId', i);
|
|
909
|
+
const body = this.getNodeParameter('campaignBody', i);
|
|
910
|
+
// crm.marketing.campaign.add (Complex API, usually requires layout)
|
|
911
|
+
// Simplified for AI: just create draft
|
|
912
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.marketing.campaign.add', {
|
|
913
|
+
fields: {
|
|
914
|
+
NAME: name,
|
|
915
|
+
CODE: 'n8n_auto_' + Date.now(),
|
|
916
|
+
ACTIVE: 'Y',
|
|
917
|
+
TYPE_ID: type.toUpperCase(),
|
|
918
|
+
SEGMENT_ID: segmentId,
|
|
919
|
+
BODY: body // HTML/Text body
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
returnData.push({
|
|
923
|
+
json: {
|
|
924
|
+
tool_call_result: {
|
|
925
|
+
campaignId: response.result,
|
|
926
|
+
status: 'DRAFT'
|
|
927
|
+
},
|
|
928
|
+
summary: `Created ${type} Campaign "${name}" (Draft)`
|
|
929
|
+
},
|
|
930
|
+
pairedItem: { item: i }
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
if (operation === 'getFunnelStructure') {
|
|
934
|
+
// 1. Get Categories (Funnels)
|
|
935
|
+
const categories = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.dealcategory.list', {});
|
|
936
|
+
const funnels = categories.result || [];
|
|
937
|
+
// 2. Get Stages for default funnel (ID 0)
|
|
938
|
+
const defaultStages = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.dealcategory.stage.list', { id: 0 });
|
|
939
|
+
// 3. Construct structure
|
|
940
|
+
const result = [
|
|
941
|
+
{
|
|
942
|
+
ID: '0',
|
|
943
|
+
NAME: 'General',
|
|
944
|
+
STAGES: defaultStages.result
|
|
945
|
+
}
|
|
946
|
+
];
|
|
947
|
+
// For other funnels, fetch stages?
|
|
948
|
+
// crm.dealcategory.stage.list with id=CATEGORY_ID
|
|
949
|
+
for (const f of funnels) {
|
|
950
|
+
if (f.ID === '0')
|
|
951
|
+
continue; // Skip default if present
|
|
952
|
+
const stages = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.dealcategory.stage.list', { id: f.ID });
|
|
953
|
+
result.push({
|
|
954
|
+
ID: f.ID,
|
|
955
|
+
NAME: f.NAME,
|
|
956
|
+
STAGES: stages.result
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
returnData.push({ json: { funnels: result }, pairedItem: { item: i } });
|
|
960
|
+
}
|
|
961
|
+
if (operation === 'registerAdSource') {
|
|
962
|
+
const name = this.getNodeParameter('marketingName', i); // Reuse marketingName
|
|
963
|
+
const code = 'n8n_' + Date.now();
|
|
964
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.tracking.source.add', {
|
|
965
|
+
fields: {
|
|
966
|
+
NAME: name,
|
|
967
|
+
CODE: code
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
returnData.push({
|
|
971
|
+
json: {
|
|
972
|
+
tool_call_result: { sourceId: response.result, code },
|
|
973
|
+
summary: `Registered Ad Source "${name}"`
|
|
974
|
+
},
|
|
975
|
+
pairedItem: { item: i }
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
if (operation === 'findDuplicates') {
|
|
979
|
+
const type = this.getNodeParameter('entityType', i); // Reuse entityType?
|
|
980
|
+
// crm.duplicate.find requires entity_type (LEAD, CONTACT, COMPANY)
|
|
981
|
+
// And type (EMAIL, PHONE, PERSON)
|
|
982
|
+
// Let's simplify: Search by Phone or Email?
|
|
983
|
+
// Or just use generic 'query' parameter as value?
|
|
984
|
+
// Ideally we need dedicated inputs. Reuse 'query' as value (e.g. phone number).
|
|
985
|
+
// We need to know WHAT to search (Phone, Email).
|
|
986
|
+
// Let's assume user passes JSON in 'query' or we stick to simple Phone search for now?
|
|
987
|
+
// Bitrix24Tool 'searchCrm' handles simple search.
|
|
988
|
+
// 'findDuplicates' is stricter.
|
|
989
|
+
// crm.duplicate.findbycomm params: type=EMAIL, values=[...], entity_type=LEAD
|
|
990
|
+
// Simplification for V26: Search by Email/Phone automatically based on regex of query?
|
|
991
|
+
// Or just search by Phone (most common).
|
|
992
|
+
const query = this.getNodeParameter('query', i);
|
|
993
|
+
let typeToSearch = 'PHONE';
|
|
994
|
+
if (query.includes('@'))
|
|
995
|
+
typeToSearch = 'EMAIL';
|
|
996
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'crm.duplicate.findbycomm', {
|
|
997
|
+
type: typeToSearch,
|
|
998
|
+
values: [query],
|
|
999
|
+
entity_type: type.toUpperCase() // LEAD, CONTACT...
|
|
1000
|
+
});
|
|
1001
|
+
returnData.push({ json: { duplicates: response.result }, pairedItem: { item: i } });
|
|
1002
|
+
}
|
|
1003
|
+
if (operation === 'addCrmStatus') {
|
|
1004
|
+
// Pending implementation
|
|
1005
|
+
}
|
|
1006
|
+
if (operation === 'getScope') {
|
|
1007
|
+
// scope returns json with 'result' array of scopes
|
|
1008
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'GET', 'scope.json', {});
|
|
1009
|
+
returnData.push({ json: { scope: response.result }, pairedItem: { item: i } });
|
|
1010
|
+
}
|
|
1011
|
+
if (operation === 'getFeatures') {
|
|
1012
|
+
// feature.get
|
|
1013
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'feature.get', {});
|
|
1014
|
+
returnData.push({ json: { features: response.result }, pairedItem: { item: i } });
|
|
1015
|
+
}
|
|
1016
|
+
if (operation === 'listOffline') {
|
|
1017
|
+
// event.offline.list
|
|
1018
|
+
// Requires scope: 'im'? No, 'event' scope? Usually included in basic.
|
|
1019
|
+
const params = JSON.parse(this.getNodeParameter('jsonParameters', i, '{}'));
|
|
1020
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', 'event.offline.list', params);
|
|
1021
|
+
returnData.push({ json: { events: response.result }, pairedItem: { item: i } });
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
catch (error) {
|
|
1025
|
+
if (this.continueOnFail()) {
|
|
1026
|
+
returnData.push({ json: { error: error.message }, pairedItem: { item: i } });
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1029
|
+
throw error;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
return [returnData];
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
exports.Bitrix24Tool = Bitrix24Tool;
|