@wondai/n8n-nodes-nucleo 0.2.2 → 0.2.4
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/README.md +6 -0
- package/dist/nodes/Nucleo/Nucleo.node.js +75 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,9 +20,11 @@ parede. Isso mantém o segredo fora do workflow, a lógica num lugar só e o tok
|
|
|
20
20
|
|---|---|---|---|
|
|
21
21
|
| Cliente | Buscar | `GET /api/v1/agent/cliente` | `cliente:ler` |
|
|
22
22
|
| Catálogo | Resolver Produtos | `POST /api/v1/agent/catalogo/resolver` | `catalogo:ler` |
|
|
23
|
+
| Pedido | Detalhar | `GET /api/v1/agent/pedido/:ref` | `pedido:ler` |
|
|
23
24
|
| Pedido | Criar | `POST /api/v1/agent/pedido` | `pedido:escrever` |
|
|
24
25
|
| Pedido | Alterar | `PATCH /api/v1/agent/pedido/:id` | `pedido:escrever` |
|
|
25
26
|
| Pedido | Cancelar | `POST /api/v1/agent/pedido/:id/cancelar` | `pedido:escrever` |
|
|
27
|
+
| Conversa | Registrar | `POST /api/v1/agent/conversa/fechar` | `conversa:escrever` |
|
|
26
28
|
|
|
27
29
|
**Resolver Produtos** é a operação inteligente: manda várias consultas numa chamada (máx 10),
|
|
28
30
|
tolera erro de digitação (`banofe`→Banoffee), falta de acento (`pao frances`→Pão Francês) e
|
|
@@ -31,6 +33,10 @@ apelidos; devolve no máx 3 candidatos por consulta com `status` (`achou`/`ambig
|
|
|
31
33
|
**Criar** é idempotente: deixe *Idempotency Key* vazio (gera uma) ou repita a mesma chave num retry
|
|
32
34
|
— o Núcleo nunca duplica o pedido.
|
|
33
35
|
|
|
36
|
+
No **Pedido Criar**, `Nome do Cliente` e `Endereço de Entrega (JSON)` são opcionais e existem para
|
|
37
|
+
carregar o que a IA já coletou no atendimento. O node continua burro: só envia `nome_cliente` e
|
|
38
|
+
`endereco_entrega`; quem decide tenant, valida e grava snapshot em `crm.entregas` é o Núcleo.
|
|
39
|
+
|
|
34
40
|
## Instalação (n8n self-hosted)
|
|
35
41
|
|
|
36
42
|
1. **Settings → Community Nodes → Install** → `@wondai/n8n-nodes-nucleo`.
|
|
@@ -85,6 +85,24 @@ function asArray(value) {
|
|
|
85
85
|
}
|
|
86
86
|
return [];
|
|
87
87
|
}
|
|
88
|
+
/** Lê um parâmetro JSON (string ou objeto) como objeto simples. Vazio → null. */
|
|
89
|
+
function asObject(value) {
|
|
90
|
+
if (value && typeof value === "object" && !Array.isArray(value))
|
|
91
|
+
return value;
|
|
92
|
+
if (typeof value === "string") {
|
|
93
|
+
const t = value.trim();
|
|
94
|
+
if (!t)
|
|
95
|
+
return null;
|
|
96
|
+
try {
|
|
97
|
+
const j = JSON.parse(t);
|
|
98
|
+
return j && typeof j === "object" && !Array.isArray(j) ? j : null;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
88
106
|
/** IDs separados por vírgula ou JSON array → string[]. */
|
|
89
107
|
function parseIds(value) {
|
|
90
108
|
if (Array.isArray(value))
|
|
@@ -196,7 +214,7 @@ class Nucleo {
|
|
|
196
214
|
name: "Alterar",
|
|
197
215
|
value: "alterar",
|
|
198
216
|
action: "Alterar pedido",
|
|
199
|
-
description: "Altera data/observações/itens (adicionar,
|
|
217
|
+
description: "Altera data/observações/itens. Itens por PRODUTO (adicionar soma, ajustar +/-, definir, remover produto) ou por id de item (compat).",
|
|
200
218
|
},
|
|
201
219
|
{
|
|
202
220
|
name: "Cancelar",
|
|
@@ -268,6 +286,14 @@ class Nucleo {
|
|
|
268
286
|
description: "Telefone do cliente (E.164). Resolve o cliente existente ou cria um novo.",
|
|
269
287
|
displayOptions: { show: { resource: ["pedido"], operation: ["criar"] } },
|
|
270
288
|
},
|
|
289
|
+
{
|
|
290
|
+
displayName: "Nome do Cliente",
|
|
291
|
+
name: "nomeCliente",
|
|
292
|
+
type: "string",
|
|
293
|
+
default: "",
|
|
294
|
+
description: "Opcional. Preenche cliente novo ou cliente existente ainda sem nome. Não sobrescreve nome já cadastrado.",
|
|
295
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["criar"] } },
|
|
296
|
+
},
|
|
271
297
|
{
|
|
272
298
|
displayName: "Itens (JSON)",
|
|
273
299
|
name: "itens",
|
|
@@ -304,6 +330,14 @@ class Nucleo {
|
|
|
304
330
|
description: "Data/hora ISO 8601 para encomenda. Vazio = imediato.",
|
|
305
331
|
displayOptions: { show: { resource: ["pedido"], operation: ["criar"] } },
|
|
306
332
|
},
|
|
333
|
+
{
|
|
334
|
+
displayName: "Endereço de Entrega (JSON)",
|
|
335
|
+
name: "enderecoEntrega",
|
|
336
|
+
type: "json",
|
|
337
|
+
default: "{}",
|
|
338
|
+
description: 'Opcional. Para entrega, snapshot do endereço escolhido: {"logradouro","numero","complemento","bairro","cidade","estado","cep","referencia"}. Logradouro e cidade são obrigatórios quando enviado.',
|
|
339
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["criar"] } },
|
|
340
|
+
},
|
|
307
341
|
{
|
|
308
342
|
displayName: "Loja (unit_id)",
|
|
309
343
|
name: "unitId",
|
|
@@ -370,6 +404,30 @@ class Nucleo {
|
|
|
370
404
|
description: 'Muda a quantidade de itens já existentes: [{"item_id":"...","quantidade":4}]. Os IDs vêm do Detalhar. Trocar item = remover + adicionar. Vazio = não altera.',
|
|
371
405
|
displayOptions: { show: { resource: ["pedido"], operation: ["alterar"] } },
|
|
372
406
|
},
|
|
407
|
+
{
|
|
408
|
+
displayName: "Ajustar Itens por Produto (JSON)",
|
|
409
|
+
name: "ajustarItens",
|
|
410
|
+
type: "json",
|
|
411
|
+
default: "[]",
|
|
412
|
+
description: 'Ajuste relativo POR PRODUTO (o cliente não sabe id de item): [{"produto_id":"...","quantidade_delta":7}] soma; -5 subtrai; resultado ≤ 0 remove a linha. produto_id vem do Catálogo Resolver. Vazio = não ajusta.',
|
|
413
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["alterar"] } },
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
displayName: "Definir Itens por Produto (JSON)",
|
|
417
|
+
name: "definirItens",
|
|
418
|
+
type: "json",
|
|
419
|
+
default: "[]",
|
|
420
|
+
description: 'Quantidade absoluta POR PRODUTO: [{"produto_id":"...","quantidade":5}] deixa a linha com 5; 0 remove. produto_id vem do Catálogo Resolver. Vazio = não define.',
|
|
421
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["alterar"] } },
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
displayName: "Remover Produtos (produto_ids)",
|
|
425
|
+
name: "removerProdutoIds",
|
|
426
|
+
type: "string",
|
|
427
|
+
default: "",
|
|
428
|
+
description: "produto_ids a remover do pedido (todas as linhas do produto), separados por vírgula ou JSON array. Use para 'tirar os X' e para a troca. produto_id vem do Catálogo Resolver.",
|
|
429
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["alterar"] } },
|
|
430
|
+
},
|
|
373
431
|
{
|
|
374
432
|
displayName: "Motivo",
|
|
375
433
|
name: "motivo",
|
|
@@ -455,20 +513,27 @@ class Nucleo {
|
|
|
455
513
|
}
|
|
456
514
|
else if (resource === "pedido" && operation === "criar") {
|
|
457
515
|
const telefone = this.getNodeParameter("telefone", i).trim();
|
|
516
|
+
const nomeCliente = this.getNodeParameter("nomeCliente", i, "").trim();
|
|
458
517
|
const itens = asArray(this.getNodeParameter("itens", i));
|
|
459
518
|
const tipoEntrega = this.getNodeParameter("tipoEntrega", i);
|
|
460
519
|
const observacoes = this.getNodeParameter("observacoes", i, "").trim();
|
|
461
520
|
const agendadoPara = this.getNodeParameter("agendadoPara", i, "").trim();
|
|
521
|
+
const enderecoEntrega = asObject(this.getNodeParameter("enderecoEntrega", i, "{}"));
|
|
462
522
|
const unitId = this.getNodeParameter("unitId", i, "").trim();
|
|
463
523
|
idempotencyKey =
|
|
464
524
|
this.getNodeParameter("idempotencyKey", i, "").trim() || (0, node_crypto_1.randomUUID)();
|
|
465
525
|
const b = { telefone, itens };
|
|
526
|
+
if (nomeCliente)
|
|
527
|
+
b.nome_cliente = nomeCliente;
|
|
466
528
|
if (tipoEntrega)
|
|
467
529
|
b.tipo_entrega = tipoEntrega;
|
|
468
530
|
if (observacoes)
|
|
469
531
|
b.observacoes = observacoes;
|
|
470
532
|
if (agendadoPara)
|
|
471
533
|
b.agendado_para = agendadoPara;
|
|
534
|
+
if (enderecoEntrega && Object.keys(enderecoEntrega).length) {
|
|
535
|
+
b.endereco_entrega = enderecoEntrega;
|
|
536
|
+
}
|
|
472
537
|
if (unitId)
|
|
473
538
|
b.unit_id = unitId;
|
|
474
539
|
method = "POST";
|
|
@@ -482,6 +547,9 @@ class Nucleo {
|
|
|
482
547
|
const adicionar = asArray(this.getNodeParameter("adicionarItens", i, "[]"));
|
|
483
548
|
const remover = parseIds(this.getNodeParameter("removerItemIds", i, ""));
|
|
484
549
|
const alterar = asArray(this.getNodeParameter("alterarItens", i, "[]"));
|
|
550
|
+
const ajustar = asArray(this.getNodeParameter("ajustarItens", i, "[]"));
|
|
551
|
+
const definir = asArray(this.getNodeParameter("definirItens", i, "[]"));
|
|
552
|
+
const removerProdutos = parseIds(this.getNodeParameter("removerProdutoIds", i, ""));
|
|
485
553
|
const b = {};
|
|
486
554
|
if (observacoes.trim())
|
|
487
555
|
b.observacoes = observacoes.trim();
|
|
@@ -493,6 +561,12 @@ class Nucleo {
|
|
|
493
561
|
b.remover_item_ids = remover;
|
|
494
562
|
if (alterar.length)
|
|
495
563
|
b.alterar_itens = alterar;
|
|
564
|
+
if (ajustar.length)
|
|
565
|
+
b.ajustar_itens = ajustar;
|
|
566
|
+
if (definir.length)
|
|
567
|
+
b.definir_itens = definir;
|
|
568
|
+
if (removerProdutos.length)
|
|
569
|
+
b.remover_produto_ids = removerProdutos;
|
|
496
570
|
method = "PATCH";
|
|
497
571
|
path = `/api/v1/agent/pedido/${encodeURIComponent(pedidoId)}`;
|
|
498
572
|
bodyObj = b;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wondai/n8n-nodes-nucleo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Node n8n para o Núcleo Wondai — atendimento de IA (cliente, catálogo fuzzy, pedidos) com assinatura HMAC v1. Tenant vem do token (a parede, ADR-013).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|