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,1410 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bitrix24 (Pragma) — Основная CRM Нода
|
|
4
|
+
*
|
|
5
|
+
* Bitrix24 PRAGMA.by nodes for n8n
|
|
6
|
+
* Профессиональная интеграция с Битрикс24 CRM.
|
|
7
|
+
* Поддержка: Лиды, Сделки, Контакты, Компании, Предложения, Смарт-процессы.
|
|
8
|
+
*
|
|
9
|
+
* @author PRAGMA & Азбука Решений
|
|
10
|
+
* @copyright 2026 PRAGMA (https://pragma.by/) & Азбука Решений (https://abc-solution.ru/)
|
|
11
|
+
* @version 1.0.0
|
|
12
|
+
*
|
|
13
|
+
* Контакты для заказа разработки:
|
|
14
|
+
* 🇧🇾 PRAGMA: +375 (44) 702-70-90 | https://pragma.by/
|
|
15
|
+
* 🇷🇺 Азбука Решений: +7 (939) 555-19-60 | https://abc-solution.ru/
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.Bitrix24 = void 0;
|
|
19
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
20
|
+
const types_1 = require("./types");
|
|
21
|
+
const Helpers_1 = require("./Helpers"); // Standard 2026: Helper
|
|
22
|
+
const Lead_1 = require("./Lead");
|
|
23
|
+
const Deal_1 = require("./Deal");
|
|
24
|
+
const Contact_1 = require("./Contact");
|
|
25
|
+
const Company_1 = require("./Company");
|
|
26
|
+
class Bitrix24 {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.description = {
|
|
29
|
+
displayName: 'Bitrix24 (Pragma)',
|
|
30
|
+
name: 'pragmaBitrix24',
|
|
31
|
+
icon: 'file:bitrix24.svg',
|
|
32
|
+
group: ['transform'],
|
|
33
|
+
version: 1,
|
|
34
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
35
|
+
description: 'Работа с Битрикс24 CRM — лиды, сделки, контакты, компании и другие сущности',
|
|
36
|
+
defaults: {
|
|
37
|
+
name: 'Bitrix24 CRM',
|
|
38
|
+
},
|
|
39
|
+
inputs: ['main'],
|
|
40
|
+
outputs: ['main'],
|
|
41
|
+
credentials: [
|
|
42
|
+
{
|
|
43
|
+
name: 'bitrix24Api',
|
|
44
|
+
required: true,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
properties: [
|
|
48
|
+
{
|
|
49
|
+
displayName: 'Ресурс',
|
|
50
|
+
name: 'resource',
|
|
51
|
+
type: 'options',
|
|
52
|
+
noDataExpression: true,
|
|
53
|
+
options: [
|
|
54
|
+
// Описания ресурсов CRM на русском языке
|
|
55
|
+
{
|
|
56
|
+
name: Lead_1.Lead.getDescription().name,
|
|
57
|
+
value: Lead_1.Lead.getDescription().value,
|
|
58
|
+
description: 'Управление лидами в CRM. <a href="https://training.bitrix24.com/rest_help/crm/leads/" target="_blank">Документация</a>'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: Deal_1.Deal.getDescription().name,
|
|
62
|
+
value: Deal_1.Deal.getDescription().value,
|
|
63
|
+
description: 'Управление сделками в CRM. <a href="https://training.bitrix24.com/rest_help/crm/deals/" target="_blank">Документация</a>'
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: Contact_1.Contact.getDescription().name,
|
|
67
|
+
value: Contact_1.Contact.getDescription().value,
|
|
68
|
+
description: 'Управление контактами в CRM. <a href="https://training.bitrix24.com/rest_help/crm/contacts/" target="_blank">Документация</a>'
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: Company_1.Company.getDescription().name,
|
|
72
|
+
value: 'company',
|
|
73
|
+
description: 'Управление компаниями в CRM. <a href="https://training.bitrix24.com/rest_help/crm/companies/" target="_blank">Документация</a>'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'Смарт-процесс (SPA)',
|
|
77
|
+
value: 'smart_process',
|
|
78
|
+
description: 'Управление динамическими сущностями (Smart Process Automation)',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'Реквизиты',
|
|
82
|
+
value: 'requisite',
|
|
83
|
+
description: 'Управление реквизитами компаний/контактов (платёжные данные)',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'Товары (Строки)',
|
|
87
|
+
value: 'productrow',
|
|
88
|
+
description: 'Управление товарными позициями в сделках/лидах',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'Воронка (Направление)',
|
|
92
|
+
value: 'category',
|
|
93
|
+
description: 'Управление воронками продаж',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'Стадия (Статус)',
|
|
97
|
+
value: 'status',
|
|
98
|
+
description: 'Управление стадиями и статусами CRM',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Произвольный (Raw)',
|
|
102
|
+
value: 'other',
|
|
103
|
+
description: 'Вызов любого метода Bitrix24 API',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'Предложение (Смета)',
|
|
107
|
+
value: 'quote',
|
|
108
|
+
description: 'Управление коммерческими предложениями',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
default: 'lead',
|
|
112
|
+
required: true,
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
displayName: 'Операция',
|
|
116
|
+
name: 'operation',
|
|
117
|
+
type: 'options',
|
|
118
|
+
noDataExpression: true,
|
|
119
|
+
options: [
|
|
120
|
+
{
|
|
121
|
+
name: 'Создать',
|
|
122
|
+
value: 'create',
|
|
123
|
+
description: 'Создать новую запись',
|
|
124
|
+
action: 'Создать запись',
|
|
125
|
+
displayOptions: {
|
|
126
|
+
hide: {
|
|
127
|
+
resource: ['other'],
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: 'Получить',
|
|
133
|
+
value: 'get',
|
|
134
|
+
description: 'Получить запись по ID',
|
|
135
|
+
action: 'Получить запись',
|
|
136
|
+
displayOptions: {
|
|
137
|
+
hide: {
|
|
138
|
+
resource: ['other'],
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'Список',
|
|
144
|
+
value: 'list',
|
|
145
|
+
description: 'Получить список записей',
|
|
146
|
+
action: 'Получить список',
|
|
147
|
+
displayOptions: {
|
|
148
|
+
hide: {
|
|
149
|
+
resource: ['other'],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: 'Обновить',
|
|
155
|
+
value: 'update',
|
|
156
|
+
description: 'Обновить запись',
|
|
157
|
+
action: 'Обновить запись',
|
|
158
|
+
displayOptions: {
|
|
159
|
+
hide: {
|
|
160
|
+
resource: ['other'],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'Удалить',
|
|
166
|
+
value: 'delete',
|
|
167
|
+
description: 'Удалить запись',
|
|
168
|
+
action: 'Удалить запись',
|
|
169
|
+
displayOptions: {
|
|
170
|
+
hide: {
|
|
171
|
+
resource: ['other'],
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'Произвольный запрос',
|
|
177
|
+
value: 'raw',
|
|
178
|
+
description: 'Вызов любого метода API',
|
|
179
|
+
action: 'Выполнить API запрос',
|
|
180
|
+
displayOptions: {
|
|
181
|
+
show: {
|
|
182
|
+
resource: ['other'],
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
default: 'create',
|
|
188
|
+
required: true,
|
|
189
|
+
},
|
|
190
|
+
// ----------------------------------
|
|
191
|
+
// Поля Предложения
|
|
192
|
+
// ----------------------------------
|
|
193
|
+
{
|
|
194
|
+
displayName: 'Тема предложения',
|
|
195
|
+
name: 'quoteSubject',
|
|
196
|
+
type: 'string',
|
|
197
|
+
default: '',
|
|
198
|
+
placeholder: 'Коммерческое предложение клиенту',
|
|
199
|
+
displayOptions: {
|
|
200
|
+
show: {
|
|
201
|
+
resource: ['quote'],
|
|
202
|
+
operation: ['create', 'update'],
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
description: 'Тема/название коммерческого предложения',
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
displayName: 'ID сделки (привязка)',
|
|
209
|
+
name: 'dealId',
|
|
210
|
+
type: 'string',
|
|
211
|
+
default: '',
|
|
212
|
+
placeholder: '123',
|
|
213
|
+
hint: 'ID сделки для привязки предложения',
|
|
214
|
+
displayOptions: {
|
|
215
|
+
show: {
|
|
216
|
+
resource: ['quote'],
|
|
217
|
+
operation: ['create'],
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
displayName: 'ID компании',
|
|
223
|
+
name: 'companyId',
|
|
224
|
+
type: 'string',
|
|
225
|
+
default: '',
|
|
226
|
+
placeholder: '456',
|
|
227
|
+
hint: 'ID компании-клиента',
|
|
228
|
+
displayOptions: {
|
|
229
|
+
show: {
|
|
230
|
+
resource: ['quote'],
|
|
231
|
+
operation: ['create'],
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
displayName: 'ID контакта',
|
|
237
|
+
name: 'contactId',
|
|
238
|
+
type: 'string',
|
|
239
|
+
default: '',
|
|
240
|
+
placeholder: '789',
|
|
241
|
+
hint: 'ID контакта-клиента',
|
|
242
|
+
displayOptions: {
|
|
243
|
+
show: {
|
|
244
|
+
resource: ['quote'],
|
|
245
|
+
operation: ['create'],
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
// ----------------------------------
|
|
250
|
+
// Поля Сделки/Лида
|
|
251
|
+
// ----------------------------------
|
|
252
|
+
{
|
|
253
|
+
displayName: 'Название',
|
|
254
|
+
name: 'title',
|
|
255
|
+
type: 'string',
|
|
256
|
+
default: '',
|
|
257
|
+
placeholder: 'Новая сделка с Компанией ABC',
|
|
258
|
+
displayOptions: {
|
|
259
|
+
show: {
|
|
260
|
+
resource: ['lead', 'deal'],
|
|
261
|
+
operation: ['create'],
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
description: 'Название сделки или лида',
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
displayName: 'Ответственный',
|
|
268
|
+
name: 'assignedById',
|
|
269
|
+
type: 'options',
|
|
270
|
+
typeOptions: {
|
|
271
|
+
loadOptionsMethod: 'getUsers',
|
|
272
|
+
},
|
|
273
|
+
default: '',
|
|
274
|
+
displayOptions: {
|
|
275
|
+
show: {
|
|
276
|
+
resource: ['lead', 'deal', 'contact', 'company'],
|
|
277
|
+
operation: ['create'],
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
description: 'Пользователь, ответственный за сущность',
|
|
281
|
+
},
|
|
282
|
+
// Статус лида
|
|
283
|
+
{
|
|
284
|
+
displayName: 'Статус',
|
|
285
|
+
name: 'statusId',
|
|
286
|
+
type: 'options',
|
|
287
|
+
typeOptions: {
|
|
288
|
+
loadOptionsMethod: 'getLeadStatuses',
|
|
289
|
+
},
|
|
290
|
+
default: '',
|
|
291
|
+
displayOptions: {
|
|
292
|
+
show: {
|
|
293
|
+
resource: ['lead'],
|
|
294
|
+
operation: ['create'],
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
description: 'Текущий статус лида в воронке. Выберите из списка доступных статусов.',
|
|
298
|
+
hint: 'Статусы настраиваются в CRM → Настройки → Стадии и статусы',
|
|
299
|
+
},
|
|
300
|
+
// Воронка и стадия сделки
|
|
301
|
+
{
|
|
302
|
+
displayName: 'Воронка (Направление)',
|
|
303
|
+
name: 'categoryId',
|
|
304
|
+
type: 'options',
|
|
305
|
+
typeOptions: {
|
|
306
|
+
loadOptionsMethod: 'getDealCategories',
|
|
307
|
+
},
|
|
308
|
+
default: '0',
|
|
309
|
+
displayOptions: {
|
|
310
|
+
show: {
|
|
311
|
+
resource: ['deal'],
|
|
312
|
+
operation: ['create', 'update'],
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
description: 'Воронка продаж для сделки. Каждая воронка имеет свои стадии.',
|
|
316
|
+
hint: '0 = Общая воронка. Дополнительные создаются в CRM → Настройки',
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
displayName: 'Стадия',
|
|
320
|
+
name: 'stageId',
|
|
321
|
+
type: 'options',
|
|
322
|
+
typeOptions: {
|
|
323
|
+
loadOptionsMethod: 'getDealStages',
|
|
324
|
+
loadOptionsDependsOn: ['categoryId'],
|
|
325
|
+
},
|
|
326
|
+
default: '',
|
|
327
|
+
displayOptions: {
|
|
328
|
+
show: {
|
|
329
|
+
resource: ['deal'],
|
|
330
|
+
operation: ['create', 'update'],
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
description: 'Текущая стадия сделки в выбранной воронке',
|
|
334
|
+
hint: 'Список стадий зависит от выбранной воронки',
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
displayName: 'Тип смарт-процесса',
|
|
338
|
+
name: 'smartProcessId',
|
|
339
|
+
type: 'options',
|
|
340
|
+
typeOptions: {
|
|
341
|
+
loadOptionsMethod: 'getSmartProcesses',
|
|
342
|
+
},
|
|
343
|
+
default: '',
|
|
344
|
+
required: true,
|
|
345
|
+
displayOptions: {
|
|
346
|
+
show: {
|
|
347
|
+
resource: ['smart_process'],
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
description: 'Выберите тип динамической сущности (Smart Process Automation)',
|
|
351
|
+
hint: 'Смарт-процессы создаются в CRM → Настройки → CRM → Смарт-процессы',
|
|
352
|
+
},
|
|
353
|
+
// Поля произвольного запроса
|
|
354
|
+
{
|
|
355
|
+
displayName: 'Метод HTTP',
|
|
356
|
+
name: 'method',
|
|
357
|
+
type: 'options',
|
|
358
|
+
options: [
|
|
359
|
+
{ name: 'GET', value: 'GET' },
|
|
360
|
+
{ name: 'POST', value: 'POST' },
|
|
361
|
+
],
|
|
362
|
+
default: 'POST',
|
|
363
|
+
required: true,
|
|
364
|
+
displayOptions: {
|
|
365
|
+
show: {
|
|
366
|
+
resource: ['other'],
|
|
367
|
+
operation: ['raw'],
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
description: 'HTTP-метод запроса. Большинство методов Битрикс24 используют POST.',
|
|
371
|
+
hint: 'POST — для создания/изменения, GET — для получения данных',
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
displayName: 'Метод API',
|
|
375
|
+
name: 'endpoint',
|
|
376
|
+
type: 'string',
|
|
377
|
+
default: '',
|
|
378
|
+
placeholder: 'crm.lead.add',
|
|
379
|
+
required: true,
|
|
380
|
+
displayOptions: {
|
|
381
|
+
show: {
|
|
382
|
+
resource: ['other'],
|
|
383
|
+
operation: ['raw'],
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
description: 'Название метода REST API Битрикс24 для вызова',
|
|
387
|
+
hint: 'Список методов: <a href="https://training.bitrix24.com/rest_help/" target="_blank">training.bitrix24.com/rest_help</a>',
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
displayName: 'Тело запроса (JSON)',
|
|
391
|
+
name: 'jsonBody',
|
|
392
|
+
type: 'json',
|
|
393
|
+
default: '{}',
|
|
394
|
+
displayOptions: {
|
|
395
|
+
show: {
|
|
396
|
+
resource: ['other'],
|
|
397
|
+
operation: ['raw'],
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
description: 'JSON-объект с параметрами запроса. Структура зависит от метода API.',
|
|
401
|
+
hint: 'Пример: {"fields": {"TITLE": "Новый лид", "NAME": "Иван"}}',
|
|
402
|
+
},
|
|
403
|
+
// Поле ID
|
|
404
|
+
{
|
|
405
|
+
displayName: 'Получить по',
|
|
406
|
+
name: 'getBy',
|
|
407
|
+
type: 'options',
|
|
408
|
+
options: [
|
|
409
|
+
{
|
|
410
|
+
name: 'ID',
|
|
411
|
+
value: 'id',
|
|
412
|
+
description: 'Получить по идентификатору',
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
name: 'Фильтр',
|
|
416
|
+
value: 'filter',
|
|
417
|
+
description: 'Получить по условию фильтра',
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
default: 'id',
|
|
421
|
+
displayOptions: {
|
|
422
|
+
show: {
|
|
423
|
+
operation: ['get'],
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
description: 'Способ поиска записи',
|
|
427
|
+
hint: 'ID — быстрее, Фильтр — гибче',
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
displayName: 'ID записи',
|
|
431
|
+
name: 'id',
|
|
432
|
+
type: 'string',
|
|
433
|
+
default: '',
|
|
434
|
+
required: true,
|
|
435
|
+
placeholder: '123 или 123,124,125',
|
|
436
|
+
displayOptions: {
|
|
437
|
+
show: {
|
|
438
|
+
operation: ['get'],
|
|
439
|
+
getBy: ['id'],
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
description: 'Уникальный идентификатор записи. Для нескольких записей укажите ID через запятую.',
|
|
443
|
+
hint: 'Пример: 10,11,12 для получения трёх записей одним запросом',
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
displayName: 'Компактный режим',
|
|
447
|
+
name: 'compactMode',
|
|
448
|
+
type: 'boolean',
|
|
449
|
+
default: false,
|
|
450
|
+
description: 'Скрыть пустые и служебные поля в результате для уменьшения объёма данных',
|
|
451
|
+
hint: 'Рекомендуется для AI-интеграций и больших объёмов данных',
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
displayName: 'Filter Fields',
|
|
455
|
+
name: 'filterFields',
|
|
456
|
+
type: 'fixedCollection',
|
|
457
|
+
typeOptions: {
|
|
458
|
+
multipleValues: true,
|
|
459
|
+
sortable: true,
|
|
460
|
+
},
|
|
461
|
+
placeholder: 'Add Filter Field',
|
|
462
|
+
default: {},
|
|
463
|
+
options: [
|
|
464
|
+
{
|
|
465
|
+
name: 'field',
|
|
466
|
+
displayName: 'Fields',
|
|
467
|
+
values: [
|
|
468
|
+
{
|
|
469
|
+
displayName: 'Field Name',
|
|
470
|
+
name: 'fieldName',
|
|
471
|
+
type: 'options',
|
|
472
|
+
typeOptions: {
|
|
473
|
+
loadOptionsMethod: 'getFields',
|
|
474
|
+
},
|
|
475
|
+
default: '',
|
|
476
|
+
description: 'Name of the field to filter by',
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
displayName: 'Operation',
|
|
480
|
+
name: 'operation',
|
|
481
|
+
type: 'options',
|
|
482
|
+
options: [
|
|
483
|
+
{ name: 'Equals', value: 'equals' },
|
|
484
|
+
{ name: 'Not Equals', value: '!=' },
|
|
485
|
+
{ name: 'Greater Than', value: '>' },
|
|
486
|
+
{ name: 'Greater Than or Equal', value: '>=' },
|
|
487
|
+
{ name: 'Less Than', value: '<' },
|
|
488
|
+
{ name: 'Less Than or Equal', value: '<=' },
|
|
489
|
+
{ name: 'Contains', value: '%' },
|
|
490
|
+
{ name: 'Not Contains', value: '!%' },
|
|
491
|
+
{ name: 'Starts With', value: '=%' },
|
|
492
|
+
{ name: 'Ends With', value: '%=' },
|
|
493
|
+
{ name: 'In List', value: '@' },
|
|
494
|
+
{ name: 'Not In List', value: '!@' },
|
|
495
|
+
],
|
|
496
|
+
default: 'equals',
|
|
497
|
+
description: 'Comparison operation',
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
displayName: 'Value',
|
|
501
|
+
name: 'value',
|
|
502
|
+
type: 'string',
|
|
503
|
+
default: '',
|
|
504
|
+
description: 'Filter value',
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
],
|
|
509
|
+
displayOptions: {
|
|
510
|
+
show: {
|
|
511
|
+
operation: ['get'],
|
|
512
|
+
getBy: ['filter'],
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
displayName: 'ID',
|
|
518
|
+
name: 'id',
|
|
519
|
+
type: 'string',
|
|
520
|
+
default: '',
|
|
521
|
+
required: true,
|
|
522
|
+
displayOptions: {
|
|
523
|
+
show: {
|
|
524
|
+
operation: ['update', 'delete'],
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
description: 'Record ID',
|
|
528
|
+
},
|
|
529
|
+
// Input Format Selection
|
|
530
|
+
{
|
|
531
|
+
displayName: 'Input Format',
|
|
532
|
+
name: 'inputFormat',
|
|
533
|
+
type: 'options',
|
|
534
|
+
options: [
|
|
535
|
+
{
|
|
536
|
+
name: 'Form',
|
|
537
|
+
value: 'form',
|
|
538
|
+
description: 'Use form for field input',
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
name: 'JSON',
|
|
542
|
+
value: 'json',
|
|
543
|
+
description: 'Use JSON format for field input',
|
|
544
|
+
},
|
|
545
|
+
],
|
|
546
|
+
default: 'form',
|
|
547
|
+
displayOptions: {
|
|
548
|
+
show: {
|
|
549
|
+
operation: ['create', 'update'],
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
// JSON Fields
|
|
554
|
+
{
|
|
555
|
+
displayName: 'Fields (JSON)',
|
|
556
|
+
name: 'fieldsJson',
|
|
557
|
+
type: 'json',
|
|
558
|
+
default: '{}',
|
|
559
|
+
description: 'Fields in JSON format',
|
|
560
|
+
displayOptions: {
|
|
561
|
+
show: {
|
|
562
|
+
operation: ['create', 'update'],
|
|
563
|
+
inputFormat: ['json'],
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
// Form Fields
|
|
568
|
+
{
|
|
569
|
+
displayName: 'Fields',
|
|
570
|
+
name: 'fields',
|
|
571
|
+
type: 'fixedCollection',
|
|
572
|
+
typeOptions: {
|
|
573
|
+
multipleValues: true,
|
|
574
|
+
sortable: true,
|
|
575
|
+
},
|
|
576
|
+
placeholder: 'Add Field',
|
|
577
|
+
default: {},
|
|
578
|
+
options: [
|
|
579
|
+
{
|
|
580
|
+
name: 'field',
|
|
581
|
+
displayName: 'Fields',
|
|
582
|
+
values: [
|
|
583
|
+
{
|
|
584
|
+
displayName: 'Field Name',
|
|
585
|
+
name: 'fieldName',
|
|
586
|
+
type: 'options',
|
|
587
|
+
typeOptions: {
|
|
588
|
+
loadOptionsMethod: 'getFields',
|
|
589
|
+
},
|
|
590
|
+
default: '',
|
|
591
|
+
description: 'Name of the field to update',
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
displayName: 'Communication Type',
|
|
595
|
+
name: 'fieldValueType',
|
|
596
|
+
type: 'options',
|
|
597
|
+
options: Contact_1.Contact.communicationTypes,
|
|
598
|
+
default: types_1.CommunicationType.WORK,
|
|
599
|
+
description: 'Type of contact data',
|
|
600
|
+
displayOptions: {
|
|
601
|
+
show: {
|
|
602
|
+
'/resource': ['contact'],
|
|
603
|
+
},
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
displayName: 'Field Value',
|
|
608
|
+
name: 'fieldValue',
|
|
609
|
+
type: 'options',
|
|
610
|
+
typeOptions: {
|
|
611
|
+
loadOptionsMethod: 'getEnumValues',
|
|
612
|
+
loadOptionsDependsOn: ['fieldName'],
|
|
613
|
+
},
|
|
614
|
+
displayOptions: {
|
|
615
|
+
show: {
|
|
616
|
+
'/operation': ['create', 'update'],
|
|
617
|
+
fieldValueType: ['enumeration'],
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
default: '',
|
|
621
|
+
description: 'Value of the field',
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
displayName: 'Field Value',
|
|
625
|
+
name: 'fieldValue',
|
|
626
|
+
type: 'string',
|
|
627
|
+
displayOptions: {
|
|
628
|
+
hide: {
|
|
629
|
+
fieldValueType: ['enumeration'],
|
|
630
|
+
},
|
|
631
|
+
},
|
|
632
|
+
default: '',
|
|
633
|
+
description: 'Value of the field',
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
description: 'Fields for creation/update',
|
|
639
|
+
displayOptions: {
|
|
640
|
+
show: {
|
|
641
|
+
operation: ['create', 'update'],
|
|
642
|
+
inputFormat: ['form'],
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
// List Fields
|
|
647
|
+
{
|
|
648
|
+
displayName: 'Return All',
|
|
649
|
+
name: 'returnAll',
|
|
650
|
+
type: 'boolean',
|
|
651
|
+
default: false,
|
|
652
|
+
description: 'Whether to return all results or only up to a given limit',
|
|
653
|
+
displayOptions: {
|
|
654
|
+
show: {
|
|
655
|
+
operation: ['list'],
|
|
656
|
+
},
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
displayName: 'Limit',
|
|
661
|
+
name: 'limit',
|
|
662
|
+
type: 'number',
|
|
663
|
+
default: 50,
|
|
664
|
+
description: 'Max number of results to return',
|
|
665
|
+
displayOptions: {
|
|
666
|
+
show: {
|
|
667
|
+
operation: ['list'],
|
|
668
|
+
returnAll: [false],
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
displayName: 'Use Filter',
|
|
674
|
+
name: 'useFilter',
|
|
675
|
+
type: 'boolean',
|
|
676
|
+
default: false,
|
|
677
|
+
description: 'Whether to filter the results',
|
|
678
|
+
displayOptions: {
|
|
679
|
+
show: {
|
|
680
|
+
operation: ['list'],
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
displayName: 'Filter Fields',
|
|
686
|
+
name: 'filterFields',
|
|
687
|
+
type: 'fixedCollection',
|
|
688
|
+
typeOptions: {
|
|
689
|
+
multipleValues: true,
|
|
690
|
+
sortable: true,
|
|
691
|
+
},
|
|
692
|
+
placeholder: 'Add Filter Field',
|
|
693
|
+
default: {},
|
|
694
|
+
options: [
|
|
695
|
+
{
|
|
696
|
+
name: 'field',
|
|
697
|
+
displayName: 'Fields',
|
|
698
|
+
values: [
|
|
699
|
+
{
|
|
700
|
+
displayName: 'Field Name',
|
|
701
|
+
name: 'fieldName',
|
|
702
|
+
type: 'options',
|
|
703
|
+
typeOptions: {
|
|
704
|
+
loadOptionsMethod: 'getFields',
|
|
705
|
+
},
|
|
706
|
+
default: '',
|
|
707
|
+
description: 'Name of the field to filter by',
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
displayName: 'Operation',
|
|
711
|
+
name: 'operation',
|
|
712
|
+
type: 'options',
|
|
713
|
+
options: [
|
|
714
|
+
{ name: 'Equals', value: 'equals' },
|
|
715
|
+
{ name: 'Not Equals', value: '!=' },
|
|
716
|
+
{ name: 'Greater Than', value: '>' },
|
|
717
|
+
{ name: 'Greater Than or Equal', value: '>=' },
|
|
718
|
+
{ name: 'Less Than', value: '<' },
|
|
719
|
+
{ name: 'Less Than or Equal', value: '<=' },
|
|
720
|
+
{ name: 'Contains', value: '%' },
|
|
721
|
+
{ name: 'Not Contains', value: '!%' },
|
|
722
|
+
{ name: 'Starts With', value: '=%' },
|
|
723
|
+
{ name: 'Ends With', value: '%=' },
|
|
724
|
+
{ name: 'In List', value: '@' },
|
|
725
|
+
{ name: 'Not In List', value: '!@' },
|
|
726
|
+
],
|
|
727
|
+
default: 'equals',
|
|
728
|
+
description: 'Comparison operation',
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
displayName: 'Value',
|
|
732
|
+
name: 'value',
|
|
733
|
+
type: 'string',
|
|
734
|
+
default: '',
|
|
735
|
+
description: 'Filter value',
|
|
736
|
+
},
|
|
737
|
+
],
|
|
738
|
+
},
|
|
739
|
+
],
|
|
740
|
+
displayOptions: {
|
|
741
|
+
show: {
|
|
742
|
+
operation: ['list'],
|
|
743
|
+
useFilter: [true],
|
|
744
|
+
},
|
|
745
|
+
},
|
|
746
|
+
},
|
|
747
|
+
{
|
|
748
|
+
displayName: 'Select Fields',
|
|
749
|
+
name: 'selectFields',
|
|
750
|
+
type: 'multiOptions',
|
|
751
|
+
typeOptions: {
|
|
752
|
+
loadOptionsMethod: 'getFields',
|
|
753
|
+
},
|
|
754
|
+
default: [],
|
|
755
|
+
description: 'Select fields to retrieve',
|
|
756
|
+
displayOptions: {
|
|
757
|
+
show: {
|
|
758
|
+
operation: ['get', 'list'],
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
},
|
|
762
|
+
],
|
|
763
|
+
};
|
|
764
|
+
this.methods = {
|
|
765
|
+
loadOptions: {
|
|
766
|
+
async getSmartProcesses() {
|
|
767
|
+
try {
|
|
768
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
769
|
+
if (!credentials)
|
|
770
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials returned!');
|
|
771
|
+
const response = await this.helpers.httpRequest({
|
|
772
|
+
method: 'GET',
|
|
773
|
+
baseURL: credentials.webhookUrl,
|
|
774
|
+
url: 'crm.type.list.json', // Standard 2026: SPA List
|
|
775
|
+
json: true,
|
|
776
|
+
});
|
|
777
|
+
if (!response || !response.result || !response.result.types) {
|
|
778
|
+
// Fallback if no types or different format
|
|
779
|
+
return [];
|
|
780
|
+
}
|
|
781
|
+
const types = response.result.types;
|
|
782
|
+
return types.map(t => ({
|
|
783
|
+
name: t.title,
|
|
784
|
+
value: t.entityTypeId.toString(),
|
|
785
|
+
}));
|
|
786
|
+
}
|
|
787
|
+
catch (error) {
|
|
788
|
+
// Fallback for older Bitrix versions
|
|
789
|
+
return [];
|
|
790
|
+
}
|
|
791
|
+
},
|
|
792
|
+
async getFields() {
|
|
793
|
+
try {
|
|
794
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
795
|
+
if (!credentials) {
|
|
796
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials returned!');
|
|
797
|
+
}
|
|
798
|
+
let resource = this.getCurrentNodeParameter('resource');
|
|
799
|
+
let endpoint = `crm.${resource}.fields`;
|
|
800
|
+
// Standard 2026: SPA Fields Logic
|
|
801
|
+
if (resource === 'smart_process') {
|
|
802
|
+
const smartProcessId = this.getCurrentNodeParameter('smartProcessId');
|
|
803
|
+
if (!smartProcessId)
|
|
804
|
+
return [];
|
|
805
|
+
endpoint = `crm.item.fields?entityTypeId=${smartProcessId}`;
|
|
806
|
+
}
|
|
807
|
+
// Standard 2026: Requisite Fields Logic
|
|
808
|
+
if (resource === 'requisite') {
|
|
809
|
+
endpoint = 'crm.requisite.fields';
|
|
810
|
+
}
|
|
811
|
+
const response = await this.helpers.httpRequest({
|
|
812
|
+
method: 'GET',
|
|
813
|
+
baseURL: credentials.webhookUrl,
|
|
814
|
+
url: endpoint,
|
|
815
|
+
json: true,
|
|
816
|
+
});
|
|
817
|
+
if (!response || !response.result) {
|
|
818
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid response from Bitrix24!');
|
|
819
|
+
}
|
|
820
|
+
const fields = response.result;
|
|
821
|
+
const options = [];
|
|
822
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
823
|
+
const fieldName = value.formLabel || value.listLabel || value.title || key;
|
|
824
|
+
const description = [
|
|
825
|
+
`Type: ${value.type}`,
|
|
826
|
+
value.isRequired ? 'Required' : 'Optional',
|
|
827
|
+
value.isReadOnly ? 'Read-only' : 'Read/Write',
|
|
828
|
+
value.isMultiple ? 'Multiple' : 'Single',
|
|
829
|
+
].join(', ');
|
|
830
|
+
options.push({
|
|
831
|
+
name: fieldName,
|
|
832
|
+
value: key,
|
|
833
|
+
description,
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
return options;
|
|
837
|
+
}
|
|
838
|
+
catch (error) {
|
|
839
|
+
if (error instanceof n8n_workflow_1.NodeOperationError) {
|
|
840
|
+
throw error;
|
|
841
|
+
}
|
|
842
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to load fields: ' + error.message);
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
async getEnumValues() {
|
|
846
|
+
try {
|
|
847
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
848
|
+
if (!credentials) {
|
|
849
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials returned!');
|
|
850
|
+
}
|
|
851
|
+
let resource = this.getCurrentNodeParameter('resource');
|
|
852
|
+
let endpoint = `crm.${resource}.fields`;
|
|
853
|
+
if (resource === 'smart_process') {
|
|
854
|
+
const smartProcessId = this.getCurrentNodeParameter('smartProcessId');
|
|
855
|
+
endpoint = `crm.item.fields?entityTypeId=${smartProcessId}`;
|
|
856
|
+
}
|
|
857
|
+
if (resource === 'requisite') {
|
|
858
|
+
endpoint = 'crm.requisite.fields';
|
|
859
|
+
}
|
|
860
|
+
const fieldsData = this.getCurrentNodeParameter('fields');
|
|
861
|
+
const fieldName = fieldsData?.field?.[0]?.fieldName;
|
|
862
|
+
if (!fieldName) {
|
|
863
|
+
return [{ name: '- Select Field First -', value: '', description: 'Please select a field first' }];
|
|
864
|
+
}
|
|
865
|
+
const response = await this.helpers.httpRequest({
|
|
866
|
+
method: 'GET',
|
|
867
|
+
baseURL: credentials.webhookUrl,
|
|
868
|
+
url: endpoint,
|
|
869
|
+
json: true,
|
|
870
|
+
});
|
|
871
|
+
if (!response || !response.result) {
|
|
872
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid response from Bitrix24!');
|
|
873
|
+
}
|
|
874
|
+
const fieldsInfo = response.result;
|
|
875
|
+
const field = fieldsInfo[fieldName];
|
|
876
|
+
if (!field) {
|
|
877
|
+
return [{ name: '- Field Not Found -', value: '', description: 'Field not found in Bitrix24 response' }];
|
|
878
|
+
}
|
|
879
|
+
if (field.type === 'enumeration' || (field.type === 'crm_status')) { // Handle generic status fields too
|
|
880
|
+
if (field.items && Array.isArray(field.items)) {
|
|
881
|
+
return field.items.map((item) => ({
|
|
882
|
+
name: item.VALUE,
|
|
883
|
+
value: item.VALUE,
|
|
884
|
+
description: `ID: ${item.ID}`,
|
|
885
|
+
}));
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
// Standard 2026: Dynamic Users
|
|
889
|
+
if (field.type === 'user') {
|
|
890
|
+
const userResponse = await this.helpers.httpRequest({
|
|
891
|
+
method: 'POST',
|
|
892
|
+
baseURL: credentials.webhookUrl,
|
|
893
|
+
url: 'user.get.json',
|
|
894
|
+
body: { FILTER: { ACTIVE: 'Y' } },
|
|
895
|
+
json: true,
|
|
896
|
+
});
|
|
897
|
+
if (userResponse.result && Array.isArray(userResponse.result)) {
|
|
898
|
+
return userResponse.result.map((u) => ({
|
|
899
|
+
name: `${u.NAME} ${u.LAST_NAME}`.trim(),
|
|
900
|
+
value: u.ID,
|
|
901
|
+
description: `ID: ${u.ID}`,
|
|
902
|
+
}));
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
// Standard 2026: Dynamic Currencies
|
|
906
|
+
if (field.type === 'crm_currency') {
|
|
907
|
+
const currResponse = await this.helpers.httpRequest({
|
|
908
|
+
method: 'POST',
|
|
909
|
+
baseURL: credentials.webhookUrl,
|
|
910
|
+
url: 'crm.currency.list.json',
|
|
911
|
+
json: true,
|
|
912
|
+
});
|
|
913
|
+
if (currResponse.result && Array.isArray(currResponse.result)) {
|
|
914
|
+
return currResponse.result.map((c) => ({
|
|
915
|
+
name: c.FULL_NAME,
|
|
916
|
+
value: c.CURRENCY,
|
|
917
|
+
description: `Code: ${c.CURRENCY}`,
|
|
918
|
+
}));
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
return [{ name: '- Text Field (or Manual ID) -', value: '', description: 'Enter value manually' }];
|
|
922
|
+
}
|
|
923
|
+
catch (error) {
|
|
924
|
+
if (error instanceof n8n_workflow_1.NodeOperationError) {
|
|
925
|
+
throw error;
|
|
926
|
+
}
|
|
927
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to load enum values: ' + error.message);
|
|
928
|
+
}
|
|
929
|
+
},
|
|
930
|
+
async getCrmCategories() {
|
|
931
|
+
try {
|
|
932
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
933
|
+
if (!credentials)
|
|
934
|
+
return [];
|
|
935
|
+
const resource = this.getCurrentNodeParameter('resource');
|
|
936
|
+
if (resource !== 'deal') {
|
|
937
|
+
return [{ name: 'General', value: '0' }];
|
|
938
|
+
}
|
|
939
|
+
const response = await this.helpers.httpRequest({
|
|
940
|
+
method: 'POST',
|
|
941
|
+
baseURL: credentials.webhookUrl,
|
|
942
|
+
url: 'crm.category.list.json',
|
|
943
|
+
body: { entityTypeId: 2 }, // 2 for Deal
|
|
944
|
+
json: true,
|
|
945
|
+
});
|
|
946
|
+
const options = [{ name: 'General', value: '0' }];
|
|
947
|
+
if (response.result && Array.isArray(response.result.categories)) {
|
|
948
|
+
for (const cat of response.result.categories) {
|
|
949
|
+
options.push({
|
|
950
|
+
name: cat.name,
|
|
951
|
+
value: cat.id.toString(),
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return options;
|
|
956
|
+
}
|
|
957
|
+
catch (e) {
|
|
958
|
+
return [{ name: 'General', value: '0' }];
|
|
959
|
+
}
|
|
960
|
+
},
|
|
961
|
+
async getCrmStages() {
|
|
962
|
+
try {
|
|
963
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
964
|
+
if (!credentials)
|
|
965
|
+
return [];
|
|
966
|
+
const resource = this.getCurrentNodeParameter('resource');
|
|
967
|
+
const categoryId = this.getCurrentNodeParameter('categoryId');
|
|
968
|
+
let endpoint = 'crm.status.list.json';
|
|
969
|
+
let body = {};
|
|
970
|
+
if (resource === 'lead') {
|
|
971
|
+
body = { FILTER: { ENTITY_ID: 'STATUS' } };
|
|
972
|
+
}
|
|
973
|
+
else if (resource === 'deal') {
|
|
974
|
+
if (categoryId && categoryId !== '0') {
|
|
975
|
+
endpoint = 'crm.dealcategory.stage.list.json';
|
|
976
|
+
body = { id: categoryId };
|
|
977
|
+
}
|
|
978
|
+
else {
|
|
979
|
+
body = { FILTER: { ENTITY_ID: 'DEAL_STAGE' } };
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
return [];
|
|
984
|
+
}
|
|
985
|
+
const response = await this.helpers.httpRequest({
|
|
986
|
+
method: 'POST',
|
|
987
|
+
baseURL: credentials.webhookUrl,
|
|
988
|
+
url: endpoint,
|
|
989
|
+
body,
|
|
990
|
+
json: true,
|
|
991
|
+
});
|
|
992
|
+
const options = [];
|
|
993
|
+
if (Array.isArray(response.result)) {
|
|
994
|
+
for (const stage of response.result) {
|
|
995
|
+
options.push({
|
|
996
|
+
name: stage.NAME || stage.name, // .list returns NAME, .stage.list returns name
|
|
997
|
+
value: stage.STATUS_ID || stage.statusId,
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return options;
|
|
1002
|
+
}
|
|
1003
|
+
catch (e) {
|
|
1004
|
+
return [];
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
async execute() {
|
|
1011
|
+
try {
|
|
1012
|
+
const items = this.getInputData();
|
|
1013
|
+
const returnData = [];
|
|
1014
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
1015
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
1016
|
+
for (let i = 0; i < items.length; i++) {
|
|
1017
|
+
try {
|
|
1018
|
+
if (operation === 'create' || operation === 'update') {
|
|
1019
|
+
let method = operation === 'create' ? 'add' : 'update';
|
|
1020
|
+
let endpoint = `crm.${resource}.${method}.json`;
|
|
1021
|
+
// Standard 2026: SPA Logic
|
|
1022
|
+
if (resource === 'smart_process') {
|
|
1023
|
+
endpoint = `crm.item.${method}.json`;
|
|
1024
|
+
}
|
|
1025
|
+
// Standard 2026: Requisite Logic
|
|
1026
|
+
if (resource === 'requisite') {
|
|
1027
|
+
endpoint = `crm.requisite.${method}.json`;
|
|
1028
|
+
}
|
|
1029
|
+
const inputFormat = this.getNodeParameter('inputFormat', i);
|
|
1030
|
+
let fields = {};
|
|
1031
|
+
if (inputFormat === 'json') {
|
|
1032
|
+
const fieldsJson = this.getNodeParameter('fieldsJson', i);
|
|
1033
|
+
if (typeof fieldsJson === 'string') {
|
|
1034
|
+
fields = JSON.parse(fieldsJson);
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
fields = fieldsJson;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
else {
|
|
1041
|
+
// Standard 2026: Fetch dynamic fields
|
|
1042
|
+
let fieldsEndpoint = `crm.${resource}.fields.json`;
|
|
1043
|
+
if (resource === 'smart_process') {
|
|
1044
|
+
const smartProcessId = this.getNodeParameter('smartProcessId', i);
|
|
1045
|
+
fieldsEndpoint = `crm.item.fields.json?entityTypeId=${smartProcessId}`;
|
|
1046
|
+
}
|
|
1047
|
+
if (resource === 'requisite') {
|
|
1048
|
+
fieldsEndpoint = 'crm.requisite.fields.json';
|
|
1049
|
+
}
|
|
1050
|
+
const fieldsResponse = await Helpers_1.bitrixRequestWithRetry.call(this, 'GET', fieldsEndpoint);
|
|
1051
|
+
const fieldsInfo = fieldsResponse.result;
|
|
1052
|
+
const fieldsCollection = this.getNodeParameter('fields.field', i, []);
|
|
1053
|
+
const enrichedFieldsCollection = fieldsCollection.map(field => {
|
|
1054
|
+
const fieldInfo = fieldsInfo[field.fieldName];
|
|
1055
|
+
let updatedFieldValueType = field.fieldValueType;
|
|
1056
|
+
if (fieldInfo && fieldInfo.type === 'enumeration') {
|
|
1057
|
+
updatedFieldValueType = 'enumeration';
|
|
1058
|
+
}
|
|
1059
|
+
return {
|
|
1060
|
+
...field,
|
|
1061
|
+
fieldValueType: updatedFieldValueType,
|
|
1062
|
+
resource: resource,
|
|
1063
|
+
field: fieldInfo,
|
|
1064
|
+
};
|
|
1065
|
+
});
|
|
1066
|
+
fields = (0, types_1.processFormFields)(enrichedFieldsCollection);
|
|
1067
|
+
}
|
|
1068
|
+
const body = { fields };
|
|
1069
|
+
// UX: Merge Top-Level Fields
|
|
1070
|
+
if (resource === 'quote') {
|
|
1071
|
+
const quoteSubject = this.getNodeParameter('quoteSubject', i, '');
|
|
1072
|
+
if (quoteSubject)
|
|
1073
|
+
fields['TITLE'] = quoteSubject;
|
|
1074
|
+
if (operation === 'create') {
|
|
1075
|
+
const dealId = this.getNodeParameter('dealId', i, '');
|
|
1076
|
+
if (dealId)
|
|
1077
|
+
fields['DEAL_ID'] = dealId;
|
|
1078
|
+
const companyId = this.getNodeParameter('companyId', i, '');
|
|
1079
|
+
if (companyId)
|
|
1080
|
+
fields['COMPANY_ID'] = companyId;
|
|
1081
|
+
const contactId = this.getNodeParameter('contactId', i, '');
|
|
1082
|
+
if (contactId)
|
|
1083
|
+
fields['CONTACT_ID'] = contactId;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
const title = this.getNodeParameter('title', i, '');
|
|
1087
|
+
if (title)
|
|
1088
|
+
fields['TITLE'] = title;
|
|
1089
|
+
const assignedById = this.getNodeParameter('assignedById', i, '');
|
|
1090
|
+
if (assignedById)
|
|
1091
|
+
fields['ASSIGNED_BY_ID'] = assignedById;
|
|
1092
|
+
const statusId = this.getNodeParameter('statusId', i, '');
|
|
1093
|
+
if (statusId)
|
|
1094
|
+
fields['STATUS_ID'] = statusId;
|
|
1095
|
+
const categoryId = this.getNodeParameter('categoryId', i, '');
|
|
1096
|
+
if (categoryId && categoryId !== '0')
|
|
1097
|
+
fields['CATEGORY_ID'] = categoryId;
|
|
1098
|
+
const stageId = this.getNodeParameter('stageId', i, '');
|
|
1099
|
+
if (stageId)
|
|
1100
|
+
fields['STAGE_ID'] = stageId;
|
|
1101
|
+
// Standard 2026: SPA requires entityTypeId
|
|
1102
|
+
if (resource === 'smart_process') {
|
|
1103
|
+
const smartProcessId = this.getNodeParameter('smartProcessId', i);
|
|
1104
|
+
body.entityTypeId = smartProcessId;
|
|
1105
|
+
}
|
|
1106
|
+
if (operation === 'update') {
|
|
1107
|
+
body.id = this.getNodeParameter('id', i);
|
|
1108
|
+
}
|
|
1109
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', endpoint, body);
|
|
1110
|
+
// Standard 2026: Direct Entity Link
|
|
1111
|
+
const result = response;
|
|
1112
|
+
if (resource !== 'requisite' && resource !== 'smart_process' && resource !== 'other') {
|
|
1113
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
1114
|
+
const domain = credentials?.webhookUrl?.split('/rest')[0];
|
|
1115
|
+
// Construct URL: https://portal.bitrix24.com/crm/lead/details/123/
|
|
1116
|
+
if (domain && (result.result || body.id)) {
|
|
1117
|
+
const id = result.result || body.id;
|
|
1118
|
+
result.url = `${domain}/crm/${resource}/details/${id}/`;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
// SPA Link logic is complex (depends on routing), skipping for now to avoid broken links
|
|
1122
|
+
returnData.push({
|
|
1123
|
+
json: result,
|
|
1124
|
+
pairedItem: { item: i },
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
// Standard 2026: Raw API Request Mode
|
|
1128
|
+
if (operation === 'raw') {
|
|
1129
|
+
const method = this.getNodeParameter('method', i);
|
|
1130
|
+
// Remove 'crm.' prefix if user typed it, or assume endpoint is full method name like 'crm.lead.add'
|
|
1131
|
+
// The helper appends base URL. Endpoint should be 'crm.lead.add.json' or 'crm.lead.add'
|
|
1132
|
+
let rawEndpoint = this.getNodeParameter('endpoint', i);
|
|
1133
|
+
if (!rawEndpoint.endsWith('.json'))
|
|
1134
|
+
rawEndpoint += '.json';
|
|
1135
|
+
const rawBody = this.getNodeParameter('jsonBody', i);
|
|
1136
|
+
let body = {};
|
|
1137
|
+
if (rawBody) {
|
|
1138
|
+
try {
|
|
1139
|
+
body = JSON.parse(rawBody);
|
|
1140
|
+
}
|
|
1141
|
+
catch (e) {
|
|
1142
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid JSON Body', { itemIndex: i });
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, method, rawEndpoint, body);
|
|
1146
|
+
returnData.push({
|
|
1147
|
+
json: response,
|
|
1148
|
+
pairedItem: { item: i },
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
if (operation === 'get') {
|
|
1152
|
+
const getBy = this.getNodeParameter('getBy', i);
|
|
1153
|
+
const selectFields = this.getNodeParameter('selectFields', i, []);
|
|
1154
|
+
const params = {};
|
|
1155
|
+
if (selectFields.length > 0) {
|
|
1156
|
+
params.select = selectFields;
|
|
1157
|
+
}
|
|
1158
|
+
else {
|
|
1159
|
+
let defaults = [];
|
|
1160
|
+
switch (resource) {
|
|
1161
|
+
case Lead_1.Lead.resource:
|
|
1162
|
+
defaults = Lead_1.Lead.getDefaultFields();
|
|
1163
|
+
break;
|
|
1164
|
+
case Deal_1.Deal.resource:
|
|
1165
|
+
defaults = Deal_1.Deal.getDefaultFields();
|
|
1166
|
+
break;
|
|
1167
|
+
case Contact_1.Contact.resource:
|
|
1168
|
+
defaults = Contact_1.Contact.getDefaultFields();
|
|
1169
|
+
break;
|
|
1170
|
+
case Company_1.Company.resource:
|
|
1171
|
+
defaults = Company_1.Company.getDefaultFields();
|
|
1172
|
+
break;
|
|
1173
|
+
}
|
|
1174
|
+
if (defaults.length)
|
|
1175
|
+
params.select = defaults;
|
|
1176
|
+
}
|
|
1177
|
+
let endpoint = `crm.${resource}.list.json`;
|
|
1178
|
+
// Standard 2026: SPA Logic
|
|
1179
|
+
if (resource === 'smart_process') {
|
|
1180
|
+
endpoint = 'crm.item.list.json';
|
|
1181
|
+
const smartProcessId = this.getNodeParameter('smartProcessId', i);
|
|
1182
|
+
params.entityTypeId = smartProcessId;
|
|
1183
|
+
}
|
|
1184
|
+
// Standard 2026: Requisite Logic
|
|
1185
|
+
if (resource === 'requisite') {
|
|
1186
|
+
endpoint = 'crm.requisite.list.json';
|
|
1187
|
+
}
|
|
1188
|
+
if (getBy === 'id') {
|
|
1189
|
+
const idInput = this.getNodeParameter('id', i);
|
|
1190
|
+
// Standard 2026: Bulk ID Input
|
|
1191
|
+
const ids = idInput.split(',').map(id => id.trim()).filter(id => id);
|
|
1192
|
+
if (ids.length > 1) {
|
|
1193
|
+
params.filter = { 'ID': ids }; // Bitrix supports array in filter
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
params.filter = { 'ID': ids[0] };
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
else {
|
|
1200
|
+
const filterFields = this.getNodeParameter('filterFields.field', i, []);
|
|
1201
|
+
if (filterFields.length > 0) {
|
|
1202
|
+
const filter = {};
|
|
1203
|
+
for (const field of filterFields) {
|
|
1204
|
+
let value = field.value;
|
|
1205
|
+
if (field.operation === '@' || field.operation === '!@') {
|
|
1206
|
+
value = value.split(',').map(item => item.trim());
|
|
1207
|
+
}
|
|
1208
|
+
if (field.operation === 'equals') {
|
|
1209
|
+
filter[field.fieldName] = value;
|
|
1210
|
+
}
|
|
1211
|
+
else {
|
|
1212
|
+
filter[field.operation + field.fieldName] = value;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
params.filter = filter;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', endpoint, params);
|
|
1219
|
+
const results = response.result; // Bitrix returns array for list/get calls
|
|
1220
|
+
if (results && Array.isArray(results) && results.length > 0) {
|
|
1221
|
+
for (const item of results) {
|
|
1222
|
+
// Standard 2026: Direct Entity Link
|
|
1223
|
+
if (resource !== 'requisite' && resource !== 'smart_process' && resource !== 'other') {
|
|
1224
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
1225
|
+
const domain = credentials?.webhookUrl?.split('/rest')[0];
|
|
1226
|
+
if (domain && item.ID) {
|
|
1227
|
+
item.url = `${domain}/crm/${resource}/details/${item.ID}/`;
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
returnData.push({
|
|
1231
|
+
json: item,
|
|
1232
|
+
pairedItem: { item: i },
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
else {
|
|
1237
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Record not found', { itemIndex: i });
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
if (operation === 'list') {
|
|
1241
|
+
const returnAll = this.getNodeParameter('returnAll', i);
|
|
1242
|
+
const selectFields = this.getNodeParameter('selectFields', i, []);
|
|
1243
|
+
const useFilter = this.getNodeParameter('useFilter', i);
|
|
1244
|
+
const body = {};
|
|
1245
|
+
if (selectFields.length > 0) {
|
|
1246
|
+
body.select = selectFields;
|
|
1247
|
+
}
|
|
1248
|
+
else {
|
|
1249
|
+
let defaults = [];
|
|
1250
|
+
switch (resource) {
|
|
1251
|
+
case Lead_1.Lead.resource:
|
|
1252
|
+
defaults = Lead_1.Lead.getDefaultFields();
|
|
1253
|
+
break;
|
|
1254
|
+
case Deal_1.Deal.resource:
|
|
1255
|
+
defaults = Deal_1.Deal.getDefaultFields();
|
|
1256
|
+
break;
|
|
1257
|
+
case Contact_1.Contact.resource:
|
|
1258
|
+
defaults = Contact_1.Contact.getDefaultFields();
|
|
1259
|
+
break;
|
|
1260
|
+
case Company_1.Company.resource:
|
|
1261
|
+
defaults = Company_1.Company.getDefaultFields();
|
|
1262
|
+
break;
|
|
1263
|
+
}
|
|
1264
|
+
if (defaults.length)
|
|
1265
|
+
body.select = defaults;
|
|
1266
|
+
}
|
|
1267
|
+
let endpoint = `crm.${resource}.list.json`;
|
|
1268
|
+
// Standard 2026: SPA Logic
|
|
1269
|
+
if (resource === 'smart_process') {
|
|
1270
|
+
endpoint = 'crm.item.list.json';
|
|
1271
|
+
const smartProcessId = this.getNodeParameter('smartProcessId', i);
|
|
1272
|
+
body.entityTypeId = smartProcessId;
|
|
1273
|
+
}
|
|
1274
|
+
// Standard 2026: Requisite Logic
|
|
1275
|
+
if (resource === 'requisite') {
|
|
1276
|
+
endpoint = 'crm.requisite.list.json';
|
|
1277
|
+
}
|
|
1278
|
+
if (useFilter) {
|
|
1279
|
+
const filterFields = this.getNodeParameter('filterFields.field', i, []);
|
|
1280
|
+
if (filterFields.length > 0) {
|
|
1281
|
+
const filter = {};
|
|
1282
|
+
for (const field of filterFields) {
|
|
1283
|
+
let value = field.value;
|
|
1284
|
+
if (field.operation === '@' || field.operation === '!@') {
|
|
1285
|
+
value = value.split(',').map(item => item.trim());
|
|
1286
|
+
}
|
|
1287
|
+
if (field.operation === 'equals') {
|
|
1288
|
+
filter[field.fieldName] = value;
|
|
1289
|
+
}
|
|
1290
|
+
else {
|
|
1291
|
+
filter[field.operation + field.fieldName] = value;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
body.filter = filter;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
const limit = returnAll ? 100000 : this.getNodeParameter('limit', i);
|
|
1298
|
+
if (returnAll) {
|
|
1299
|
+
let start = 0;
|
|
1300
|
+
let hasMore = true;
|
|
1301
|
+
// Standard 2026: Auto-Pagination Guard
|
|
1302
|
+
// Prevent infinite loops or OOM by limiting total pages
|
|
1303
|
+
let pageCount = 0;
|
|
1304
|
+
const MAX_PAGES = 500; // Limit to ~25,000 items per execution to be safe
|
|
1305
|
+
while (hasMore) {
|
|
1306
|
+
if (pageCount >= MAX_PAGES) {
|
|
1307
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Auto-Pagination Guard: Stopped after ${MAX_PAGES} pages (~25k items) to prevent memory crash. Please use 'Limit' or split your workflow.`);
|
|
1308
|
+
}
|
|
1309
|
+
pageCount++;
|
|
1310
|
+
body.start = start;
|
|
1311
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', endpoint, body);
|
|
1312
|
+
const results = response.result;
|
|
1313
|
+
if (!results || results.length === 0) {
|
|
1314
|
+
hasMore = false;
|
|
1315
|
+
}
|
|
1316
|
+
else {
|
|
1317
|
+
for (const item of results) {
|
|
1318
|
+
// Standard 2026: Direct Entity Link
|
|
1319
|
+
if (resource !== 'requisite' && resource !== 'smart_process' && resource !== 'other') {
|
|
1320
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
1321
|
+
const domain = credentials?.webhookUrl?.split('/rest')[0];
|
|
1322
|
+
if (domain && item.ID) {
|
|
1323
|
+
item.url = `${domain}/crm/${resource}/details/${item.ID}/`;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
returnData.push({
|
|
1327
|
+
json: item,
|
|
1328
|
+
pairedItem: { item: i },
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
start += results.length;
|
|
1332
|
+
if (results.length < 50)
|
|
1333
|
+
hasMore = false;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
else {
|
|
1338
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', endpoint, body);
|
|
1339
|
+
const results = response.result;
|
|
1340
|
+
if (results) {
|
|
1341
|
+
for (let j = 0; j < results.length && j < limit; j++) {
|
|
1342
|
+
const item = results[j];
|
|
1343
|
+
// Standard 2026: Direct Entity Link
|
|
1344
|
+
if (resource !== 'requisite' && resource !== 'smart_process' && resource !== 'other') {
|
|
1345
|
+
const credentials = await this.getCredentials('bitrix24Api');
|
|
1346
|
+
const domain = credentials?.webhookUrl?.split('/rest')[0];
|
|
1347
|
+
if (domain && item.ID) {
|
|
1348
|
+
item.url = `${domain}/crm/${resource}/details/${item.ID}/`;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
returnData.push({
|
|
1352
|
+
json: item,
|
|
1353
|
+
pairedItem: { item: i },
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
if (operation === 'delete') {
|
|
1360
|
+
const id = this.getNodeParameter('id', i);
|
|
1361
|
+
let endpoint = `crm.${resource}.delete.json`;
|
|
1362
|
+
const body = { id };
|
|
1363
|
+
// Standard 2026: SPA Logic
|
|
1364
|
+
if (resource === 'smart_process') {
|
|
1365
|
+
endpoint = 'crm.item.delete.json';
|
|
1366
|
+
const smartProcessId = this.getNodeParameter('smartProcessId', i);
|
|
1367
|
+
body.entityTypeId = smartProcessId;
|
|
1368
|
+
}
|
|
1369
|
+
// Standard 2026: Requisite Logic
|
|
1370
|
+
if (resource === 'requisite') {
|
|
1371
|
+
endpoint = 'crm.requisite.delete.json';
|
|
1372
|
+
}
|
|
1373
|
+
const response = await Helpers_1.bitrixRequestWithRetry.call(this, 'POST', endpoint, body);
|
|
1374
|
+
returnData.push({
|
|
1375
|
+
json: { success: true, id, result: response.result },
|
|
1376
|
+
pairedItem: { item: i },
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
catch (error) {
|
|
1381
|
+
if (this.continueOnFail()) {
|
|
1382
|
+
returnData.push({
|
|
1383
|
+
json: { error: error.message },
|
|
1384
|
+
pairedItem: { item: i },
|
|
1385
|
+
});
|
|
1386
|
+
continue;
|
|
1387
|
+
}
|
|
1388
|
+
throw error;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
returnData.forEach(item => {
|
|
1392
|
+
const pairedItem = item.pairedItem;
|
|
1393
|
+
const index = (pairedItem && typeof pairedItem === 'object' && 'item' in pairedItem) ? pairedItem.item : 0;
|
|
1394
|
+
if (this.getNodeParameter('compactMode', index, false)) {
|
|
1395
|
+
const json = item.json;
|
|
1396
|
+
Object.keys(json).forEach(key => {
|
|
1397
|
+
if (json[key] === null || json[key] === '' || (Array.isArray(json[key]) && json[key].length === 0)) {
|
|
1398
|
+
delete json[key];
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
return [returnData];
|
|
1404
|
+
}
|
|
1405
|
+
catch (error) {
|
|
1406
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
exports.Bitrix24 = Bitrix24;
|