Skip to content

Commit

Permalink
feat: get many expenses
Browse files Browse the repository at this point in the history
  • Loading branch information
rfdez committed Sep 25, 2023
1 parent a618030 commit f26ac78
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 10 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes

- Expenses
- Create an expense (in equally split mode)
- List the current user's expenses

## Credentials

Expand All @@ -41,7 +42,7 @@ If you are using the OAuth 2.0 authentication method, you need to copy the callb

## Compatibility

This node was tested against Splitwise API 3.0.0 and n8n 1.5.1.
This node was tested against Splitwise API 3.0.0 and n8n 1.7.1.

## Usage

Expand Down
96 changes: 95 additions & 1 deletion nodes/Splitwise/ExpenseDescription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ export const expenseOperations: INodeProperties[] = [
description: 'Create an expense',
action: 'Create an expense',
},
{
name: 'Get Many',
value: 'getAll',
description: "List the current user's expenses",
action: 'Get many expenses',
},
],
},
];
Expand Down Expand Up @@ -185,4 +191,92 @@ const createExpenseFields: INodeProperties[] = [
},
];

export const expenseFields: INodeProperties[] = [...createExpenseFields];
const getAllExpenseFields: INodeProperties[] = [
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['expense'],
operation: ['getAll'],
},
},
options: [
{
displayName: 'Group Name or ID',
name: 'group_id',
type: 'options',
description:
'Name or ID of the group to get the expenses. If provided, only expenses in that group will be returned, and `friend_id` will be ignored. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
default: '',
typeOptions: {
loadOptionsMethod: 'getGroups',
},
},
{
displayName: 'Friend Name or ID',
name: 'friend_id',
type: 'options',
description:
'Name or ID of another user. If provided, only expenses between the current and provided user will be returned. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.',
default: '',
typeOptions: {
loadOptionsMethod: 'getFriends',
},
},
{
displayName: 'Dated After',
name: 'dated_after',
type: 'dateTime',
description: 'Only expenses dated after this date will be returned',
default: '',
},
{
displayName: 'Dated Before',
name: 'dated_before',
type: 'dateTime',
description: 'Only expenses dated before this date will be returned',
default: '',
},
{
displayName: 'Updated After',
name: 'updated_after',
type: 'dateTime',
description: 'Only expenses updated after this date will be returned',
default: '',
},
{
displayName: 'Updated Before',
name: 'updated_before',
type: 'dateTime',
description: 'Only expenses updated before this date will be returned',
default: '',
},
{
displayName: 'Limit',
name: 'limit',
description: 'Max number of results to return',
type: 'number',
default: 50,
typeOptions: {
minValue: 1,
},
},
{
displayName: 'Offset',
name: 'offset',
description: 'Number of results to skip',
type: 'number',
default: 0,
typeOptions: {
minValue: 0,
},
},
],
},
];

export const expenseFields: INodeProperties[] = [...createExpenseFields, ...getAllExpenseFields];
34 changes: 34 additions & 0 deletions nodes/Splitwise/GenericFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,37 @@ export async function getGroups(this: ILoadOptionsFunctions): Promise<INodePrope

return returnData;
}

export async function getFriends(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const endpoint = '/get_friends';
const responseData = await splitwiseApiRequest.call(this, 'GET', endpoint, {});

if (responseData.friends === undefined) {
throw new NodeApiError(this.getNode(), responseData as JsonObject, {
message: 'No data got returned',
});
}

const returnData: INodePropertyOptions[] = [];
for (const friend of responseData.friends) {
const friendName = `${friend.first_name} ${friend.last_name}`;
const friendId = friend.id;

returnData.push({
name: friendName,
value: friendId,
});
}

returnData.sort((a, b) => {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});

return returnData;
}
62 changes: 55 additions & 7 deletions nodes/Splitwise/Splitwise.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import {
NodeOperationError,
} from 'n8n-workflow';
import { expenseFields, expenseOperations } from './ExpenseDescription';
import { getCategories, getCurrencies, getGroups, splitwiseApiRequest } from './GenericFunctions';
import {
getCategories,
getCurrencies,
getGroups,
getFriends,
splitwiseApiRequest,
} from './GenericFunctions';

export class Splitwise implements INodeType {
description: INodeTypeDescription = {
Expand Down Expand Up @@ -90,6 +96,7 @@ export class Splitwise implements INodeType {
getCategories,
getCurrencies,
getGroups,
getFriends,
},
};

Expand All @@ -100,8 +107,15 @@ export class Splitwise implements INodeType {
const resource = this.getNodeParameter('resource', 0) as string;
const operation = this.getNodeParameter('operation', 0) as string;

let body: IDataObject;
let query: IDataObject;
let responseData;

for (let i = 0; i < items.length; i++) {
try {
body = {};
query = {};

if (resource === 'expense') {
if (operation === 'create') {
const cost = this.getNodeParameter('cost', i) as number;
Expand All @@ -111,7 +125,7 @@ export class Splitwise implements INodeType {
const groupId = this.getNodeParameter('group_id', i) as number;
const splitEqually = this.getNodeParameter('split_equally', i) as boolean;

const body: IDataObject = {
body = {
cost: cost.toFixed(2),
description,
currency_code: currencyCode,
Expand All @@ -126,16 +140,50 @@ export class Splitwise implements INodeType {
Object.assign(body, additionalFields);
}

const response = await splitwiseApiRequest.call(this, 'POST', '/create_expense', body);
responseData = await splitwiseApiRequest.call(this, 'POST', '/create_expense', body);

if (response.error || response.errors?.base?.length) {
const errorMessage = response.error ? response.error : response.errors.base[0];
if (responseData.error || responseData.errors?.base?.length) {
const errorMessage = responseData.error
? responseData.error
: responseData.errors.base[0];
throw new NodeOperationError(this.getNode(), errorMessage, { itemIndex: i });
}

returnData.push(response.expenses);
responseData = responseData.expense;
}

if (operation === 'getAll') {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;

if (!additionalFields.limit) {
additionalFields.limit = 50;
}

if (Object.keys(additionalFields).length) {
Object.assign(query, additionalFields);
}

responseData = await splitwiseApiRequest.call(this, 'GET', '/get_expenses', {}, query);

if (responseData.error || responseData.errors?.base?.length) {
const errorMessage = responseData.error
? responseData.error
: responseData.errors.base[0];
throw new NodeOperationError(this.getNode(), errorMessage, { itemIndex: i });
}

responseData = responseData.expenses;
}
}

returnData.push(
...this.helpers.constructExecutionMetaData(
this.helpers.returnJsonArray(responseData as IDataObject[]),
{
itemData: { item: i },
},
),
);
} catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
Expand All @@ -146,6 +194,6 @@ export class Splitwise implements INodeType {
}
}

return [this.helpers.returnJsonArray(returnData)];
return [returnData as INodeExecutionData[]];
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rfdez/n8n-nodes-splitwise",
"version": "0.1.1",
"version": "0.2.0",
"description": "n8n community node to consume the Splitwise API",
"keywords": [
"n8n-community-node-package"
Expand Down

0 comments on commit f26ac78

Please sign in to comment.