n8n-nodes-atendix 1.3.7 → 1.3.8
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.
|
@@ -252,27 +252,50 @@ class Atendix {
|
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
254
|
async execute() {
|
|
255
|
-
var _a;
|
|
255
|
+
var _a, _b, _c, _d;
|
|
256
256
|
const items = this.getInputData();
|
|
257
257
|
const returnData = [];
|
|
258
258
|
const resource = this.getNodeParameter('resource', 0);
|
|
259
259
|
const operation = this.getNodeParameter('operation', 0);
|
|
260
|
-
|
|
260
|
+
console.log(`\n========================================`);
|
|
261
|
+
console.log(`[ATENDIX v1.3.7] Iniciando execução`);
|
|
262
|
+
console.log(`[ATENDIX] resource=${resource} | operation=${operation} | items=${items.length}`);
|
|
263
|
+
console.log(`========================================`);
|
|
264
|
+
// Chaves internalizadas — não dependem de variáveis de ambiente
|
|
261
265
|
if (!ATENDIX_AUTH_TOKEN) {
|
|
266
|
+
console.error('[ATENDIX] ❌ ATENDIX_AUTH_TOKEN não encontrado no pacote');
|
|
262
267
|
throw new Error('Configuração de validação Atendix incompleta. Entre em contato com o suporte.');
|
|
263
268
|
}
|
|
264
269
|
// 1. Credenciais
|
|
265
270
|
const credentials = await this.getCredentials('trayApiAuto');
|
|
266
|
-
|
|
271
|
+
const apiHost = (credentials.apiHost || '').trim().replace(/\/$/, '');
|
|
272
|
+
const apiAddress = (credentials.apiAddress || '').trim().replace(/\/$/, '');
|
|
273
|
+
let baseUrl = (apiHost || apiAddress);
|
|
274
|
+
console.log(`[ATENDIX] apiHost = "${apiHost}"`);
|
|
275
|
+
console.log(`[ATENDIX] apiAddress = "${apiAddress}"`);
|
|
276
|
+
console.log(`[ATENDIX] baseUrl = "${baseUrl}"`);
|
|
277
|
+
console.log(`[ATENDIX] accessToken = ${credentials.accessToken ? '✅ presente em cache' : '⚠️ ausente — vai autenticar'}`);
|
|
278
|
+
console.log(`[ATENDIX] tokenExpiry = ${credentials.tokenExpiration || 'não definido'}`);
|
|
267
279
|
// ==========================================
|
|
268
280
|
// 1.1 VALIDAÇÃO DE LICENÇA (SaaS GATEKEEPER)
|
|
269
281
|
// ==========================================
|
|
270
282
|
const storeBaseUrl = baseUrl.replace('/web_api', '');
|
|
271
283
|
let licenseCheck;
|
|
284
|
+
// Detecta se está rodando no servidor da Maria Pinho (mesma rede Docker)
|
|
285
|
+
// Se sim, usa endereço interno do container para evitar loop via Traefik
|
|
286
|
+
const n8nHost = process.env.N8N_HOST || '';
|
|
287
|
+
const isInternalServer = n8nHost.includes('mariapinho.com.br');
|
|
288
|
+
const licenseUrlExternal = 'https://n8n.mariapinho.com.br/webhook/valida-atendix';
|
|
289
|
+
const licenseUrlInternal = 'http://n8n_webhook:5678/webhook/valida-atendix';
|
|
290
|
+
const licenseUrl = isInternalServer ? licenseUrlInternal : licenseUrlExternal;
|
|
291
|
+
console.log(`[ATENDIX] 🔐 Validando licença para: ${storeBaseUrl}`);
|
|
292
|
+
console.log(`[ATENDIX] 🔐 N8N_HOST detectado: "${n8nHost}"`);
|
|
293
|
+
console.log(`[ATENDIX] 🔐 Modo: ${isInternalServer ? 'INTERNO (Docker)' : 'EXTERNO (internet)'}`);
|
|
294
|
+
console.log(`[ATENDIX] 🔐 License URL: ${licenseUrl}`);
|
|
272
295
|
try {
|
|
273
296
|
licenseCheck = await this.helpers.httpRequest({
|
|
274
297
|
method: 'POST',
|
|
275
|
-
url:
|
|
298
|
+
url: licenseUrl,
|
|
276
299
|
headers: {
|
|
277
300
|
'Content-Type': 'application/json',
|
|
278
301
|
'Authorization': ATENDIX_AUTH_TOKEN,
|
|
@@ -280,22 +303,29 @@ class Atendix {
|
|
|
280
303
|
body: { url: storeBaseUrl },
|
|
281
304
|
json: true,
|
|
282
305
|
});
|
|
283
|
-
console.
|
|
306
|
+
console.log(`[ATENDIX] 🔐 License check response:`, JSON.stringify(licenseCheck));
|
|
284
307
|
if (!licenseCheck || licenseCheck.autorizado !== true) {
|
|
285
|
-
console.error(
|
|
308
|
+
console.error(`[ATENDIX] ❌ Licença NÃO autorizada para ${storeBaseUrl}`);
|
|
309
|
+
console.error(`[ATENDIX] ❌ Resposta do servidor:`, JSON.stringify(licenseCheck));
|
|
286
310
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Sua licença Atendix para a loja ${storeBaseUrl} não está ativa. Acesse https://atendix.co`);
|
|
287
311
|
}
|
|
312
|
+
console.log(`[ATENDIX] ✅ Licença OK`);
|
|
288
313
|
}
|
|
289
314
|
catch (error) {
|
|
290
|
-
console.error(
|
|
291
|
-
console.error(
|
|
315
|
+
console.error(`[ATENDIX] ❌ Erro na validação de licença`);
|
|
316
|
+
console.error(`[ATENDIX] licenseUrl = ${licenseUrl}`);
|
|
317
|
+
console.error(`[ATENDIX] storeBaseUrl = ${storeBaseUrl}`);
|
|
318
|
+
console.error(`[ATENDIX] HTTP status = ${(_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status}`);
|
|
319
|
+
console.error(`[ATENDIX] HTTP body = ${JSON.stringify((_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data)}`);
|
|
320
|
+
console.error(`[ATENDIX] message = ${error === null || error === void 0 ? void 0 : error.message}`);
|
|
292
321
|
if (error instanceof n8n_workflow_1.NodeOperationError)
|
|
293
322
|
throw error;
|
|
294
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(),
|
|
323
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Erro crítico na validação de licença: ${error === null || error === void 0 ? void 0 : error.message}`);
|
|
295
324
|
}
|
|
296
|
-
// 2. TOKEN MANAGER (Fallback)
|
|
325
|
+
// 2. TOKEN MANAGER (Fallback quando preAuthentication não preencheu)
|
|
297
326
|
let accessToken = credentials.accessToken;
|
|
298
327
|
if (!accessToken) {
|
|
328
|
+
console.log(`[ATENDIX] ⚠️ accessToken vazio — autenticando manualmente via ${baseUrl}/auth`);
|
|
299
329
|
try {
|
|
300
330
|
const authResponse = await this.helpers.httpRequest({
|
|
301
331
|
method: 'POST',
|
|
@@ -308,11 +338,16 @@ class Atendix {
|
|
|
308
338
|
json: true,
|
|
309
339
|
});
|
|
310
340
|
accessToken = authResponse.access_token;
|
|
341
|
+
console.log(`[ATENDIX] ✅ Token obtido via fallback: ${accessToken ? accessToken.substring(0, 20) + '...' : 'VAZIO'}`);
|
|
311
342
|
}
|
|
312
343
|
catch (authError) {
|
|
344
|
+
console.error(`[ATENDIX] ❌ Falha no fallback de autenticação: ${authError.message}`);
|
|
313
345
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Falha na Autenticação Tray: ${authError.message}`);
|
|
314
346
|
}
|
|
315
347
|
}
|
|
348
|
+
else {
|
|
349
|
+
console.log(`[ATENDIX] ✅ Usando token em cache: ${accessToken.substring(0, 20)}...`);
|
|
350
|
+
}
|
|
316
351
|
// ==========================================
|
|
317
352
|
// 3. LOOP PRINCIPAL — Rate limit: 500ms entre itens
|
|
318
353
|
// ==========================================
|
|
@@ -326,8 +361,10 @@ class Atendix {
|
|
|
326
361
|
if (resource === 'order') {
|
|
327
362
|
if (operation === 'get') {
|
|
328
363
|
const orderId = this.getNodeParameter('orderId', i);
|
|
329
|
-
|
|
330
|
-
|
|
364
|
+
const url = `${baseUrl}/orders/${orderId}`;
|
|
365
|
+
console.log(`[ATENDIX] 📦 GET ${url}`);
|
|
366
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
367
|
+
console.log(`[ATENDIX] ✅ Pedido retornado: ${JSON.stringify(responseData).substring(0, 200)}`);
|
|
331
368
|
}
|
|
332
369
|
if (operation === 'list') {
|
|
333
370
|
const filters = this.getNodeParameter('filters', i, {});
|
|
@@ -335,7 +372,9 @@ class Atendix {
|
|
|
335
372
|
qs.status = filters.status;
|
|
336
373
|
if (filters.limit)
|
|
337
374
|
qs.limit = filters.limit;
|
|
338
|
-
|
|
375
|
+
const url = `${baseUrl}/orders`;
|
|
376
|
+
console.log(`[ATENDIX] 📦 GET ${url} | qs=${JSON.stringify(qs)}`);
|
|
377
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
339
378
|
}
|
|
340
379
|
}
|
|
341
380
|
// ==================== CLIENTES ====================
|
|
@@ -347,7 +386,9 @@ class Atendix {
|
|
|
347
386
|
qs.email = searchValue;
|
|
348
387
|
else
|
|
349
388
|
qs.cpf_cnpj = searchValue;
|
|
350
|
-
|
|
389
|
+
const url = `${baseUrl}/customers`;
|
|
390
|
+
console.log(`[ATENDIX] 👤 GET ${url} | searchType=${searchType} value=${searchValue}`);
|
|
391
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
351
392
|
}
|
|
352
393
|
}
|
|
353
394
|
// ==================== PRODUTOS ====================
|
|
@@ -356,11 +397,15 @@ class Atendix {
|
|
|
356
397
|
const searchType = this.getNodeParameter('searchType', i);
|
|
357
398
|
const searchValue = this.getNodeParameter('searchValue', i);
|
|
358
399
|
if (searchType === 'id') {
|
|
359
|
-
|
|
400
|
+
const url = `${baseUrl}/products/${searchValue}`;
|
|
401
|
+
console.log(`[ATENDIX] 🛍️ GET ${url}`);
|
|
402
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
360
403
|
}
|
|
361
404
|
else {
|
|
405
|
+
const url = `${baseUrl}/products`;
|
|
362
406
|
qs.sku = searchValue;
|
|
363
|
-
|
|
407
|
+
console.log(`[ATENDIX] 🛍️ GET ${url} | sku=${searchValue}`);
|
|
408
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
364
409
|
}
|
|
365
410
|
}
|
|
366
411
|
}
|
|
@@ -372,11 +417,15 @@ class Atendix {
|
|
|
372
417
|
qs.limit = filters.limit;
|
|
373
418
|
if (filters.page)
|
|
374
419
|
qs.page = filters.page;
|
|
375
|
-
|
|
420
|
+
const url = `${baseUrl}/categories`;
|
|
421
|
+
console.log(`[ATENDIX] 📂 GET ${url} | qs=${JSON.stringify(qs)}`);
|
|
422
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
376
423
|
}
|
|
377
424
|
if (operation === 'get') {
|
|
378
425
|
const categoryId = this.getNodeParameter('categoryId', i);
|
|
379
|
-
|
|
426
|
+
const url = `${baseUrl}/categories/${categoryId}`;
|
|
427
|
+
console.log(`[ATENDIX] 📂 GET ${url}`);
|
|
428
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
380
429
|
}
|
|
381
430
|
}
|
|
382
431
|
// ==================== VARIAÇÕES ====================
|
|
@@ -389,11 +438,15 @@ class Atendix {
|
|
|
389
438
|
qs.limit = filters.limit;
|
|
390
439
|
if (filters.page)
|
|
391
440
|
qs.page = filters.page;
|
|
392
|
-
|
|
441
|
+
const url = `${baseUrl}/variants`;
|
|
442
|
+
console.log(`[ATENDIX] 🔀 GET ${url} | product_id=${productIdForVariant}`);
|
|
443
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
393
444
|
}
|
|
394
445
|
if (operation === 'get') {
|
|
395
446
|
const variantId = this.getNodeParameter('variantId', i);
|
|
396
|
-
|
|
447
|
+
const url = `${baseUrl}/variants/${variantId}`;
|
|
448
|
+
console.log(`[ATENDIX] 🔀 GET ${url}`);
|
|
449
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
397
450
|
}
|
|
398
451
|
}
|
|
399
452
|
// ==================== IMAGENS DE PRODUTO ====================
|
|
@@ -402,12 +455,16 @@ class Atendix {
|
|
|
402
455
|
const imageUrl = this.getNodeParameter('imageUrl', i);
|
|
403
456
|
if (operation === 'create') {
|
|
404
457
|
const body = { ProductImage: { product_id: productIdForImage, url: imageUrl } };
|
|
405
|
-
|
|
458
|
+
const url = `${baseUrl}/products/${productIdForImage}/images`;
|
|
459
|
+
console.log(`[ATENDIX] 🖼️ POST ${url} | body=${JSON.stringify(body)}`);
|
|
460
|
+
responseData = await this.helpers.httpRequest({ method: 'POST', url, qs, body, json: true });
|
|
406
461
|
}
|
|
407
462
|
if (operation === 'createVariant') {
|
|
408
463
|
const variantIdForImage = this.getNodeParameter('variantIdForImage', i);
|
|
409
464
|
const body = { VariantImage: { product_id: productIdForImage, variant_id: variantIdForImage, url: imageUrl } };
|
|
410
|
-
|
|
465
|
+
const url = `${baseUrl}/variants/${variantIdForImage}/images`;
|
|
466
|
+
console.log(`[ATENDIX] 🖼️ POST ${url} | body=${JSON.stringify(body)}`);
|
|
467
|
+
responseData = await this.helpers.httpRequest({ method: 'POST', url, qs, body, json: true });
|
|
411
468
|
}
|
|
412
469
|
}
|
|
413
470
|
// ==================== NOTA FISCAL ====================
|
|
@@ -416,29 +473,43 @@ class Atendix {
|
|
|
416
473
|
// ✅ CORRETO: GET /orders/:order_id/invoices
|
|
417
474
|
// GET /invoices NÃO EXISTE na API Tray (confirmado no PRD §3.3)
|
|
418
475
|
const invoiceOrderId = this.getNodeParameter('invoiceOrderId', i);
|
|
419
|
-
|
|
476
|
+
const url = `${baseUrl}/orders/${invoiceOrderId}/invoices`;
|
|
477
|
+
console.log(`[ATENDIX] 🧾 GET ${url}`);
|
|
478
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
420
479
|
}
|
|
421
480
|
if (operation === 'get') {
|
|
422
481
|
const invoiceOrderId = this.getNodeParameter('invoiceOrderId', i);
|
|
423
482
|
const invoiceId = this.getNodeParameter('invoiceId', i);
|
|
424
|
-
|
|
483
|
+
const url = `${baseUrl}/orders/${invoiceOrderId}/invoices/${invoiceId}`;
|
|
484
|
+
console.log(`[ATENDIX] 🧾 GET ${url}`);
|
|
485
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
425
486
|
}
|
|
426
487
|
if (operation === 'getByOrder') {
|
|
427
488
|
const invoiceOrderId = this.getNodeParameter('invoiceOrderId', i);
|
|
428
|
-
|
|
489
|
+
const url = `${baseUrl}/orders/${invoiceOrderId}/invoices`;
|
|
490
|
+
console.log(`[ATENDIX] 🧾 GET ${url}`);
|
|
491
|
+
responseData = await this.helpers.httpRequest({ method: 'GET', url, qs, json: true });
|
|
429
492
|
}
|
|
430
493
|
if (operation === 'create') {
|
|
431
494
|
const invoiceOrderId = this.getNodeParameter('invoiceOrderId', i);
|
|
432
495
|
const invoiceData = this.getNodeParameter('invoiceData', i, {});
|
|
433
496
|
const body = { Invoice: { order_id: invoiceOrderId, ...invoiceData } };
|
|
434
|
-
|
|
497
|
+
const url = `${baseUrl}/invoices`;
|
|
498
|
+
console.log(`[ATENDIX] 🧾 POST ${url} | body=${JSON.stringify(body)}`);
|
|
499
|
+
responseData = await this.helpers.httpRequest({ method: 'POST', url, qs, body, json: true });
|
|
435
500
|
}
|
|
436
501
|
}
|
|
502
|
+
console.log(`[ATENDIX] ✅ item[${i}] concluído`);
|
|
437
503
|
const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
|
|
438
504
|
returnData.push(...executionData);
|
|
439
505
|
}
|
|
440
506
|
catch (error) {
|
|
441
507
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
508
|
+
console.error(`[ATENDIX] ❌ Erro no item[${i}]: ${errorMessage}`);
|
|
509
|
+
if (error instanceof Error && error.response) {
|
|
510
|
+
console.error(`[ATENDIX] ❌ HTTP status : ${(_c = error.response) === null || _c === void 0 ? void 0 : _c.status}`);
|
|
511
|
+
console.error(`[ATENDIX] ❌ HTTP body : ${JSON.stringify((_d = error.response) === null || _d === void 0 ? void 0 : _d.data)}`);
|
|
512
|
+
}
|
|
442
513
|
if (this.continueOnFail()) {
|
|
443
514
|
returnData.push({ json: { error: errorMessage }, pairedItem: { item: i } });
|
|
444
515
|
continue;
|
|
@@ -446,6 +517,7 @@ class Atendix {
|
|
|
446
517
|
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex: i });
|
|
447
518
|
}
|
|
448
519
|
}
|
|
520
|
+
console.log(`[ATENDIX] ✅ Execução finalizada — ${returnData.length} item(s) retornados`);
|
|
449
521
|
return [returnData];
|
|
450
522
|
}
|
|
451
523
|
}
|