n8n-rdstation-crm
Version:
Nós personalizados do n8n para integração com a API do RD Station CRM (v1)
339 lines (338 loc) • 18.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RdStationCrmDealProducts = void 0;
const n8n_workflow_1 = require("n8n-workflow");
/**
* Classe para o nó de Produtos em Negociações do RD Station CRM
* Este nó permite gerenciar produtos vinculados às negociações (oportunidades),
* possibilitando adicionar, atualizar ou remover itens de produto dos negócios.
* No RD Station CRM, é possível cadastrar um catálogo de produtos/serviços e
* vincular itens desse catálogo às negociações como itens de proposta comercial.
*/
class RdStationCrmDealProducts {
constructor() {
this.description = {
// Informações básicas do nó que serão exibidas na interface do n8n
displayName: 'RD Station CRM Produtos em Negócios',
name: 'rdStationCrmDealProducts',
icon: 'file:rdstation.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Gerenciar produtos em negociações no RD Station CRM',
defaults: {
name: 'RD Station CRM Produtos em Negócios', // Nome padrão quando o nó é adicionado
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
// Define que o nó requer credenciais do tipo rdStationCrmApi
name: 'rdStationCrmApi',
required: true, // As credenciais são obrigatórias
},
],
properties: [
// Seleção do recurso (neste caso, só temos produtos em negócios)
{
displayName: 'Recurso',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Produto em Negócio',
value: 'dealProduct', // Valor interno da opção
},
],
default: 'dealProduct',
required: true, // Campo obrigatório
},
// Seleção da operação a ser realizada sobre os produtos em negócios
{
displayName: 'Operação',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
// Mostra este campo apenas quando o recurso for 'dealProduct'
resource: [
'dealProduct',
],
},
},
options: [
// Lista de operações disponíveis para produtos em negócios
{
name: 'Adicionar',
value: 'add',
description: 'Adicionar produtos a uma negociação',
action: 'Adicionar produtos a uma negociação',
},
{
name: 'Atualizar',
value: 'update',
description: 'Atualizar produtos em uma negociação',
action: 'Atualizar produtos em uma negociação',
},
{
name: 'Remover',
value: 'remove',
description: 'Remover produtos de uma negociação',
action: 'Remover produtos de uma negociação',
},
{
name: 'Listar',
value: 'getAll',
description: 'Listar todos os produtos de uma negociação',
action: 'Listar produtos de uma negociação',
},
],
default: 'getAll', // Operação padrão
},
// Campo comum para todas as operações: ID do Negócio
{
displayName: 'ID do Negócio',
name: 'dealId',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: [
'dealProduct',
],
},
},
description: 'ID do negócio ao qual os produtos estão ou serão vinculados',
},
// Para a operação REMOVER PRODUTOS, precisamos dos IDs dos produtos a remover
{
displayName: 'IDs dos Produtos',
name: 'productIds',
placeholder: 'Adicionar ID de Produto',
type: 'fixedCollection',
typeOptions: {
multipleValues: true, // Permite múltiplos IDs
},
displayOptions: {
show: {
resource: [
'dealProduct',
],
operation: [
'remove',
],
},
},
default: {},
options: [
{
name: 'productIdValues',
displayName: 'ID do Produto',
values: [
{
displayName: 'ID do Produto',
name: 'id',
type: 'string',
default: '',
description: 'ID do produto a ser removido da negociação',
required: true, // ID é obrigatório
},
],
},
],
description: 'IDs dos produtos a serem removidos da negociação',
},
// Para as operações ADICIONAR e ATUALIZAR, precisamos dos detalhes dos produtos
{
displayName: 'Produtos',
name: 'products',
placeholder: 'Adicionar Produto',
type: 'fixedCollection',
typeOptions: {
multipleValues: true, // Permite múltiplos produtos
},
displayOptions: {
show: {
resource: [
'dealProduct',
],
operation: [
'add',
'update',
],
},
},
default: {},
options: [
{
name: 'productValues',
displayName: 'Produto',
values: [
{
displayName: 'ID do Produto',
name: 'product_id',
type: 'string',
default: '',
description: 'ID do produto do catálogo a vincular',
required: true, // ID do produto é obrigatório
},
{
displayName: 'Quantidade',
name: 'quantity',
type: 'number',
default: 1,
description: 'Quantidade do produto na negociação',
required: true, // Quantidade é obrigatória
},
{
displayName: 'Valor Unitário',
name: 'unit_value',
type: 'number',
default: 0,
description: 'Valor unitário do produto no contexto da negociação',
required: true, // Valor unitário é obrigatório
},
{
displayName: 'Desconto (%)',
name: 'discount',
type: 'number',
default: 0,
description: 'Desconto percentual aplicado ao produto (0-100)',
},
{
displayName: 'Total',
name: 'total',
type: 'number',
default: 0,
description: 'Valor total do item (calculado automaticamente se não fornecido)',
},
],
},
],
description: 'Produtos a serem adicionados ou atualizados na negociação',
},
],
};
}
/**
* Método principal que executa o nó com base na operação selecionada
* Este método é chamado pelo n8n quando o fluxo é executado
*/
async execute() {
const items = this.getInputData(); // Obtém os dados de entrada
const returnData = []; // Array para armazenar resultados
// URL base da API do RD Station CRM
const baseUrl = 'https://crm.rdstation.com/api/v1';
const resource = this.getNodeParameter('resource', 0); // Obtém o recurso selecionado
const operation = this.getNodeParameter('operation', 0); // Obtém a operação selecionada
// Para cada item de entrada, processa a operação solicitada
for (let i = 0; i < items.length; i++) {
try {
// Configuração comum para todas as requisições HTTP
const options = {
uri: '',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json', // Envia dados em formato JSON
},
json: true,
resolveWithFullResponse: true, // Retorna o objeto de resposta completo
};
// Vamos determinar qual operação executar com base no recurso e operação selecionados
if (resource === 'dealProduct') {
// Obtém o ID do negócio a ser trabalhado (comum a todas as operações)
const dealId = this.getNodeParameter('dealId', i);
// Verifica se o ID do negócio foi fornecido
if (!dealId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'É necessário fornecer um ID de negócio válido!', { itemIndex: i });
}
if (operation === 'getAll') {
// Operação: LISTAR PRODUTOS DO NEGÓCIO
// Preparando a requisição para listar produtos do negócio
options.method = 'GET'; // Método HTTP GET para listar
options.uri = `${baseUrl}/deals/${dealId}/deal_products`; // Endpoint de produtos do negócio
}
else if (operation === 'add') {
// Operação: ADICIONAR PRODUTOS AO NEGÓCIO
// Configurando requisição para adicionar produtos em lote
options.method = 'POST'; // Método HTTP POST para criação
options.uri = `${baseUrl}/deals/${dealId}/deal_products/batch`; // Endpoint batch para criação em lote
// Obtendo os produtos a serem adicionados
const productsCollection = this.getNodeParameter('products', i);
// Verificando se foram fornecidos produtos para adicionar
if (!productsCollection.productValues || productsCollection.productValues.length === 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'É necessário fornecer pelo menos um produto para adicionar à negociação!', { itemIndex: i });
}
// Preparando o corpo da requisição
const body = {
products: productsCollection.productValues, // Lista de produtos a adicionar
};
options.body = body; // Anexa o corpo à requisição
}
else if (operation === 'update') {
// Operação: ATUALIZAR PRODUTOS DO NEGÓCIO
// Configurando requisição para atualizar produtos em lote
options.method = 'PATCH'; // Método HTTP PATCH para atualização parcial
options.uri = `${baseUrl}/deals/${dealId}/deal_products/batch/update`; // Endpoint batch/update
// Obtendo os produtos a serem atualizados
const productsCollection = this.getNodeParameter('products', i);
// Verificando se foram fornecidos produtos para atualizar
if (!productsCollection.productValues || productsCollection.productValues.length === 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'É necessário fornecer pelo menos um produto para atualizar na negociação!', { itemIndex: i });
}
// Preparando o corpo da requisição
const body = {
products: productsCollection.productValues, // Lista de produtos com dados atualizados
};
options.body = body; // Anexa o corpo à requisição
}
else if (operation === 'remove') {
// Operação: REMOVER PRODUTOS DO NEGÓCIO
// Configurando requisição para remover produtos em lote
options.method = 'DELETE'; // Método HTTP DELETE para remoção
options.uri = `${baseUrl}/deals/${dealId}/deal_products/batch`; // Endpoint batch para operação em lote
// Obtendo os IDs dos produtos a serem removidos
const productIdsCollection = this.getNodeParameter('productIds', i);
// Verificando se foram fornecidos IDs de produtos para remover
if (!productIdsCollection.productIdValues || productIdsCollection.productIdValues.length === 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'É necessário fornecer pelo menos um ID de produto para remover da negociação!', { itemIndex: i });
}
// Preparando o corpo da requisição com os IDs a remover
const body = {
product_ids: productIdsCollection.productIdValues.map(item => item.id), // Extrai apenas os IDs
};
options.body = body; // Anexa o corpo à requisição
}
}
// Executa a requisição HTTP com as opções configuradas e autenticação
const response = await this.helpers.requestWithAuthentication.call(this, 'rdStationCrmApi', // Usa as credenciais configuradas
options);
// Extrai os dados da resposta e adiciona ao retorno
const responseData = response.body;
returnData.push({
json: responseData,
pairedItem: { item: i }, // Mantém o pareamento com o item de entrada
});
}
catch (error) {
// Trata e reporta erros ocorridos durante a execução
if (this.continueOnFail()) {
// Se configurado para continuar mesmo com falhas
returnData.push({
json: {
error: error instanceof Error ? error.message : String(error), // Inclui a mensagem de erro
},
pairedItem: { item: i },
});
continue; // Continua para o próximo item
}
throw error; // Senão, propaga o erro para interromper a execução
}
}
return [returnData]; // Retorna os dados processados
}
}
exports.RdStationCrmDealProducts = RdStationCrmDealProducts;