n8n-nodes-alegra-unofficial
Version:
Unofficial Alegra node for n8n - Community integration with Alegra's accounting platform. NOT OFFICIALLY SUPPORTED BY ALEGRA.
790 lines • 33.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Alegra = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const contact_operations_1 = require("./operations/contact.operations");
const invoice_operations_1 = require("./operations/invoice.operations");
const item_operations_1 = require("./operations/item.operations");
const payment_operations_1 = require("./operations/payment.operations");
const estimate_operations_1 = require("./operations/estimate.operations");
const tax_operations_1 = require("./operations/tax.operations");
const bankAccount_operations_1 = require("./operations/bankAccount.operations");
class Alegra {
constructor() {
this.description = {
displayName: 'Alegra (Unofficial - BETA)',
name: 'alegra',
icon: 'file:alegra.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Alegra API - UNOFFICIAL BETA community node. NOT officially supported by Alegra.',
defaults: {
name: 'Alegra',
},
inputs: [{ type: 'main' }],
outputs: [{ type: 'main' }],
credentials: [
{
name: 'alegraApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Contact',
value: 'contact',
description: 'Manage contacts (clients and providers)',
},
{
name: 'Invoice',
value: 'invoice',
description: 'Manage sales invoices',
},
{
name: 'Item',
value: 'item',
description: 'Manage products and services',
},
{
name: 'Payment',
value: 'payment',
description: 'Manage payments',
},
{
name: 'Estimate',
value: 'estimate',
description: 'Manage estimates/quotes',
},
{
name: 'Tax',
value: 'tax',
description: 'Manage taxes',
},
{
name: 'Bank Account',
value: 'bankAccount',
description: 'Manage bank accounts',
},
],
default: 'contact',
},
...contact_operations_1.contactOperations,
...invoice_operations_1.invoiceOperations,
...item_operations_1.itemOperations,
...payment_operations_1.paymentOperations,
...estimate_operations_1.estimateOperations,
...tax_operations_1.taxOperations,
...bankAccount_operations_1.bankAccountOperations,
],
};
this.methods = {
loadOptions: {
async getContacts() {
const returnData = [];
const contacts = await alegraApiRequest.call(this, 'GET', '/contacts');
for (const contact of contacts) {
returnData.push({
name: contact.name,
value: contact.id,
});
}
return returnData;
},
async getItems() {
const returnData = [];
const items = await alegraApiRequest.call(this, 'GET', '/items');
for (const item of items) {
returnData.push({
name: item.name,
value: item.id,
});
}
return returnData;
},
async getTaxes() {
const returnData = [];
const taxes = await alegraApiRequest.call(this, 'GET', '/taxes');
for (const tax of taxes) {
returnData.push({
name: `${tax.name} (${tax.percentage}%)`,
value: tax.id,
});
}
return returnData;
},
async getBankAccounts() {
const returnData = [];
const accounts = await alegraApiRequest.call(this, 'GET', '/bank-accounts');
for (const account of accounts) {
returnData.push({
name: account.name,
value: account.id,
});
}
return returnData;
},
async getSellers() {
const returnData = [];
const sellers = await alegraApiRequest.call(this, 'GET', '/sellers');
for (const seller of sellers) {
returnData.push({
name: seller.name,
value: seller.id,
});
}
return returnData;
},
async getCategories() {
const returnData = [];
const categories = await alegraApiRequest.call(this, 'GET', '/categories');
for (const category of categories) {
returnData.push({
name: category.name,
value: category.id,
});
}
return returnData;
},
async getAccountCategories() {
const returnData = [];
const categories = await alegraApiRequest.call(this, 'GET', '/account-categories');
for (const category of categories) {
returnData.push({
name: category.name,
value: category.id,
});
}
return returnData;
},
async getNumberTemplates() {
const returnData = [];
const templates = await alegraApiRequest.call(this, 'GET', '/number-templates/invoices');
for (const template of templates) {
returnData.push({
name: template.name,
value: template.id,
});
}
return returnData;
},
async getCostCenters() {
const returnData = [];
const centers = await alegraApiRequest.call(this, 'GET', '/cost-centers');
for (const center of centers) {
returnData.push({
name: center.name,
value: center.id,
});
}
return returnData;
},
async getPriceLists() {
const returnData = [];
const lists = await alegraApiRequest.call(this, 'GET', '/price-lists');
for (const list of lists) {
returnData.push({
name: list.name,
value: list.id,
});
}
return returnData;
},
async getRetentions() {
const returnData = [];
const retentions = await alegraApiRequest.call(this, 'GET', '/retentions');
for (const retention of retentions) {
returnData.push({
name: `${retention.name} (${retention.percentage}%)`,
value: retention.id,
});
}
return returnData;
},
},
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < items.length; i++) {
try {
let responseData;
if (resource === 'contact') {
responseData = await handleContactOperations.call(this, operation, i);
}
else if (resource === 'invoice') {
responseData = await handleInvoiceOperations.call(this, operation, i);
}
else if (resource === 'item') {
responseData = await handleItemOperations.call(this, operation, i);
}
else if (resource === 'payment') {
responseData = await handlePaymentOperations.call(this, operation, i);
}
else if (resource === 'estimate') {
responseData = await handleEstimateOperations.call(this, operation, i);
}
else if (resource === 'tax') {
responseData = await handleTaxOperations.call(this, operation, i);
}
else if (resource === 'bankAccount') {
responseData = await handleBankAccountOperations.call(this, operation, i);
}
if (Array.isArray(responseData)) {
returnData.push(...responseData.map(item => ({ json: item })));
}
else {
returnData.push({ json: responseData });
}
}
catch (error) {
if (this.continueOnFail()) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
returnData.push({ json: { error: errorMessage } });
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.Alegra = Alegra;
// Helper function to make API requests
async function alegraApiRequest(method, endpoint, body = {}, query = {}) {
const credentials = await this.getCredentials('alegraApi');
const options = {
method: method,
url: `${credentials.environment}/api/v1${endpoint}`,
json: true,
qs: query,
};
if (Object.keys(body).length !== 0) {
options.body = body;
}
try {
return await this.helpers.requestWithAuthentication.call(this, 'alegraApi', options);
}
catch (error) {
if (error instanceof Error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message);
}
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Unknown error occurred');
}
}
// Contact operations handler
async function handleContactOperations(operation, index) {
if (operation === 'create') {
const name = this.getNodeParameter('name', index);
const type = this.getNodeParameter('type', index);
const identificationType = this.getNodeParameter('identificationType', index);
const identificationNumber = this.getNodeParameter('identificationNumber', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
name,
type,
identification: {
type: identificationType,
number: identificationNumber,
},
};
Object.assign(body, additionalFields);
// Handle address fields
if (additionalFields.address?.addressFields) {
body.address = additionalFields.address.addressFields;
delete body.address.addressFields;
}
return await alegraApiRequest.call(this, 'POST', '/contacts', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/contacts/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
Object.assign(query, filters);
return await alegraApiRequest.call(this, 'GET', '/contacts', {}, query);
}
if (operation === 'update') {
const id = this.getNodeParameter('id', index);
const updateFields = this.getNodeParameter('updateFields', index);
const body = {};
Object.assign(body, updateFields);
// Handle address fields
if (updateFields.address?.addressFields) {
body.address = updateFields.address.addressFields;
delete body.address.addressFields;
}
return await alegraApiRequest.call(this, 'PUT', `/contacts/${id}`, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/contacts/${id}`);
}
}
// Invoice operations handler
async function handleInvoiceOperations(operation, index) {
if (operation === 'create') {
const date = this.getNodeParameter('date', index);
const dueDate = this.getNodeParameter('dueDate', index);
const client = this.getNodeParameter('client', index);
const paymentForm = this.getNodeParameter('paymentForm', index);
const paymentMethod = this.getNodeParameter('paymentMethod', index);
const generateStamp = this.getNodeParameter('generateStamp', index);
const items = this.getNodeParameter('items', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
date: date.split('T')[0],
dueDate: dueDate.split('T')[0],
client: { id: client },
paymentForm,
paymentMethod,
stamp: { generateStamp },
items: items.item,
currency: { code: additionalFields.currency || 'COP' },
};
// Handle additional fields
if (additionalFields.seller)
body.seller = { id: additionalFields.seller };
if (additionalFields.observations)
body.observations = additionalFields.observations;
if (additionalFields.anotation)
body.anotation = additionalFields.anotation;
if (additionalFields.termsConditions)
body.termsConditions = additionalFields.termsConditions;
if (additionalFields.numberTemplate)
body.numberTemplate = { id: additionalFields.numberTemplate };
if (additionalFields.costCenter)
body.costCenter = { id: additionalFields.costCenter };
if (additionalFields.exchangeRate)
body.exchangeRate = additionalFields.exchangeRate;
if (additionalFields.type)
body.type = additionalFields.type;
if (additionalFields.retentions) {
body.retentions = additionalFields.retentions.map((id) => ({ id }));
}
// Process items
body.items = body.items.map((item) => {
const processedItem = {
id: item.id,
price: item.price,
quantity: item.quantity,
description: item.description,
};
if (item.discount)
processedItem.discount = item.discount;
if (item.tax && item.tax.length > 0) {
processedItem.tax = item.tax.map((taxId) => ({ id: taxId }));
}
return processedItem;
});
return await alegraApiRequest.call(this, 'POST', '/invoices', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/invoices/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
if (filters.start)
query.start = filters.start.split('T')[0];
if (filters.end)
query.end = filters.end.split('T')[0];
if (filters.status)
query.status = filters.status;
if (filters.client)
query.client = filters.client;
if (filters.orderBy)
query.orderBy = filters.orderBy;
if (filters.orderDirection)
query.order = filters.orderDirection;
return await alegraApiRequest.call(this, 'GET', '/invoices', {}, query);
}
if (operation === 'sendEmail') {
const id = this.getNodeParameter('id', index);
const emails = this.getNodeParameter('emails', index);
const sendCopyToUser = this.getNodeParameter('sendCopyToUser', index);
const invoiceType = this.getNodeParameter('invoiceType', index);
const body = {
emails,
send_copy_to_user: sendCopyToUser,
invoice_type: invoiceType,
};
return await alegraApiRequest.call(this, 'POST', `/invoices/${id}/email`, body);
}
if (operation === 'update') {
const id = this.getNodeParameter('id', index);
const updateFields = this.getNodeParameter('updateFields', index);
const body = {};
if (updateFields.date)
body.date = updateFields.date.split('T')[0];
if (updateFields.dueDate)
body.dueDate = updateFields.dueDate.split('T')[0];
if (updateFields.observations)
body.observations = updateFields.observations;
if (updateFields.anotation)
body.anotation = updateFields.anotation;
if (updateFields.status)
body.status = updateFields.status;
return await alegraApiRequest.call(this, 'PUT', `/invoices/${id}`, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/invoices/${id}`);
}
}
// Item operations handler
async function handleItemOperations(operation, index) {
if (operation === 'create') {
const name = this.getNodeParameter('name', index);
const type = this.getNodeParameter('type', index);
const price = this.getNodeParameter('price', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
name,
type,
price,
};
Object.assign(body, additionalFields);
if (additionalFields.tax && additionalFields.tax.length > 0) {
body.tax = additionalFields.tax.map((taxId) => ({ id: taxId }));
}
if (additionalFields.category) {
body.category = { id: additionalFields.category };
}
return await alegraApiRequest.call(this, 'POST', '/items', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/items/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
Object.assign(query, filters);
return await alegraApiRequest.call(this, 'GET', '/items', {}, query);
}
if (operation === 'update') {
const id = this.getNodeParameter('id', index);
const updateFields = this.getNodeParameter('updateFields', index);
const body = {};
Object.assign(body, updateFields);
if (updateFields.tax && updateFields.tax.length > 0) {
body.tax = updateFields.tax.map((taxId) => ({ id: taxId }));
}
if (updateFields.category) {
body.category = { id: updateFields.category };
}
return await alegraApiRequest.call(this, 'PUT', `/items/${id}`, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/items/${id}`);
}
}
// Payment operations handler
async function handlePaymentOperations(operation, index) {
if (operation === 'create') {
const date = this.getNodeParameter('date', index);
const bankAccount = this.getNodeParameter('bankAccount', index);
const paymentMethod = this.getNodeParameter('paymentMethod', index);
const type = this.getNodeParameter('type', index);
const invoices = this.getNodeParameter('invoices', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
date: date.split('T')[0],
bankAccount: bankAccount,
paymentMethod,
type,
invoices: invoices.invoice,
currency: { code: additionalFields.currency || 'COP' },
};
if (additionalFields.contact)
body.client = additionalFields.contact;
if (additionalFields.observations)
body.observations = additionalFields.observations;
if (additionalFields.anotation)
body.anotation = additionalFields.anotation;
if (additionalFields.exchangeRate)
body.exchangeRate = additionalFields.exchangeRate;
if (additionalFields.categories?.category) {
body.categories = additionalFields.categories.category.map((cat) => {
const category = {
id: cat.id,
price: cat.price,
};
if (cat.description)
category.description = cat.description;
if (cat.tax && cat.tax.length > 0) {
category.tax = cat.tax.map((taxId) => ({ id: taxId }));
}
return category;
});
}
if (additionalFields.retentions?.retention) {
body.retentions = additionalFields.retentions.retention;
}
return await alegraApiRequest.call(this, 'POST', '/payments', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/payments/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
if (filters.start)
query.start = filters.start.split('T')[0];
if (filters.end)
query.end = filters.end.split('T')[0];
if (filters.type)
query.type = filters.type;
if (filters.contact)
query.contact = filters.contact;
if (filters.bankAccount)
query.bankAccount = filters.bankAccount;
if (filters.orderBy)
query.orderBy = filters.orderBy;
if (filters.orderDirection)
query.order = filters.orderDirection;
return await alegraApiRequest.call(this, 'GET', '/payments', {}, query);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/payments/${id}`);
}
}
// Estimate operations handler
async function handleEstimateOperations(operation, index) {
if (operation === 'create') {
const date = this.getNodeParameter('date', index);
const dueDate = this.getNodeParameter('dueDate', index);
const client = this.getNodeParameter('client', index);
const items = this.getNodeParameter('items', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
date: date.split('T')[0],
dueDate: dueDate.split('T')[0],
client: { id: client },
items: items.item,
currency: { code: additionalFields.currency || 'COP' },
};
// Handle additional fields
if (additionalFields.seller)
body.seller = { id: additionalFields.seller };
if (additionalFields.observations)
body.observations = additionalFields.observations;
if (additionalFields.anotation)
body.anotation = additionalFields.anotation;
if (additionalFields.termsConditions)
body.termsConditions = additionalFields.termsConditions;
if (additionalFields.status)
body.status = additionalFields.status;
if (additionalFields.exchangeRate)
body.exchangeRate = additionalFields.exchangeRate;
// Process items
body.items = body.items.map((item) => {
const processedItem = {
id: item.id,
price: item.price,
quantity: item.quantity,
};
if (item.description)
processedItem.description = item.description;
if (item.discount)
processedItem.discount = item.discount;
if (item.tax && item.tax.length > 0) {
processedItem.tax = item.tax.map((taxId) => ({ id: taxId }));
}
return processedItem;
});
return await alegraApiRequest.call(this, 'POST', '/estimates', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/estimates/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
if (filters.start)
query.start = filters.start.split('T')[0];
if (filters.end)
query.end = filters.end.split('T')[0];
if (filters.status)
query.status = filters.status;
if (filters.client)
query.client = filters.client;
if (filters.orderBy)
query.orderBy = filters.orderBy;
if (filters.orderDirection)
query.order = filters.orderDirection;
return await alegraApiRequest.call(this, 'GET', '/estimates', {}, query);
}
if (operation === 'sendEmail') {
const id = this.getNodeParameter('id', index);
const to = this.getNodeParameter('to', index);
const sendCopyToMyself = this.getNodeParameter('sendCopyToMyself', index);
const body = {
to,
send_copy_to_myself: sendCopyToMyself,
};
return await alegraApiRequest.call(this, 'POST', `/estimates/${id}/email`, body);
}
if (operation === 'update') {
const id = this.getNodeParameter('id', index);
const updateFields = this.getNodeParameter('updateFields', index);
const body = {};
if (updateFields.date)
body.date = updateFields.date.split('T')[0];
if (updateFields.dueDate)
body.dueDate = updateFields.dueDate.split('T')[0];
if (updateFields.observations)
body.observations = updateFields.observations;
if (updateFields.anotation)
body.anotation = updateFields.anotation;
if (updateFields.status)
body.status = updateFields.status;
return await alegraApiRequest.call(this, 'PUT', `/estimates/${id}`, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/estimates/${id}`);
}
}
// Tax operations handler
async function handleTaxOperations(operation, index) {
if (operation === 'create') {
const name = this.getNodeParameter('name', index);
const percentage = this.getNodeParameter('percentage', index);
const type = this.getNodeParameter('type', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
name,
percentage,
type,
};
Object.assign(body, additionalFields);
return await alegraApiRequest.call(this, 'POST', '/taxes', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/taxes/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
Object.assign(query, filters);
return await alegraApiRequest.call(this, 'GET', '/taxes', {}, query);
}
if (operation === 'update') {
const id = this.getNodeParameter('id', index);
const updateFields = this.getNodeParameter('updateFields', index);
const body = {};
Object.assign(body, updateFields);
return await alegraApiRequest.call(this, 'PUT', `/taxes/${id}`, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/taxes/${id}`);
}
}
// Bank Account operations handler
async function handleBankAccountOperations(operation, index) {
if (operation === 'create') {
const name = this.getNodeParameter('name', index);
const type = this.getNodeParameter('type', index);
const initialBalance = this.getNodeParameter('initialBalance', index);
const initialBalanceDate = this.getNodeParameter('initialBalanceDate', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
name,
type,
initialBalance: initialBalance.toString(),
initialBalanceDate: initialBalanceDate.split('T')[0],
};
Object.assign(body, additionalFields);
if (additionalFields.currency) {
body.currency = { code: additionalFields.currency };
}
return await alegraApiRequest.call(this, 'POST', '/bank-accounts', body);
}
if (operation === 'get') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'GET', `/bank-accounts/${id}`);
}
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', index);
const filters = this.getNodeParameter('filters', index);
const query = {};
if (!returnAll) {
query.limit = this.getNodeParameter('limit', index);
}
Object.assign(query, filters);
return await alegraApiRequest.call(this, 'GET', '/bank-accounts', {}, query);
}
if (operation === 'transfer') {
const sourceAccount = this.getNodeParameter('sourceAccount', index);
const destinationAccount = this.getNodeParameter('destinationAccount', index);
const amount = this.getNodeParameter('amount', index);
const date = this.getNodeParameter('date', index);
const additionalFields = this.getNodeParameter('additionalFields', index);
const body = {
id_destination: destinationAccount,
amount,
date: date.split('T')[0],
};
if (additionalFields.description)
body.description = additionalFields.description;
if (additionalFields.observations)
body.observations = additionalFields.observations;
return await alegraApiRequest.call(this, 'POST', `/bank-accounts/${sourceAccount}/transfer`, body);
}
if (operation === 'update') {
const id = this.getNodeParameter('id', index);
const updateFields = this.getNodeParameter('updateFields', index);
const body = {};
Object.assign(body, updateFields);
return await alegraApiRequest.call(this, 'PUT', `/bank-accounts/${id}`, body);
}
if (operation === 'delete') {
const id = this.getNodeParameter('id', index);
return await alegraApiRequest.call(this, 'DELETE', `/bank-accounts/${id}`);
}
}
//# sourceMappingURL=Alegra.node.js.map