n8n-nodes-confirm8 0.21.0 → 0.23.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.
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from "n8n-workflow";
|
|
2
2
|
export declare class Confirm8AgentTool implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
4
|
/**
|
|
5
5
|
* Parse natural date queries into filter JSON
|
|
6
6
|
*/
|
|
7
7
|
private parseDateQuery;
|
|
8
|
+
/**
|
|
9
|
+
* Validate ISO date string yyyy-mm-dd
|
|
10
|
+
*/
|
|
11
|
+
private isIsoDate;
|
|
12
|
+
/**
|
|
13
|
+
* Enforce date filters format when present
|
|
14
|
+
*/
|
|
15
|
+
private validateDateFilters;
|
|
8
16
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
9
17
|
}
|
|
@@ -5,107 +5,180 @@ const n8n_workflow_1 = require("n8n-workflow");
|
|
|
5
5
|
class Confirm8AgentTool {
|
|
6
6
|
constructor() {
|
|
7
7
|
this.description = {
|
|
8
|
-
displayName:
|
|
9
|
-
name:
|
|
10
|
-
icon:
|
|
11
|
-
group: [
|
|
8
|
+
displayName: "Confirm8 AI Tool",
|
|
9
|
+
name: "confirm8AgentTool",
|
|
10
|
+
icon: "file:tool.svg",
|
|
11
|
+
group: ["transform"],
|
|
12
12
|
version: 1,
|
|
13
|
-
description:
|
|
13
|
+
description: `AI tool for Confirm8 (STRICT).
|
|
14
|
+
|
|
15
|
+
CRITICAL FOR AGENTS:
|
|
16
|
+
- "resource" MUST be exactly one of: user, client, item, itemType, task, service, product, order, modality, ticket, property
|
|
17
|
+
- "operation" MUST be exactly one of: getAll, get, create, update, activate, deactivate
|
|
18
|
+
- Use ONLY these tokens. Do NOT use labels like "OS", "Ordem de Serviço", "buscar".
|
|
19
|
+
- For OS/ordem de serviço => resource="order"
|
|
20
|
+
- To list/search => operation="getAll"
|
|
21
|
+
- Date filters MUST be ISO yyyy-mm-dd.`,
|
|
14
22
|
defaults: {
|
|
15
|
-
name:
|
|
23
|
+
name: "Confirm8 AI Tool",
|
|
16
24
|
},
|
|
17
25
|
usableAsTool: true,
|
|
18
|
-
inputs: [
|
|
19
|
-
outputs: [
|
|
26
|
+
inputs: ["main"],
|
|
27
|
+
outputs: ["main"],
|
|
20
28
|
properties: [
|
|
21
29
|
// API Configuration
|
|
22
30
|
{
|
|
23
|
-
displayName:
|
|
24
|
-
name:
|
|
25
|
-
type:
|
|
26
|
-
default:
|
|
27
|
-
placeholder:
|
|
31
|
+
displayName: "Base URL",
|
|
32
|
+
name: "baseUrl",
|
|
33
|
+
type: "string",
|
|
34
|
+
default: "",
|
|
35
|
+
placeholder: "https://api.confirm8.com",
|
|
28
36
|
required: true,
|
|
29
37
|
},
|
|
30
38
|
{
|
|
31
|
-
displayName:
|
|
32
|
-
name:
|
|
33
|
-
type:
|
|
39
|
+
displayName: "Bearer Token",
|
|
40
|
+
name: "bearerToken",
|
|
41
|
+
type: "string",
|
|
34
42
|
typeOptions: { password: true },
|
|
35
|
-
default:
|
|
43
|
+
default: "",
|
|
36
44
|
required: true,
|
|
37
45
|
},
|
|
38
46
|
{
|
|
39
|
-
displayName:
|
|
40
|
-
name:
|
|
41
|
-
type:
|
|
42
|
-
default:
|
|
47
|
+
displayName: "X-API-DOMAIN",
|
|
48
|
+
name: "apiDomain",
|
|
49
|
+
type: "string",
|
|
50
|
+
default: "",
|
|
43
51
|
required: true,
|
|
44
52
|
},
|
|
45
53
|
{
|
|
46
|
-
displayName:
|
|
47
|
-
name:
|
|
48
|
-
type:
|
|
54
|
+
displayName: "X-APIKEY-TOKEN",
|
|
55
|
+
name: "apiKeyToken",
|
|
56
|
+
type: "string",
|
|
49
57
|
typeOptions: { password: true },
|
|
50
|
-
default:
|
|
58
|
+
default: "",
|
|
51
59
|
required: true,
|
|
52
60
|
},
|
|
53
61
|
// Tool parameters
|
|
54
62
|
{
|
|
55
|
-
displayName:
|
|
56
|
-
name:
|
|
57
|
-
type:
|
|
63
|
+
displayName: "Resource",
|
|
64
|
+
name: "resource",
|
|
65
|
+
type: "options",
|
|
58
66
|
options: [
|
|
59
|
-
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{ name:
|
|
67
|
+
{
|
|
68
|
+
name: "user",
|
|
69
|
+
value: "user",
|
|
70
|
+
description: "Users/Employees/Funcionários",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "client",
|
|
74
|
+
value: "client",
|
|
75
|
+
description: "Clients/Customers/Clientes",
|
|
76
|
+
},
|
|
77
|
+
{ name: "item", value: "item", description: "Items/Itens" },
|
|
78
|
+
{
|
|
79
|
+
name: "itemType",
|
|
80
|
+
value: "itemType",
|
|
81
|
+
description: "Item Types/Tipos",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "task",
|
|
85
|
+
value: "task",
|
|
86
|
+
description: "Tasks/Tarefas/Checklists",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "service",
|
|
90
|
+
value: "service",
|
|
91
|
+
description: "Services/Serviços",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "product",
|
|
95
|
+
value: "product",
|
|
96
|
+
description: "Products/Produtos",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "order",
|
|
100
|
+
value: "order",
|
|
101
|
+
description: "Work Orders/OS/Ordens de Serviço/WOS",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "modality",
|
|
105
|
+
value: "modality",
|
|
106
|
+
description: "Modalities/Modalidades",
|
|
107
|
+
},
|
|
108
|
+
{ name: "ticket", value: "ticket", description: "Tickets/Chamados" },
|
|
109
|
+
{
|
|
110
|
+
name: "property",
|
|
111
|
+
value: "property",
|
|
112
|
+
description: "Properties/Propriedades",
|
|
113
|
+
},
|
|
70
114
|
],
|
|
71
|
-
default:
|
|
72
|
-
description:
|
|
115
|
+
default: "user",
|
|
116
|
+
description: `CRITICAL (Agents): Resource MUST be EXACTLY one of: user, client, item, itemType, task, service, product, order, modality, ticket, property.
|
|
117
|
+
Use ONLY the value token (example: order), never labels like OS.`,
|
|
73
118
|
},
|
|
74
119
|
{
|
|
75
|
-
displayName:
|
|
76
|
-
name:
|
|
77
|
-
type:
|
|
120
|
+
displayName: "Operation",
|
|
121
|
+
name: "operation",
|
|
122
|
+
type: "options",
|
|
78
123
|
options: [
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
{
|
|
124
|
+
{
|
|
125
|
+
name: "getAll",
|
|
126
|
+
value: "getAll",
|
|
127
|
+
description: "List/Listar/Buscar todos/Mostrar todos",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: "get",
|
|
131
|
+
value: "get",
|
|
132
|
+
description: "Get one/Buscar um/Obter",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "create",
|
|
136
|
+
value: "create",
|
|
137
|
+
description: "Create/Criar/Adicionar",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "update",
|
|
141
|
+
value: "update",
|
|
142
|
+
description: "Update/Atualizar/Modificar",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "activate",
|
|
146
|
+
value: "activate",
|
|
147
|
+
description: "Activate/Ativar",
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "deactivate",
|
|
151
|
+
value: "deactivate",
|
|
152
|
+
description: "Deactivate/Desativar",
|
|
153
|
+
},
|
|
85
154
|
],
|
|
86
|
-
default:
|
|
87
|
-
description:
|
|
155
|
+
default: "getAll",
|
|
156
|
+
description: `CRITICAL (Agents): Operation MUST be EXACTLY one of: getAll, get, create, update, activate, deactivate.
|
|
157
|
+
Use ONLY the value token (example: getAll), never labels like buscar.`,
|
|
88
158
|
},
|
|
89
159
|
{
|
|
90
|
-
displayName:
|
|
91
|
-
name:
|
|
92
|
-
type:
|
|
93
|
-
default:
|
|
94
|
-
description:
|
|
160
|
+
displayName: "Record ID",
|
|
161
|
+
name: "recordId",
|
|
162
|
+
type: "string",
|
|
163
|
+
default: "",
|
|
164
|
+
description: "Record ID (only for get/update/activate/deactivate)",
|
|
95
165
|
},
|
|
96
166
|
{
|
|
97
|
-
displayName:
|
|
98
|
-
name:
|
|
99
|
-
type:
|
|
100
|
-
default:
|
|
101
|
-
description:
|
|
167
|
+
displayName: "Data",
|
|
168
|
+
name: "data",
|
|
169
|
+
type: "string",
|
|
170
|
+
default: "",
|
|
171
|
+
description: "JSON data (only for create/update)",
|
|
102
172
|
},
|
|
103
173
|
{
|
|
104
|
-
displayName:
|
|
105
|
-
name:
|
|
106
|
-
type:
|
|
107
|
-
default:
|
|
108
|
-
description:
|
|
174
|
+
displayName: "Filters",
|
|
175
|
+
name: "filters",
|
|
176
|
+
type: "string",
|
|
177
|
+
default: "",
|
|
178
|
+
description: `Filters as JSON ONLY.
|
|
179
|
+
Dates MUST be ISO yyyy-mm-dd.
|
|
180
|
+
Example (this week): {"start_date":{"gte":"2025-06-16"},"end_date":{"lte":"2025-06-22"}}
|
|
181
|
+
Do NOT send expressions like "data >= start_of_week".`,
|
|
109
182
|
},
|
|
110
183
|
],
|
|
111
184
|
};
|
|
@@ -119,19 +192,19 @@ class Confirm8AgentTool {
|
|
|
119
192
|
query = query.toLowerCase().trim();
|
|
120
193
|
// Helper to format date as YYYY-MM-DD
|
|
121
194
|
const formatDate = (date) => {
|
|
122
|
-
return date.toISOString().split(
|
|
195
|
+
return date.toISOString().split("T")[0];
|
|
123
196
|
};
|
|
124
197
|
// Today
|
|
125
|
-
if (query.includes(
|
|
198
|
+
if (query.includes("hoje") || query.includes("today")) {
|
|
126
199
|
const endOfDay = new Date(today);
|
|
127
200
|
endOfDay.setHours(23, 59, 59, 999);
|
|
128
201
|
return {
|
|
129
202
|
start_date: { gte: formatDate(today) },
|
|
130
|
-
end_date: { lte: formatDate(endOfDay) }
|
|
203
|
+
end_date: { lte: formatDate(endOfDay) },
|
|
131
204
|
};
|
|
132
205
|
}
|
|
133
206
|
// This week / semana atual
|
|
134
|
-
if (query.includes(
|
|
207
|
+
if (query.includes("semana") || query.includes("week")) {
|
|
135
208
|
const dayOfWeek = today.getDay();
|
|
136
209
|
const diff = dayOfWeek === 0 ? -6 : 1 - dayOfWeek; // Monday is start
|
|
137
210
|
const weekStart = new Date(today);
|
|
@@ -140,16 +213,18 @@ class Confirm8AgentTool {
|
|
|
140
213
|
weekEnd.setDate(weekStart.getDate() + 6);
|
|
141
214
|
return {
|
|
142
215
|
start_date: { gte: formatDate(weekStart) },
|
|
143
|
-
end_date: { lte: formatDate(weekEnd) }
|
|
216
|
+
end_date: { lte: formatDate(weekEnd) },
|
|
144
217
|
};
|
|
145
218
|
}
|
|
146
219
|
// This month / mês atual
|
|
147
|
-
if (query.includes(
|
|
220
|
+
if (query.includes("mês") ||
|
|
221
|
+
query.includes("mes") ||
|
|
222
|
+
query.includes("month")) {
|
|
148
223
|
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
149
224
|
const monthEnd = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
|
150
225
|
return {
|
|
151
226
|
start_date: { gte: formatDate(monthStart) },
|
|
152
|
-
end_date: { lte: formatDate(monthEnd) }
|
|
227
|
+
end_date: { lte: formatDate(monthEnd) },
|
|
153
228
|
};
|
|
154
229
|
}
|
|
155
230
|
// Last N days
|
|
@@ -160,7 +235,7 @@ class Confirm8AgentTool {
|
|
|
160
235
|
startDate.setDate(today.getDate() - days);
|
|
161
236
|
return {
|
|
162
237
|
start_date: { gte: formatDate(startDate) },
|
|
163
|
-
end_date: { lte: formatDate(today) }
|
|
238
|
+
end_date: { lte: formatDate(today) },
|
|
164
239
|
};
|
|
165
240
|
}
|
|
166
241
|
// Next N days
|
|
@@ -171,26 +246,56 @@ class Confirm8AgentTool {
|
|
|
171
246
|
endDate.setDate(today.getDate() + days);
|
|
172
247
|
return {
|
|
173
248
|
start_date: { gte: formatDate(today) },
|
|
174
|
-
end_date: { lte: formatDate(endDate) }
|
|
249
|
+
end_date: { lte: formatDate(endDate) },
|
|
175
250
|
};
|
|
176
251
|
}
|
|
177
252
|
return null;
|
|
178
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Validate ISO date string yyyy-mm-dd
|
|
256
|
+
*/
|
|
257
|
+
isIsoDate(value) {
|
|
258
|
+
if (typeof value !== "string")
|
|
259
|
+
return false;
|
|
260
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(value);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Enforce date filters format when present
|
|
264
|
+
*/
|
|
265
|
+
validateDateFilters(filters) {
|
|
266
|
+
const dateFields = ["start_date", "end_date", "date", "data"];
|
|
267
|
+
for (const field of dateFields) {
|
|
268
|
+
if (!filters[field])
|
|
269
|
+
continue;
|
|
270
|
+
const ops = filters[field];
|
|
271
|
+
if (!ops || typeof ops !== "object")
|
|
272
|
+
continue;
|
|
273
|
+
for (const op of Object.keys(ops)) {
|
|
274
|
+
const v = ops[op];
|
|
275
|
+
if (v == null)
|
|
276
|
+
continue;
|
|
277
|
+
if (!this.isIsoDate(v)) {
|
|
278
|
+
throw new Error(`Invalid date format in filters["${field}"]["${op}"]="${String(v)}". ` +
|
|
279
|
+
`Dates MUST be yyyy-mm-dd (ISO), e.g. "2025-06-16".`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
179
284
|
async execute() {
|
|
180
285
|
const items = this.getInputData();
|
|
181
286
|
const returnData = [];
|
|
182
287
|
for (let i = 0; i < items.length; i++) {
|
|
183
288
|
try {
|
|
184
|
-
const baseUrl = this.getNodeParameter(
|
|
185
|
-
const bearerToken = this.getNodeParameter(
|
|
186
|
-
const apiDomain = this.getNodeParameter(
|
|
187
|
-
const apiKeyToken = this.getNodeParameter(
|
|
188
|
-
let resource = this.getNodeParameter(
|
|
189
|
-
let operation = this.getNodeParameter(
|
|
190
|
-
const recordId = this.getNodeParameter(
|
|
289
|
+
const baseUrl = this.getNodeParameter("baseUrl", i);
|
|
290
|
+
const bearerToken = this.getNodeParameter("bearerToken", i);
|
|
291
|
+
const apiDomain = this.getNodeParameter("apiDomain", i);
|
|
292
|
+
const apiKeyToken = this.getNodeParameter("apiKeyToken", i);
|
|
293
|
+
let resource = this.getNodeParameter("resource", i, "");
|
|
294
|
+
let operation = this.getNodeParameter("operation", i, "");
|
|
295
|
+
const recordId = this.getNodeParameter("recordId", i, "");
|
|
191
296
|
// Parse data
|
|
192
297
|
let data = {};
|
|
193
|
-
const dataParam = this.getNodeParameter(
|
|
298
|
+
const dataParam = this.getNodeParameter("data", i, "");
|
|
194
299
|
if (dataParam) {
|
|
195
300
|
try {
|
|
196
301
|
data = JSON.parse(dataParam);
|
|
@@ -201,7 +306,7 @@ class Confirm8AgentTool {
|
|
|
201
306
|
}
|
|
202
307
|
// Parse filters
|
|
203
308
|
let filters = {};
|
|
204
|
-
const filtersParam = this.getNodeParameter(
|
|
309
|
+
const filtersParam = this.getNodeParameter("filters", i, "");
|
|
205
310
|
if (filtersParam) {
|
|
206
311
|
try {
|
|
207
312
|
// Try to parse as JSON first
|
|
@@ -214,201 +319,309 @@ class Confirm8AgentTool {
|
|
|
214
319
|
filters = parsedDate;
|
|
215
320
|
}
|
|
216
321
|
}
|
|
322
|
+
// Enforce ISO date filters when present
|
|
323
|
+
this.validateDateFilters(filters);
|
|
217
324
|
}
|
|
218
325
|
// Aggressive normalization - EXPAND THIS
|
|
219
326
|
const resourceMap = {
|
|
220
327
|
// Standard
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
328
|
+
users: "user",
|
|
329
|
+
usuarios: "user",
|
|
330
|
+
usuários: "user",
|
|
331
|
+
employees: "user",
|
|
332
|
+
funcionários: "user",
|
|
333
|
+
funcionarios: "user",
|
|
334
|
+
clients: "client",
|
|
335
|
+
clientes: "client",
|
|
336
|
+
customers: "client",
|
|
337
|
+
items: "item",
|
|
338
|
+
itens: "item",
|
|
339
|
+
itemtypes: "itemType",
|
|
340
|
+
tipos: "itemType",
|
|
341
|
+
tasks: "task",
|
|
342
|
+
tarefas: "task",
|
|
343
|
+
services: "service",
|
|
344
|
+
serviços: "service",
|
|
345
|
+
servicos: "service",
|
|
346
|
+
products: "product",
|
|
347
|
+
produtos: "product",
|
|
348
|
+
modalities: "modality",
|
|
349
|
+
modalidades: "modality",
|
|
350
|
+
tickets: "ticket",
|
|
351
|
+
chamados: "ticket",
|
|
352
|
+
properties: "property",
|
|
353
|
+
propriedades: "property",
|
|
231
354
|
// CRITICAL: OS mappings
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
355
|
+
os: "order",
|
|
356
|
+
"o.s": "order",
|
|
357
|
+
"o.s.": "order",
|
|
358
|
+
orders: "order",
|
|
359
|
+
ordens: "order",
|
|
360
|
+
ordem: "order",
|
|
361
|
+
"ordem de serviço": "order",
|
|
362
|
+
"ordem de servico": "order",
|
|
363
|
+
"ordens de serviço": "order",
|
|
364
|
+
"ordens de servico": "order",
|
|
365
|
+
wos: "order",
|
|
366
|
+
"work order": "order",
|
|
367
|
+
"work orders": "order",
|
|
368
|
+
pedidos: "order",
|
|
369
|
+
pedido: "order",
|
|
247
370
|
};
|
|
248
371
|
const operationMap = {
|
|
249
372
|
// List/Get All
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
373
|
+
list: "getAll",
|
|
374
|
+
listar: "getAll",
|
|
375
|
+
mostrar: "getAll",
|
|
376
|
+
buscar: "getAll",
|
|
377
|
+
busque: "getAll",
|
|
378
|
+
"buscar todos": "getAll",
|
|
379
|
+
"buscar todas": "getAll",
|
|
380
|
+
"buscar todo": "getAll",
|
|
381
|
+
"buscar toda": "getAll",
|
|
382
|
+
"get all": "getAll",
|
|
383
|
+
"show all": "getAll",
|
|
384
|
+
"list all": "getAll",
|
|
385
|
+
todos: "getAll",
|
|
386
|
+
todas: "getAll",
|
|
387
|
+
"obter todos": "getAll",
|
|
388
|
+
"obter todas": "getAll",
|
|
389
|
+
"pegar todos": "getAll",
|
|
390
|
+
"pegar todas": "getAll",
|
|
268
391
|
// Get Single
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
392
|
+
obter: "get",
|
|
393
|
+
pegar: "get",
|
|
394
|
+
ver: "get",
|
|
395
|
+
visualizar: "get",
|
|
273
396
|
// Create
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
397
|
+
criar: "create",
|
|
398
|
+
adicionar: "create",
|
|
399
|
+
add: "create",
|
|
400
|
+
novo: "create",
|
|
401
|
+
nova: "create",
|
|
402
|
+
new: "create",
|
|
280
403
|
// Update
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
404
|
+
atualizar: "update",
|
|
405
|
+
modificar: "update",
|
|
406
|
+
modify: "update",
|
|
407
|
+
editar: "update",
|
|
408
|
+
edit: "update",
|
|
286
409
|
// Activate/Deactivate
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
410
|
+
ativar: "activate",
|
|
411
|
+
enable: "activate",
|
|
412
|
+
habilitar: "activate",
|
|
413
|
+
desativar: "deactivate",
|
|
414
|
+
disable: "deactivate",
|
|
415
|
+
desabilitar: "deactivate",
|
|
293
416
|
};
|
|
294
|
-
// Normalize - clean and map
|
|
295
|
-
const
|
|
296
|
-
|
|
417
|
+
// Normalize - clean and map (remove accents/punctuation)
|
|
418
|
+
const normalizeKey = (value) => value
|
|
419
|
+
.toLowerCase()
|
|
420
|
+
.normalize("NFD")
|
|
421
|
+
.replace(/\p{Diacritic}/gu, "")
|
|
422
|
+
.replace(/[^a-z0-9\s.\-_/]/g, " ")
|
|
423
|
+
.trim()
|
|
424
|
+
.replace(/\s+/g, " ");
|
|
425
|
+
const cleanResource = normalizeKey(resource);
|
|
426
|
+
const cleanOperation = normalizeKey(operation);
|
|
297
427
|
resource = resourceMap[cleanResource] || resource;
|
|
298
428
|
operation = operationMap[cleanOperation] || operation;
|
|
299
429
|
// If still not valid, throw clear error
|
|
300
|
-
const validResources = [
|
|
301
|
-
|
|
430
|
+
const validResources = [
|
|
431
|
+
"user",
|
|
432
|
+
"client",
|
|
433
|
+
"item",
|
|
434
|
+
"itemType",
|
|
435
|
+
"task",
|
|
436
|
+
"service",
|
|
437
|
+
"product",
|
|
438
|
+
"order",
|
|
439
|
+
"modality",
|
|
440
|
+
"ticket",
|
|
441
|
+
"property",
|
|
442
|
+
];
|
|
443
|
+
const validOperations = [
|
|
444
|
+
"getAll",
|
|
445
|
+
"get",
|
|
446
|
+
"create",
|
|
447
|
+
"update",
|
|
448
|
+
"activate",
|
|
449
|
+
"deactivate",
|
|
450
|
+
];
|
|
302
451
|
if (!validResources.includes(resource)) {
|
|
303
|
-
throw new Error(`Invalid resource: "${resource}". Must be one of: ${validResources.join(
|
|
304
|
-
`For OS/Ordem de Serviço use "order".`);
|
|
452
|
+
throw new Error(`Invalid resource: "${resource}". Must be one of: ${validResources.join(", ")}. ` + `For OS/Ordem de Serviço use "order".`);
|
|
305
453
|
}
|
|
306
454
|
if (!validOperations.includes(operation)) {
|
|
307
|
-
throw new Error(`Invalid operation: "${operation}". Must be one of: ${validOperations.join(
|
|
308
|
-
`To list/search use "getAll".`);
|
|
455
|
+
throw new Error(`Invalid operation: "${operation}". Must be one of: ${validOperations.join(", ")}. ` + `To list/search use "getAll".`);
|
|
309
456
|
}
|
|
310
457
|
// Resource config with relations
|
|
311
458
|
const resourceConfig = {
|
|
312
459
|
user: {
|
|
313
|
-
endpoint:
|
|
314
|
-
relations: [
|
|
460
|
+
endpoint: "users",
|
|
461
|
+
relations: [
|
|
462
|
+
"clients",
|
|
463
|
+
"attachments",
|
|
464
|
+
"permissions",
|
|
465
|
+
"device",
|
|
466
|
+
"employee",
|
|
467
|
+
],
|
|
315
468
|
},
|
|
316
469
|
client: {
|
|
317
|
-
endpoint:
|
|
318
|
-
relations: [
|
|
470
|
+
endpoint: "clients",
|
|
471
|
+
relations: [
|
|
472
|
+
"wos",
|
|
473
|
+
"items",
|
|
474
|
+
"employees",
|
|
475
|
+
"headquarter",
|
|
476
|
+
"files",
|
|
477
|
+
"userGroup",
|
|
478
|
+
"properties",
|
|
479
|
+
],
|
|
319
480
|
},
|
|
320
481
|
item: {
|
|
321
|
-
endpoint:
|
|
322
|
-
relations: [
|
|
482
|
+
endpoint: "items",
|
|
483
|
+
relations: [
|
|
484
|
+
"client",
|
|
485
|
+
"item_type",
|
|
486
|
+
"properties",
|
|
487
|
+
"parent",
|
|
488
|
+
"children",
|
|
489
|
+
"collects",
|
|
490
|
+
"wos",
|
|
491
|
+
],
|
|
323
492
|
},
|
|
324
493
|
itemType: {
|
|
325
|
-
endpoint:
|
|
326
|
-
relations: [
|
|
494
|
+
endpoint: "itemTypes",
|
|
495
|
+
relations: ["properties"],
|
|
327
496
|
},
|
|
328
497
|
task: {
|
|
329
|
-
endpoint:
|
|
330
|
-
relations: [
|
|
498
|
+
endpoint: "tasks",
|
|
499
|
+
relations: ["itemType", "activities", "wos", "modalities"],
|
|
331
500
|
},
|
|
332
501
|
service: {
|
|
333
|
-
endpoint:
|
|
334
|
-
relations: [
|
|
502
|
+
endpoint: "services",
|
|
503
|
+
relations: ["task"],
|
|
335
504
|
},
|
|
336
505
|
product: {
|
|
337
|
-
endpoint:
|
|
338
|
-
relations: []
|
|
506
|
+
endpoint: "products",
|
|
507
|
+
relations: [],
|
|
339
508
|
},
|
|
340
509
|
order: {
|
|
341
|
-
endpoint:
|
|
342
|
-
relations: [
|
|
510
|
+
endpoint: "wos",
|
|
511
|
+
relations: [
|
|
512
|
+
"client",
|
|
513
|
+
"modalities",
|
|
514
|
+
"tasks",
|
|
515
|
+
"pivot_tasks",
|
|
516
|
+
"products",
|
|
517
|
+
"users",
|
|
518
|
+
"items",
|
|
519
|
+
"tickets",
|
|
520
|
+
"services",
|
|
521
|
+
"collects",
|
|
522
|
+
"attachments",
|
|
523
|
+
],
|
|
343
524
|
},
|
|
344
525
|
modality: {
|
|
345
|
-
endpoint:
|
|
346
|
-
relations: [
|
|
526
|
+
endpoint: "modalities",
|
|
527
|
+
relations: ["tasks"],
|
|
347
528
|
},
|
|
348
529
|
ticket: {
|
|
349
|
-
endpoint:
|
|
350
|
-
relations: [
|
|
530
|
+
endpoint: "tickets",
|
|
531
|
+
relations: [
|
|
532
|
+
"client",
|
|
533
|
+
"subject_category",
|
|
534
|
+
"category",
|
|
535
|
+
"status",
|
|
536
|
+
"attachments",
|
|
537
|
+
"item",
|
|
538
|
+
"owner",
|
|
539
|
+
"priority",
|
|
540
|
+
"users",
|
|
541
|
+
"orders",
|
|
542
|
+
"properties",
|
|
543
|
+
],
|
|
351
544
|
},
|
|
352
545
|
property: {
|
|
353
|
-
endpoint:
|
|
354
|
-
relations: []
|
|
546
|
+
endpoint: "properties",
|
|
547
|
+
relations: [],
|
|
355
548
|
},
|
|
356
549
|
};
|
|
357
550
|
const config = resourceConfig[resource];
|
|
358
551
|
const baseEndpoint = config.endpoint;
|
|
359
|
-
let endpoint =
|
|
360
|
-
let method =
|
|
552
|
+
let endpoint = "";
|
|
553
|
+
let method = "GET";
|
|
361
554
|
let body = {};
|
|
362
555
|
// Build endpoint
|
|
363
556
|
switch (operation) {
|
|
364
|
-
case
|
|
557
|
+
case "getAll":
|
|
365
558
|
endpoint = `/v3/${baseEndpoint}`;
|
|
366
559
|
break;
|
|
367
|
-
case
|
|
560
|
+
case "get":
|
|
368
561
|
if (!recordId)
|
|
369
|
-
throw new Error(
|
|
562
|
+
throw new Error("recordId required");
|
|
370
563
|
endpoint = `/v3/${baseEndpoint}/${recordId}`;
|
|
371
564
|
break;
|
|
372
|
-
case
|
|
565
|
+
case "create":
|
|
373
566
|
endpoint = `/v3/${baseEndpoint}`;
|
|
374
|
-
method =
|
|
567
|
+
method = "POST";
|
|
375
568
|
body = data;
|
|
376
569
|
break;
|
|
377
|
-
case
|
|
570
|
+
case "update":
|
|
378
571
|
if (!recordId)
|
|
379
|
-
throw new Error(
|
|
572
|
+
throw new Error("recordId required");
|
|
380
573
|
endpoint = `/v3/${baseEndpoint}/${recordId}`;
|
|
381
|
-
method =
|
|
574
|
+
method = "PUT";
|
|
382
575
|
body = data;
|
|
383
576
|
break;
|
|
384
|
-
case
|
|
577
|
+
case "activate":
|
|
385
578
|
if (!recordId)
|
|
386
|
-
throw new Error(
|
|
579
|
+
throw new Error("recordId required");
|
|
387
580
|
endpoint = `/v3/${baseEndpoint}/${recordId}/active`;
|
|
388
|
-
method = [
|
|
389
|
-
|
|
581
|
+
method = [
|
|
582
|
+
"client",
|
|
583
|
+
"item",
|
|
584
|
+
"itemType",
|
|
585
|
+
"task",
|
|
586
|
+
"service",
|
|
587
|
+
"product",
|
|
588
|
+
"order",
|
|
589
|
+
"modality",
|
|
590
|
+
].includes(resource)
|
|
591
|
+
? "PUT"
|
|
592
|
+
: "PATCH";
|
|
390
593
|
break;
|
|
391
|
-
case
|
|
594
|
+
case "deactivate":
|
|
392
595
|
if (!recordId)
|
|
393
|
-
throw new Error(
|
|
596
|
+
throw new Error("recordId required");
|
|
394
597
|
endpoint = `/v3/${baseEndpoint}/${recordId}/inactive`;
|
|
395
|
-
method = [
|
|
396
|
-
|
|
598
|
+
method = [
|
|
599
|
+
"client",
|
|
600
|
+
"item",
|
|
601
|
+
"itemType",
|
|
602
|
+
"task",
|
|
603
|
+
"service",
|
|
604
|
+
"product",
|
|
605
|
+
"order",
|
|
606
|
+
"modality",
|
|
607
|
+
].includes(resource)
|
|
608
|
+
? "PUT"
|
|
609
|
+
: "PATCH";
|
|
397
610
|
break;
|
|
398
611
|
}
|
|
399
612
|
// Build query string
|
|
400
613
|
const queryParams = [];
|
|
401
614
|
// Add relations (only GET)
|
|
402
|
-
if (method ===
|
|
403
|
-
config.relations.forEach(relation => {
|
|
615
|
+
if (method === "GET" && config.relations.length > 0) {
|
|
616
|
+
config.relations.forEach((relation) => {
|
|
404
617
|
queryParams.push(`relations=${relation}`);
|
|
405
618
|
});
|
|
406
619
|
}
|
|
407
620
|
// Add filters
|
|
408
621
|
if (Object.keys(filters).length > 0) {
|
|
409
|
-
Object.keys(filters).forEach(field => {
|
|
622
|
+
Object.keys(filters).forEach((field) => {
|
|
410
623
|
const operators = filters[field];
|
|
411
|
-
Object.keys(operators).forEach(operator => {
|
|
624
|
+
Object.keys(operators).forEach((operator) => {
|
|
412
625
|
const value = operators[operator];
|
|
413
626
|
queryParams.push(`filters[${field}][${operator}]=${encodeURIComponent(String(value))}`);
|
|
414
627
|
});
|
|
@@ -417,21 +630,23 @@ class Confirm8AgentTool {
|
|
|
417
630
|
// Full URL
|
|
418
631
|
let fullUrl = `${baseUrl}${endpoint}`;
|
|
419
632
|
if (queryParams.length > 0) {
|
|
420
|
-
fullUrl +=
|
|
633
|
+
fullUrl += "?" + queryParams.join("&");
|
|
421
634
|
}
|
|
422
635
|
// Make request
|
|
423
636
|
const options = {
|
|
424
637
|
method,
|
|
425
638
|
uri: fullUrl,
|
|
426
639
|
headers: {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
640
|
+
Authorization: `Bearer ${bearerToken}`,
|
|
641
|
+
"X-API-DOMAIN": apiDomain,
|
|
642
|
+
"X-APIKEY-TOKEN": apiKeyToken,
|
|
643
|
+
"Content-Type": "application/json",
|
|
431
644
|
},
|
|
432
645
|
json: true,
|
|
433
646
|
};
|
|
434
|
-
if (method !==
|
|
647
|
+
if (method !== "GET" &&
|
|
648
|
+
method !== "DELETE" &&
|
|
649
|
+
Object.keys(body).length > 0) {
|
|
435
650
|
options.body = body;
|
|
436
651
|
}
|
|
437
652
|
const responseData = await this.helpers.request(options);
|
|
@@ -439,8 +654,8 @@ class Confirm8AgentTool {
|
|
|
439
654
|
json: {
|
|
440
655
|
success: true,
|
|
441
656
|
normalized: {
|
|
442
|
-
originalResource: this.getNodeParameter(
|
|
443
|
-
originalOperation: this.getNodeParameter(
|
|
657
|
+
originalResource: this.getNodeParameter("resource", i, ""),
|
|
658
|
+
originalOperation: this.getNodeParameter("operation", i, ""),
|
|
444
659
|
normalizedResource: resource,
|
|
445
660
|
normalizedOperation: operation,
|
|
446
661
|
},
|
|
@@ -461,7 +676,7 @@ class Confirm8AgentTool {
|
|
|
461
676
|
returnData.push({
|
|
462
677
|
json: {
|
|
463
678
|
success: false,
|
|
464
|
-
error: error.message ||
|
|
679
|
+
error: error.message || "Unknown error",
|
|
465
680
|
},
|
|
466
681
|
pairedItem: { item: i },
|
|
467
682
|
});
|