Add QuickBooks transactions report (#2040)

* add get QBO report: transaction list

* merge upstream with n8n master

* Update QuickBooks.node.ts

* add back transaction list resource

*  Refactor transactions list expansion

*  Alphabetize options

*  Fix param type of source account types

*  Add missing description

*  Improve memo display name

*  Fix default values

*  Fix casing

* 🔥 Remove logging

*  Remove time from dates

* 🔨 Rename operation

*  Add simplify response toggle

* 🐛 Fix issue when transaction:getReport does not return data

Co-authored-by: Calvin Tan <calvin14@gmail.com>
Co-authored-by: ricardo <ricardoespinoza105@gmail.com>
This commit is contained in:
Iván Ovejero
2021-08-13 11:45:26 +02:00
committed by GitHub
parent 0bfc00c129
commit eb05e90197
6 changed files with 804 additions and 3 deletions

View File

@@ -22,6 +22,7 @@ import {
} from 'change-case';
import {
omit,
pickBy,
} from 'lodash';
@@ -30,7 +31,10 @@ import {
} from 'request';
import {
DateFieldsUi,
Option,
QuickBooksOAuth2Credentials,
TransactionReport,
} from './types';
/**
@@ -123,12 +127,22 @@ export async function quickBooksApiRequestAllItems(
const maxCount = await getCount.call(this, method, endpoint, qs);
const originalQuery = qs.query;
const originalQuery = qs.query as string;
do {
qs.query = `${originalQuery} MAXRESULTS ${maxResults} STARTPOSITION ${startPosition}`;
responseData = await quickBooksApiRequest.call(this, method, endpoint, qs, body);
returnData.push(...responseData.QueryResponse[capitalCase(resource)]);
try {
const nonResource = originalQuery.split(' ')?.pop();
if (nonResource === 'CreditMemo' || nonResource === 'Term') {
returnData.push(...responseData.QueryResponse[nonResource]);
} else {
returnData.push(...responseData.QueryResponse[capitalCase(resource)]);
}
} catch (error) {
return [];
}
startPosition += maxResults;
} while (maxCount > returnData.length);
@@ -273,7 +287,7 @@ export async function loadResource(
resourceItems.forEach((resourceItem: { DisplayName: string, Name: string, Id: string }) => {
returnData.push({
name: resourceItem.DisplayName || resourceItem.Name,
name: resourceItem.DisplayName || resourceItem.Name || `Memo ${resourceItem.Id}`,
value: resourceItem.Id,
});
});
@@ -428,3 +442,63 @@ export function populateFields(
});
return body;
}
export const toOptions = (option: string) => ({ name: option, value: option });
export const toDisplayName = ({ name, value }: Option) => {
return { name: splitPascalCase(name), value };
};
export const splitPascalCase = (word: string) => {
return word.match(/($[a-z])|[A-Z][^A-Z]+/g)?.join(' ');
};
export function adjustTransactionDates(
transactionFields: IDataObject & DateFieldsUi,
): IDataObject {
const dateFieldKeys = [
'dateRangeCustom',
'dateRangeDueCustom',
'dateRangeModificationCustom',
'dateRangeCreationCustom',
] as const;
if (dateFieldKeys.every(dateField => !transactionFields[dateField])) {
return transactionFields;
}
let adjusted = omit(transactionFields, dateFieldKeys) as IDataObject;
dateFieldKeys.forEach(dateFieldKey => {
const dateField = transactionFields[dateFieldKey];
if (dateField) {
Object.entries(dateField[`${dateFieldKey}Properties`]).map(([key, value]) =>
dateField[`${dateFieldKey}Properties`][key] = value.split('T')[0],
);
adjusted = {
...adjusted,
...dateField[`${dateFieldKey}Properties`],
};
}
});
return adjusted;
}
export function simplifyTransactionReport(transactionReport: TransactionReport) {
const columns = transactionReport.Columns.Column.map((column) => column.ColType);
const rows = transactionReport.Rows.Row.map((row) => row.ColData.map(i => i.value));
const simplified = [];
for (const row of rows) {
const transaction: { [key: string]: string } = {};
for (let i = 0; i < row.length; i++) {
transaction[columns[i]] = row[i];
}
simplified.push(transaction);
}
return simplified;
}