Fix some InvoiceNinja-Node issues

This commit is contained in:
Jan Oberhauser 2020-03-16 23:26:27 +01:00
parent a5a2f4606c
commit d3a2456de9
15 changed files with 129 additions and 214 deletions

View file

@ -3,15 +3,15 @@ import {
NodePropertyTypes, NodePropertyTypes,
} from 'n8n-workflow'; } from 'n8n-workflow';
export class InvoiceNinjaServerApi implements ICredentialType { export class InvoiceNinjaApi implements ICredentialType {
name = 'invoiceNinjaServerApi'; name = 'invoiceNinjaApi';
displayName = 'Invoice Ninja API'; displayName = 'Invoice Ninja API';
properties = [ properties = [
{ {
displayName: 'Domain', displayName: 'URL',
name: 'domain', name: 'url',
type: 'string' as NodePropertyTypes, type: 'string' as NodePropertyTypes,
default: '', default: 'https://app.invoiceninja.com',
}, },
{ {
displayName: 'API Token', displayName: 'API Token',

View file

@ -1,17 +0,0 @@
import {
ICredentialType,
NodePropertyTypes,
} from 'n8n-workflow';
export class InvoiceNinjaCloudApi implements ICredentialType {
name = 'invoiceNinjaCloudApi';
displayName = 'Invoice Ninja API';
properties = [
{
displayName: 'API Token',
name: 'apiToken',
type: 'string' as NodePropertyTypes,
default: '',
},
];
}

View file

@ -18,6 +18,11 @@ export const clientOperations = [
value: 'create', value: 'create',
description: 'Create a new client', description: 'Create a new client',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a client',
},
{ {
name: 'Get', name: 'Get',
value: 'get', value: 'get',
@ -28,11 +33,6 @@ export const clientOperations = [
value: 'getAll', value: 'getAll',
description: 'Get data of all clients', description: 'Get data of all clients',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a client',
}
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',

View file

@ -8,7 +8,7 @@ export interface IContact {
} }
export interface IClient { export interface IClient {
contacts?: IContact[], contacts?: IContact[];
name?: string; name?: string;
address1?: string; address1?: string;
address2?: string; address2?: string;

View file

@ -18,21 +18,21 @@ export const expenseOperations = [
value: 'create', value: 'create',
description: 'Create a new expense', description: 'Create a new expense',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete an expense',
},
{ {
name: 'Get', name: 'Get',
value: 'get', value: 'get',
description: 'Get data of a expense', description: 'Get data of an expense',
}, },
{ {
name: 'Get All', name: 'Get All',
value: 'getAll', value: 'getAll',
description: 'Get data of all expenses', description: 'Get data of all expenses',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a expense',
}
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',
@ -60,6 +60,12 @@ export const expenseFields = [
}, },
}, },
options: [ options: [
{
displayName: 'Amount',
name: 'amount',
type: 'number',
default: 0,
},
{ {
displayName: 'Billable', displayName: 'Billable',
name: 'billable', name: 'billable',

View file

@ -13,29 +13,21 @@ import {
import { get } from 'lodash'; import { get } from 'lodash';
export async function invoiceninjaApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any export async function invoiceNinjaApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query?: IDataObject, uri?: string): Promise<any> { // tslint:disable-line:no-any
let token; const credentials = this.getCredentials('invoiceNinjaApi');
let endpoint; if (credentials === undefined) {
const cloudCredentials = this.getCredentials('invoiceNinjaCloudApi');
const serverCredentials = this.getCredentials('invoiceNinjaServerApi');
if (cloudCredentials === undefined && serverCredentials === undefined) {
throw new Error('No credentials got returned!'); throw new Error('No credentials got returned!');
} }
if (cloudCredentials !== undefined) {
endpoint = 'https://app.invoiceninja.com'; const baseUrl = credentials!.url || 'https://app.invoiceninja.com';
token = cloudCredentials!.apiToken;
} else {
endpoint = serverCredentials!.domain;
token = serverCredentials!.apiToken;
}
const options: OptionsWithUri = { const options: OptionsWithUri = {
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
'X-Ninja-Token': token, 'X-Ninja-Token': credentials.apiToken,
}, },
method, method,
qs: query, qs: query,
uri: uri || `${endpoint}/api/v1${resource}`, uri: uri || `${baseUrl}/api/v1${endpoint}`,
body, body,
json: true json: true
}; };
@ -54,7 +46,7 @@ export async function invoiceninjaApiRequest(this: IHookFunctions | IExecuteFunc
} }
} }
export async function invoiceninjaApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any export async function invoiceNinjaApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
const returnData: IDataObject[] = []; const returnData: IDataObject[] = [];
@ -63,8 +55,8 @@ export async function invoiceninjaApiRequestAllItems(this: IExecuteFunctions | I
query.per_page = 100; query.per_page = 100;
do { do {
responseData = await invoiceninjaApiRequest.call(this, method, endpoint, body, query, uri); responseData = await invoiceNinjaApiRequest.call(this, method, endpoint, body, query, uri);
let next = get(responseData, 'meta.pagination.links.next') as string | undefined; const next = get(responseData, 'meta.pagination.links.next') as string | undefined;
if (next) { if (next) {
uri = next; uri = next;
} }

View file

@ -18,6 +18,11 @@ export const invoiceOperations = [
value: 'create', value: 'create',
description: 'Create a new invoice', description: 'Create a new invoice',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a invoice',
},
{ {
name: 'Email', name: 'Email',
value: 'email', value: 'email',
@ -33,11 +38,6 @@ export const invoiceOperations = [
value: 'getAll', value: 'getAll',
description: 'Get data of all invoices', description: 'Get data of all invoices',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a invoice',
}
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',
@ -175,7 +175,7 @@ export const invoiceFields = [
default: '', default: '',
}, },
{ {
displayName: 'Po Number', displayName: 'PO Number',
name: 'poNumber', name: 'poNumber',
type: 'string', type: 'string',
default: '', default: '',

View file

@ -3,23 +3,23 @@ import {
} from 'n8n-core'; } from 'n8n-core';
import { import {
IDataObject, IDataObject,
INodeTypeDescription,
INodeExecutionData, INodeExecutionData,
INodeType,
ILoadOptionsFunctions, ILoadOptionsFunctions,
INodePropertyOptions, INodePropertyOptions,
INodeType,
INodeTypeDescription,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
invoiceninjaApiRequest, invoiceNinjaApiRequest,
invoiceninjaApiRequestAllItems, invoiceNinjaApiRequestAllItems,
} from './GenericFunctions'; } from './GenericFunctions';
import { import {
clientFields,
clientOperations, clientOperations,
clientFields
} from './ClientDescription'; } from './ClientDescription';
import { import {
invoiceFields,
invoiceOperations, invoiceOperations,
invoiceFields
} from './InvoiceDescription'; } from './InvoiceDescription';
import { import {
IClient, IClient,
@ -33,29 +33,29 @@ import {
IItem, IItem,
} from './invoiceInterface'; } from './invoiceInterface';
import { import {
taskFields,
taskOperations, taskOperations,
taskFields
} from './TaskDescription'; } from './TaskDescription';
import { import {
ITask, ITask,
} from './TaskInterface'; } from './TaskInterface';
import { import {
paymentFields,
paymentOperations, paymentOperations,
paymentFields
} from './PaymentDescription'; } from './PaymentDescription';
import { import {
IPayment, IPayment,
} from './PaymentInterface'; } from './PaymentInterface';
import { import {
expenseFields,
expenseOperations, expenseOperations,
expenseFields
} from './ExpenseDescription'; } from './ExpenseDescription';
import { import {
IExpense, IExpense,
} from './ExpenseInterface'; } from './ExpenseInterface';
import { import {
quoteFields,
quoteOperations, quoteOperations,
quoteFields
} from './QuoteDescription'; } from './QuoteDescription';
import { import {
IQuote, IQuote,
@ -78,45 +78,11 @@ export class InvoiceNinja implements INodeType {
outputs: ['main'], outputs: ['main'],
credentials: [ credentials: [
{ {
name: 'invoiceNinjaCloudApi', name: 'invoiceNinjaApi',
required: true, required: true,
displayOptions: {
show: {
invoiceNinjaVersion: [
'cloud',
],
},
},
},
{
name: 'invoiceNinjaServerApi',
required: true,
displayOptions: {
show: {
invoiceNinjaVersion: [
'server',
],
},
},
}, },
], ],
properties: [ properties: [
{
displayName: 'Version',
name: 'invoiceNinjaVersion',
type: 'options',
options: [
{
name: 'Cloud',
value: 'cloud',
},
{
name: 'Server (Self Hosted)',
value: 'server',
},
],
default: 'cloud',
},
{ {
displayName: 'Resource', displayName: 'Resource',
name: 'resource', name: 'resource',
@ -171,7 +137,7 @@ export class InvoiceNinja implements INodeType {
// select them easily // select them easily
async getClients(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getClients(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
const clients = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/clients'); const clients = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/clients');
for (const client of clients) { for (const client of clients) {
const clientName = client.display_name; const clientName = client.display_name;
const clientId = client.id; const clientId = client.id;
@ -186,7 +152,7 @@ export class InvoiceNinja implements INodeType {
// select them easily // select them easily
async getProjects(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getProjects(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
const projects = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/projects'); const projects = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/projects');
for (const project of projects) { for (const project of projects) {
const projectName = project.name; const projectName = project.name;
const projectId = project.id; const projectId = project.id;
@ -201,7 +167,7 @@ export class InvoiceNinja implements INodeType {
// select them easily // select them easily
async getInvoices(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getInvoices(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
const invoices = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/invoices'); const invoices = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/invoices');
for (const invoice of invoices) { for (const invoice of invoices) {
const invoiceName = invoice.invoice_number; const invoiceName = invoice.invoice_number;
const invoiceId = invoice.id; const invoiceId = invoice.id;
@ -230,7 +196,7 @@ export class InvoiceNinja implements INodeType {
// select them easily // select them easily
async getVendors(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getVendors(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
const vendors = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/vendors'); const vendors = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/vendors');
for (const vendor of vendors) { for (const vendor of vendors) {
const vendorName = vendor.name; const vendorName = vendor.name;
const vendorId = vendor.id; const vendorId = vendor.id;
@ -245,7 +211,7 @@ export class InvoiceNinja implements INodeType {
// select them easily // select them easily
async getExpenseCategories(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { async getExpenseCategories(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const returnData: INodePropertyOptions[] = []; const returnData: INodePropertyOptions[] = [];
const categories = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/expense_categories'); const categories = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/expense_categories');
for (const category of categories) { for (const category of categories) {
const categoryName = category.name; const categoryName = category.name;
const categoryId = category.id; const categoryId = category.id;
@ -306,8 +272,8 @@ export class InvoiceNinja implements INodeType {
last_name: contactValue.lastName as string, last_name: contactValue.lastName as string,
email: contactValue.email as string, email: contactValue.email as string,
phone: contactValue.phone as string, phone: contactValue.phone as string,
} };
contacts.push(contact) contacts.push(contact);
} }
body.contacts = contacts; body.contacts = contacts;
} }
@ -329,7 +295,7 @@ export class InvoiceNinja implements INodeType {
body.postal_code = billingAddressValue.postalCode as string; body.postal_code = billingAddressValue.postalCode as string;
body.country_id = parseInt(billingAddressValue.countryCode as string, 10); body.country_id = parseInt(billingAddressValue.countryCode as string, 10);
} }
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/clients', body); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/clients', body);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'get') { if (operation === 'get') {
@ -338,7 +304,7 @@ export class InvoiceNinja implements INodeType {
if (options.include) { if (options.include) {
qs.include = options.include as string; qs.include = options.include as string;
} }
responseData = await invoiceninjaApiRequest.call(this, 'GET', `/clients/${clientId}`, {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', `/clients/${clientId}`, {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'getAll') { if (operation === 'getAll') {
@ -348,16 +314,16 @@ export class InvoiceNinja implements INodeType {
qs.include = options.include as string; qs.include = options.include as string;
} }
if (returnAll === true) { if (returnAll === true) {
responseData = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/clients', {}, qs); responseData = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/clients', {}, qs);
} else { } else {
qs.per_page = this.getNodeParameter('limit', 0) as number; qs.per_page = this.getNodeParameter('limit', 0) as number;
responseData = await invoiceninjaApiRequest.call(this, 'GET', '/clients', {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', '/clients', {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
} }
if (operation === 'delete') { if (operation === 'delete') {
const clientId = this.getNodeParameter('clientId', i) as string; const clientId = this.getNodeParameter('clientId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'DELETE', `/clients/${clientId}`); responseData = await invoiceNinjaApiRequest.call(this, 'DELETE', `/clients/${clientId}`);
responseData = responseData.data; responseData = responseData.data;
} }
} }
@ -444,17 +410,17 @@ export class InvoiceNinja implements INodeType {
tax_rate2: itemValue.taxRate2 as number, tax_rate2: itemValue.taxRate2 as number,
tax_name1: itemValue.taxName1 as string, tax_name1: itemValue.taxName1 as string,
tax_name2: itemValue.taxName2 as string, tax_name2: itemValue.taxName2 as string,
} };
items.push(item) items.push(item);
} }
body.invoice_items = items; body.invoice_items = items;
} }
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/invoices', body); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/invoices', body);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'email') { if (operation === 'email') {
const invoiceId = this.getNodeParameter('invoiceId', i) as string; const invoiceId = this.getNodeParameter('invoiceId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/email_invoice', { id: invoiceId }); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/email_invoice', { id: invoiceId });
} }
if (operation === 'get') { if (operation === 'get') {
const invoiceId = this.getNodeParameter('invoiceId', i) as string; const invoiceId = this.getNodeParameter('invoiceId', i) as string;
@ -462,7 +428,7 @@ export class InvoiceNinja implements INodeType {
if (options.include) { if (options.include) {
qs.include = options.include as string; qs.include = options.include as string;
} }
responseData = await invoiceninjaApiRequest.call(this, 'GET', `/invoices/${invoiceId}`, {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', `/invoices/${invoiceId}`, {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'getAll') { if (operation === 'getAll') {
@ -475,16 +441,16 @@ export class InvoiceNinja implements INodeType {
qs.invoice_number = options.invoiceNumber as string; qs.invoice_number = options.invoiceNumber as string;
} }
if (returnAll === true) { if (returnAll === true) {
responseData = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/invoices', {}, qs); responseData = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/invoices', {}, qs);
} else { } else {
qs.per_page = this.getNodeParameter('limit', 0) as number; qs.per_page = this.getNodeParameter('limit', 0) as number;
responseData = await invoiceninjaApiRequest.call(this, 'GET', '/invoices', {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', '/invoices', {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
} }
if (operation === 'delete') { if (operation === 'delete') {
const invoiceId = this.getNodeParameter('invoiceId', i) as string; const invoiceId = this.getNodeParameter('invoiceId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'DELETE', `/invoices/${invoiceId}`); responseData = await invoiceNinjaApiRequest.call(this, 'DELETE', `/invoices/${invoiceId}`);
responseData = responseData.data; responseData = responseData.data;
} }
} }
@ -519,13 +485,13 @@ export class InvoiceNinja implements INodeType {
to = new Date(logValue.endDate as string).getTime()/1000 as number; to = new Date(logValue.endDate as string).getTime()/1000 as number;
} }
if (logValue.duration) { if (logValue.duration) {
to = from + (logValue.duration as number * 3600) to = from + (logValue.duration as number * 3600);
} }
logs.push([from as number, to as number]); logs.push([from as number, to as number]);
} }
body.time_log = JSON.stringify(logs); body.time_log = JSON.stringify(logs);
} }
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/tasks', body); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/tasks', body);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'get') { if (operation === 'get') {
@ -534,7 +500,7 @@ export class InvoiceNinja implements INodeType {
if (options.include) { if (options.include) {
qs.include = options.include as string; qs.include = options.include as string;
} }
responseData = await invoiceninjaApiRequest.call(this, 'GET', `/tasks/${taskId}`, {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', `/tasks/${taskId}`, {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'getAll') { if (operation === 'getAll') {
@ -544,16 +510,16 @@ export class InvoiceNinja implements INodeType {
qs.include = options.include as string; qs.include = options.include as string;
} }
if (returnAll === true) { if (returnAll === true) {
responseData = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/tasks', {}, qs); responseData = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/tasks', {}, qs);
} else { } else {
qs.per_page = this.getNodeParameter('limit', 0) as number; qs.per_page = this.getNodeParameter('limit', 0) as number;
responseData = await invoiceninjaApiRequest.call(this, 'GET', '/tasks', {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', '/tasks', {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
} }
if (operation === 'delete') { if (operation === 'delete') {
const taskId = this.getNodeParameter('taskId', i) as string; const taskId = this.getNodeParameter('taskId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'DELETE', `/tasks/${taskId}`); responseData = await invoiceNinjaApiRequest.call(this, 'DELETE', `/tasks/${taskId}`);
responseData = responseData.data; responseData = responseData.data;
} }
} }
@ -575,7 +541,7 @@ export class InvoiceNinja implements INodeType {
if (additionalFields.privateNotes) { if (additionalFields.privateNotes) {
body.private_notes = additionalFields.privateNotes as string; body.private_notes = additionalFields.privateNotes as string;
} }
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/payments', body); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/payments', body);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'get') { if (operation === 'get') {
@ -584,7 +550,7 @@ export class InvoiceNinja implements INodeType {
if (options.include) { if (options.include) {
qs.include = options.include as string; qs.include = options.include as string;
} }
responseData = await invoiceninjaApiRequest.call(this, 'GET', `/payments/${paymentId}`, {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', `/payments/${paymentId}`, {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'getAll') { if (operation === 'getAll') {
@ -594,16 +560,16 @@ export class InvoiceNinja implements INodeType {
qs.include = options.include as string; qs.include = options.include as string;
} }
if (returnAll === true) { if (returnAll === true) {
responseData = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/payments', {}, qs); responseData = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/payments', {}, qs);
} else { } else {
qs.per_page = this.getNodeParameter('limit', 0) as number; qs.per_page = this.getNodeParameter('limit', 0) as number;
responseData = await invoiceninjaApiRequest.call(this, 'GET', '/payments', {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', '/payments', {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
} }
if (operation === 'delete') { if (operation === 'delete') {
const paymentId = this.getNodeParameter('paymentId', i) as string; const paymentId = this.getNodeParameter('paymentId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'DELETE', `/payments/${paymentId}`); responseData = await invoiceNinjaApiRequest.call(this, 'DELETE', `/payments/${paymentId}`);
responseData = responseData.data; responseData = responseData.data;
} }
} }
@ -611,6 +577,9 @@ export class InvoiceNinja implements INodeType {
if (operation === 'create') { if (operation === 'create') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
const body: IExpense = {}; const body: IExpense = {};
if (additionalFields.amount) {
body.amount = additionalFields.amount as number;
}
if (additionalFields.billable) { if (additionalFields.billable) {
body.should_be_invoiced = additionalFields.billable as boolean; body.should_be_invoiced = additionalFields.billable as boolean;
} }
@ -659,27 +628,27 @@ export class InvoiceNinja implements INodeType {
if (additionalFields.vendor) { if (additionalFields.vendor) {
body.vendor_id = additionalFields.vendor as number; body.vendor_id = additionalFields.vendor as number;
} }
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/expenses', body); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/expenses', body);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'get') { if (operation === 'get') {
const expenseId = this.getNodeParameter('expenseId', i) as string; const expenseId = this.getNodeParameter('expenseId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'GET', `/expenses/${expenseId}`, {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', `/expenses/${expenseId}`, {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'getAll') { if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', 0) as boolean; const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
if (returnAll === true) { if (returnAll === true) {
responseData = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/payments', {}, qs); responseData = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/expenses', {}, qs);
} else { } else {
qs.per_page = this.getNodeParameter('limit', 0) as number; qs.per_page = this.getNodeParameter('limit', 0) as number;
responseData = await invoiceninjaApiRequest.call(this, 'GET', '/payments', {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', '/expenses', {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
} }
if (operation === 'delete') { if (operation === 'delete') {
const expenseId = this.getNodeParameter('expenseId', i) as string; const expenseId = this.getNodeParameter('expenseId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'DELETE', `/expenses/${expenseId}`); responseData = await invoiceNinjaApiRequest.call(this, 'DELETE', `/expenses/${expenseId}`);
responseData = responseData.data; responseData = responseData.data;
} }
} }
@ -752,8 +721,8 @@ export class InvoiceNinja implements INodeType {
if (additionalFields.paid) { if (additionalFields.paid) {
body.paid = additionalFields.paid as number; body.paid = additionalFields.paid as number;
} }
if (additionalFields.emailQoute) { if (additionalFields.emailQuote) {
body.email_invoice = additionalFields.emailQoute as boolean; body.email_invoice = additionalFields.emailQuote as boolean;
} }
const invoceItemsValues = (this.getNodeParameter('invoiceItemsUi', i) as IDataObject).invoiceItemsValues as IDataObject[]; const invoceItemsValues = (this.getNodeParameter('invoiceItemsUi', i) as IDataObject).invoiceItemsValues as IDataObject[];
if (invoceItemsValues) { if (invoceItemsValues) {
@ -768,17 +737,17 @@ export class InvoiceNinja implements INodeType {
tax_rate2: itemValue.taxRate2 as number, tax_rate2: itemValue.taxRate2 as number,
tax_name1: itemValue.taxName1 as string, tax_name1: itemValue.taxName1 as string,
tax_name2: itemValue.taxName2 as string, tax_name2: itemValue.taxName2 as string,
} };
items.push(item) items.push(item);
} }
body.invoice_items = items; body.invoice_items = items;
} }
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/invoices', body); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/invoices', body);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'email') { if (operation === 'email') {
const quoteId = this.getNodeParameter('quoteId', i) as string; const quoteId = this.getNodeParameter('quoteId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'POST', '/email_invoice', { id: quoteId }); responseData = await invoiceNinjaApiRequest.call(this, 'POST', '/email_invoice', { id: quoteId });
} }
if (operation === 'get') { if (operation === 'get') {
const quoteId = this.getNodeParameter('quoteId', i) as string; const quoteId = this.getNodeParameter('quoteId', i) as string;
@ -786,7 +755,7 @@ export class InvoiceNinja implements INodeType {
if (options.include) { if (options.include) {
qs.include = options.include as string; qs.include = options.include as string;
} }
responseData = await invoiceninjaApiRequest.call(this, 'GET', `/invoices/${quoteId}`, {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', `/invoices/${quoteId}`, {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
if (operation === 'getAll') { if (operation === 'getAll') {
@ -799,16 +768,16 @@ export class InvoiceNinja implements INodeType {
qs.invoice_number = options.invoiceNumber as string; qs.invoice_number = options.invoiceNumber as string;
} }
if (returnAll === true) { if (returnAll === true) {
responseData = await invoiceninjaApiRequestAllItems.call(this, 'data', 'GET', '/quotes', {}, qs); responseData = await invoiceNinjaApiRequestAllItems.call(this, 'data', 'GET', '/quotes', {}, qs);
} else { } else {
qs.per_page = this.getNodeParameter('limit', 0) as number; qs.per_page = this.getNodeParameter('limit', 0) as number;
responseData = await invoiceninjaApiRequest.call(this, 'GET', '/quotes', {}, qs); responseData = await invoiceNinjaApiRequest.call(this, 'GET', '/quotes', {}, qs);
responseData = responseData.data; responseData = responseData.data;
} }
} }
if (operation === 'delete') { if (operation === 'delete') {
const quoteId = this.getNodeParameter('quoteId', i) as string; const quoteId = this.getNodeParameter('quoteId', i) as string;
responseData = await invoiceninjaApiRequest.call(this, 'DELETE', `/invoices/${quoteId}`); responseData = await invoiceNinjaApiRequest.call(this, 'DELETE', `/invoices/${quoteId}`);
responseData = responseData.data; responseData = responseData.data;
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -10,7 +10,7 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
invoiceninjaApiRequest, invoiceNinjaApiRequest,
} from './GenericFunctions'; } from './GenericFunctions';
export class InvoiceNinjaTrigger implements INodeType { export class InvoiceNinjaTrigger implements INodeType {
@ -29,26 +29,8 @@ export class InvoiceNinjaTrigger implements INodeType {
outputs: ['main'], outputs: ['main'],
credentials: [ credentials: [
{ {
name: 'invoiceNinjaCloudApi', name: 'invoiceNinjaApi',
required: true, required: true,
displayOptions: {
show: {
invoiceNinjaVersion: [
'cloud',
],
},
},
},
{
name: 'invoiceNinjaServerApi',
required: true,
displayOptions: {
show: {
invoiceNinjaVersion: [
'server',
],
},
},
}, },
], ],
webhooks: [ webhooks: [
@ -60,45 +42,29 @@ export class InvoiceNinjaTrigger implements INodeType {
}, },
], ],
properties: [ properties: [
{
displayName: 'Version',
name: 'invoiceNinjaVersion',
type: 'options',
options: [
{
name: 'Cloud',
value: 'cloud',
},
{
name: 'Server (Self Hosted)',
value: 'server',
},
],
default: 'cloud',
},
{ {
displayName: 'Event', displayName: 'Event',
name: 'event', name: 'event',
type: 'options', type: 'options',
options: [ options: [
{ {
name: 'client.created', name: 'Client Created',
value: 'create_client', value: 'create_client',
}, },
{ {
name: 'invoce.created', name: 'Invoice Created',
value: 'create_invoice', value: 'create_invoice',
}, },
{ {
name: 'payment.created', name: 'Payment Created',
value: 'create_payment', value: 'create_payment',
}, },
{ {
name: 'quote.created', name: 'Quote Created',
value: 'create_quote', value: 'create_quote',
}, },
{ {
name: 'vendor.created', name: 'Vendor Created',
value: 'create_vendor', value: 'create_vendor',
}, },
], ],
@ -126,7 +92,7 @@ export class InvoiceNinjaTrigger implements INodeType {
event, event,
}; };
const responseData = await invoiceninjaApiRequest.call(this, 'POST', endpoint, body); const responseData = await invoiceNinjaApiRequest.call(this, 'POST', endpoint, body);
if (responseData.id === undefined) { if (responseData.id === undefined) {
// Required data is missing so was not successful // Required data is missing so was not successful
@ -145,7 +111,7 @@ export class InvoiceNinjaTrigger implements INodeType {
const endpoint = `/hooks/${webhookData.webhookId}`; const endpoint = `/hooks/${webhookData.webhookId}`;
try { try {
await invoiceninjaApiRequest.call(this, 'DELETE', endpoint); await invoiceNinjaApiRequest.call(this, 'DELETE', endpoint);
} catch (e) { } catch (e) {
return false; return false;
} }

View file

@ -18,6 +18,11 @@ export const paymentOperations = [
value: 'create', value: 'create',
description: 'Create a new payment', description: 'Create a new payment',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a payment',
},
{ {
name: 'Get', name: 'Get',
value: 'get', value: 'get',
@ -28,11 +33,6 @@ export const paymentOperations = [
value: 'getAll', value: 'getAll',
description: 'Get data of all payments', description: 'Get data of all payments',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a payment',
}
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',

View file

@ -18,6 +18,11 @@ export const quoteOperations = [
value: 'create', value: 'create',
description: 'Create a new quote', description: 'Create a new quote',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a quote',
},
{ {
name: 'Email', name: 'Email',
value: 'email', value: 'email',
@ -33,11 +38,6 @@ export const quoteOperations = [
value: 'getAll', value: 'getAll',
description: 'Get data of all quotes', description: 'Get data of all quotes',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a quote',
}
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',
@ -117,8 +117,8 @@ export const quoteFields = [
default: '', default: '',
}, },
{ {
displayName: 'Email Qoute', displayName: 'Email Quote',
name: 'emailQoute', name: 'emailQuote',
type: 'boolean', type: 'boolean',
default: false, default: false,
}, },
@ -135,7 +135,7 @@ export const quoteFields = [
default: '', default: '',
}, },
{ {
displayName: 'Qoute Status', displayName: 'Quote Status',
name: 'quoteStatus', name: 'quoteStatus',
type: 'options', type: 'options',
options: [ options: [
@ -351,7 +351,7 @@ export const quoteFields = [
/* quote:get */ /* quote:get */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'Qoute ID', displayName: 'Quote ID',
name: 'quoteId', name: 'quoteId',
type: 'string', type: 'string',
required: true, required: true,
@ -459,7 +459,7 @@ export const quoteFields = [
}, },
options: [ options: [
{ {
displayName: 'Qoute Number', displayName: 'Quote Number',
name: 'quoteNumber', name: 'quoteNumber',
type: 'string', type: 'string',
default: '', default: '',

View file

@ -18,6 +18,11 @@ export const taskOperations = [
value: 'create', value: 'create',
description: 'Create a new task', description: 'Create a new task',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a task',
},
{ {
name: 'Get', name: 'Get',
value: 'get', value: 'get',
@ -28,11 +33,6 @@ export const taskOperations = [
value: 'getAll', value: 'getAll',
description: 'Get data of all tasks', description: 'Get data of all tasks',
}, },
{
name: 'Delete',
value: 'delete',
description: 'Delete a task',
}
], ],
default: 'create', default: 'create',
description: 'The operation to perform.', description: 'The operation to perform.',

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -62,8 +62,7 @@
"dist/credentials/HunterApi.credentials.js", "dist/credentials/HunterApi.credentials.js",
"dist/credentials/Imap.credentials.js", "dist/credentials/Imap.credentials.js",
"dist/credentials/IntercomApi.credentials.js", "dist/credentials/IntercomApi.credentials.js",
"dist/credentials/InvoiceNinjaCloudApi.credentials.js", "dist/credentials/InvoiceNinjaApi.credentials.js",
"dist/credentials/InvoiceNinjaServerApi.credentials.js",
"dist/credentials/JiraSoftwareCloudApi.credentials.js", "dist/credentials/JiraSoftwareCloudApi.credentials.js",
"dist/credentials/JiraSoftwareServerApi.credentials.js", "dist/credentials/JiraSoftwareServerApi.credentials.js",
"dist/credentials/JotFormApi.credentials.js", "dist/credentials/JotFormApi.credentials.js",