feat(core): Add support for CI workflows and update gitignore
This commit is contained in:
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* autocreated commitinfo by @push.rocks/commitinfo
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@fin.cx/csvparser',
|
||||
version: '1.1.0',
|
||||
description: 'A TypeScript-based parser for CSV files from various financial service providers.'
|
||||
}
|
98
ts/commerzbank/csv-commerzbank.classes.csvcommerzbank.ts
Normal file
98
ts/commerzbank/csv-commerzbank.classes.csvcommerzbank.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import * as plugins from '../csvparser.plugins.js';
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
export class CsvCommerzbank extends plugins.portablefinance
|
||||
.AcCsvParser<interfaces.ICommerzbankTransaction> {
|
||||
// INSTANCE
|
||||
public paymentProviderName = 'Commerzbank';
|
||||
public description: string = `a csv parser for parsing downloaded csv transaction files from Commerzbank`;
|
||||
private csvDescriptorArray: plugins.portablefinance.ICsvDescriptor[] = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
addCsvDecriptor(csvDescriptorArg: plugins.portablefinance.ICsvDescriptor): void {
|
||||
this.csvDescriptorArray.push(csvDescriptorArg);
|
||||
}
|
||||
|
||||
public async getTransactions(): Promise<plugins.portablefinance.IMonetaryTransaction[]> {
|
||||
const payments: interfaces.ICommerzbankOriginalTransaction[] = [];
|
||||
|
||||
for (const csvDescriptor of this.csvDescriptorArray) {
|
||||
const csvInstance = await plugins.smartcsv.Csv.createCsvFromString(csvDescriptor.contentString, {
|
||||
headers: true,
|
||||
unquote: true,
|
||||
});
|
||||
|
||||
payments.push(
|
||||
...(await csvInstance.exportAsObject())
|
||||
);
|
||||
}
|
||||
|
||||
const finalTransactionArray: interfaces.ICommerzbankTransaction[] = [];
|
||||
for (const transaction of payments) {
|
||||
// transaction.Buchungstag = transaction.Wertstellung;
|
||||
console.log(transaction);
|
||||
const finalTransaction: interfaces.ICommerzbankTransaction = {
|
||||
simpleTransaction: null,
|
||||
transactionHash: null,
|
||||
original: transaction,
|
||||
amount: plugins.smartmoney.parseEuropeanNumberString(transaction.Betrag),
|
||||
currency: transaction.Währung,
|
||||
description: transaction.Buchungstext,
|
||||
transactionDate: plugins.smarttime.ExtendedDate.fromEuropeanDate(transaction.Buchungstag),
|
||||
valuationDate: plugins.smarttime.ExtendedDate.fromEuropeanDate(transaction.Wertstellung),
|
||||
transactionType: ((): interfaces.TTransactionType => {
|
||||
switch (transaction.Umsatzart) {
|
||||
case 'Gutschrift':
|
||||
return 'Credit';
|
||||
case 'Lastschrift':
|
||||
return 'Debit';
|
||||
case 'Zinsen/Entgelte':
|
||||
return 'BankFees';
|
||||
case 'Überweisung':
|
||||
return 'ActiveTransfer';
|
||||
default:
|
||||
throw new Error(`unknown transactiontype ${transaction.Umsatzart}`);
|
||||
}
|
||||
})(),
|
||||
};
|
||||
|
||||
// lets assign the transactionHash
|
||||
finalTransaction.transactionHash = await plugins.smarthash.sha265FromObject({
|
||||
description: finalTransaction.description,
|
||||
amount: finalTransaction.amount,
|
||||
date: finalTransaction.valuationDate,
|
||||
});
|
||||
|
||||
finalTransaction.simpleTransaction = {
|
||||
id: finalTransaction.transactionHash,
|
||||
accountId: null,
|
||||
name: finalTransaction.description,
|
||||
amount: finalTransaction.amount,
|
||||
description: finalTransaction.description,
|
||||
date: finalTransaction.transactionDate,
|
||||
};
|
||||
finalTransactionArray.push(finalTransaction);
|
||||
}
|
||||
|
||||
return finalTransactionArray.map((commerzbankTransaction) => {
|
||||
const fin2021Transaction: plugins.portablefinance.IMonetaryTransaction = {
|
||||
id: null,
|
||||
data: {
|
||||
additionalIds: [],
|
||||
amount: commerzbankTransaction.amount,
|
||||
date: commerzbankTransaction.transactionDate.getTime(),
|
||||
description: commerzbankTransaction.description,
|
||||
name: commerzbankTransaction.description,
|
||||
originAccountId: null,
|
||||
originTransactionId: commerzbankTransaction.transactionHash,
|
||||
paymentAccountId: null,
|
||||
justForLooks: null,
|
||||
},
|
||||
};
|
||||
return fin2021Transaction;
|
||||
});
|
||||
}
|
||||
}
|
1
ts/commerzbank/index.ts
Normal file
1
ts/commerzbank/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './csv-commerzbank.classes.csvcommerzbank.js';
|
1
ts/commerzbank/interfaces/index.ts
Normal file
1
ts/commerzbank/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './interfaces.commerzbanktransaction.js';
|
@ -0,0 +1,30 @@
|
||||
import * as plugins from '../../csvparser.plugins.js';
|
||||
|
||||
export interface ICommerzbankOriginalTransaction {
|
||||
Buchungstag: string;
|
||||
Wertstellung: string;
|
||||
Umsatzart: 'Überweisung' | 'Gutschrift' | 'Lastschrift' | 'Zinsen/Entgelte';
|
||||
Buchungstext: string;
|
||||
Betrag: string;
|
||||
Währung: string;
|
||||
Auftraggeberkonto: string;
|
||||
'Bankleitzahl Auftraggeberkonto': string;
|
||||
'IBAN Auftraggeberkonto': string;
|
||||
Kategorie: string;
|
||||
}
|
||||
|
||||
export type TTransactionType = 'Credit' | 'Debit' | 'ActiveTransfer' | 'BankFees';
|
||||
|
||||
export interface ICommerzbankTransaction {
|
||||
simpleTransaction: plugins.tsclass.finance.ITransaction;
|
||||
transactionHash: string;
|
||||
original: ICommerzbankOriginalTransaction;
|
||||
|
||||
// translated to English
|
||||
transactionDate: plugins.smarttime.ExtendedDate;
|
||||
valuationDate: plugins.smarttime.ExtendedDate;
|
||||
transactionType: TTransactionType;
|
||||
description: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
}
|
26
ts/csvparser.plugins.ts
Normal file
26
ts/csvparser.plugins.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// node native scope
|
||||
import * as path from 'path';
|
||||
|
||||
export { path };
|
||||
|
||||
// fin.cx scope
|
||||
import * as portablefinance from '@fin.cx/portablefinance';
|
||||
|
||||
export {
|
||||
portablefinance
|
||||
}
|
||||
|
||||
// pushrocks scope
|
||||
import * as smartcsv from '@push.rocks/smartcsv';
|
||||
import * as smartfile from '@push.rocks/smartfile';
|
||||
import * as smarthash from '@push.rocks/smarthash';
|
||||
import * as smartmoney from '@push.rocks/smartmoney';
|
||||
import * as smartstring from '@push.rocks/smartstring';
|
||||
import * as smarttime from '@push.rocks/smarttime';
|
||||
|
||||
export { smartcsv, smartfile, smarthash, smartmoney, smartstring, smarttime };
|
||||
|
||||
// tsclass scope
|
||||
import * as tsclass from '@tsclass/tsclass';
|
||||
|
||||
export { tsclass };
|
55
ts/fidor/csv-fidor.classes.csvfidor.ts
Normal file
55
ts/fidor/csv-fidor.classes.csvfidor.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import * as plugins from '../csvparser.plugins.js';
|
||||
|
||||
import { ExtendedDate } from '@push.rocks/smarttime';
|
||||
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
export class CsvFidor extends plugins.portablefinance.AcCsvParser<plugins.portablefinance.IMonetaryTransaction> {
|
||||
|
||||
// INSTANCE
|
||||
public paymentProviderName: string = 'Fidor Bank AG';
|
||||
public description: string = 'a csv parser optimized for csv files from Fidor.';
|
||||
public csvDescriptorArray: plugins.portablefinance.ICsvDescriptor[] = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
addCsvDecriptor (csvDescriptorArg: plugins.portablefinance.ICsvDescriptor): void {
|
||||
this.csvDescriptorArray.push(csvDescriptorArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the transactions
|
||||
*/
|
||||
public async getTransactions(): Promise<plugins.portablefinance.IMonetaryTransaction[]> {
|
||||
const payments: plugins.portablefinance.IMonetaryTransaction[] = [];
|
||||
|
||||
for (const csvDescriptor of this.csvDescriptorArray) {
|
||||
const csvInstance = new plugins.smartcsv.Csv(csvDescriptor.contentString, {
|
||||
headers: true
|
||||
});
|
||||
|
||||
const fidorTransactionArray: interfaces.IFidorOriginalTransaction[] = await csvInstance.exportAsObject();
|
||||
for (const transaction of fidorTransactionArray) {
|
||||
payments.push({
|
||||
id: await plugins.smarthash.sha265FromObject(transaction),
|
||||
data: {
|
||||
additionalIds: [],
|
||||
amount: parseFloat(transaction.Wert.replace('.', '').replace(',', '.')),
|
||||
date: plugins.smarttime.ExtendedDate.fromEuropeanDate(transaction.Datum).getTime(),
|
||||
name: transaction.Beschreibung,
|
||||
description: transaction.Beschreibung2,
|
||||
originAccountId: null,
|
||||
originTransactionId: null,
|
||||
paymentAccountId: null,
|
||||
justForLooks: null,
|
||||
voucherData: null,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return payments;
|
||||
}
|
||||
}
|
1
ts/fidor/index.ts
Normal file
1
ts/fidor/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './csv-fidor.classes.csvfidor.js';
|
1
ts/fidor/interfaces/index.ts
Normal file
1
ts/fidor/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './interfaces.fidortransaction.js';
|
6
ts/fidor/interfaces/interfaces.fidortransaction.ts
Normal file
6
ts/fidor/interfaces/interfaces.fidortransaction.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface IFidorOriginalTransaction {
|
||||
Datum: string;
|
||||
Beschreibung: string;
|
||||
Beschreibung2: string;
|
||||
Wert: string;
|
||||
}
|
4
ts/index.ts
Normal file
4
ts/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './commerzbank/index.js';
|
||||
export * from './fidor/index.js';
|
||||
export * from './paypal/index.js';
|
||||
export * from './spendesk/index.js';
|
147
ts/paypal/csv-paypal.classes.csvpaypal.ts
Normal file
147
ts/paypal/csv-paypal.classes.csvpaypal.ts
Normal file
@ -0,0 +1,147 @@
|
||||
import * as plugins from '../csvparser.plugins.js';
|
||||
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
export class CsvPayPal extends plugins.portablefinance
|
||||
.AcCsvParser<plugins.portablefinance.IMonetaryTransaction> {
|
||||
// INSTANCE
|
||||
public paymentProviderName = 'PayPal';
|
||||
public description: string = 'a csv parser optimized for PayPal obtained csv files.';
|
||||
public csvDescriptorArray: plugins.portablefinance.ICsvDescriptor[] = [];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets transactions
|
||||
*/
|
||||
public async getTransactions() {
|
||||
const payments: plugins.portablefinance.IMonetaryTransaction[] = [];
|
||||
for (const csvDescriptor of this.csvDescriptorArray) {
|
||||
let stringToParse = csvDescriptor.contentString;
|
||||
stringToParse = stringToParse.replace(/"(.*?)"/gi, (match, p1, offset, originalString) => {
|
||||
return plugins.smartstring.base64.encodeUri(match);
|
||||
});
|
||||
const smartCsvInstance = new plugins.smartcsv.Csv(stringToParse, {
|
||||
headers: true,
|
||||
});
|
||||
const payPalTransactions: interfaces.IPayPalCsvOriginalTransaction[] = (
|
||||
await smartCsvInstance.exportAsObject()
|
||||
).map((originalTransaction) => {
|
||||
// tslint:disable-next-line: no-object-literal-type-assertion
|
||||
const decodedTransaction = {} as interfaces.IPayPalCsvOriginalTransaction;
|
||||
for (const key in originalTransaction) {
|
||||
if (originalTransaction[key]) {
|
||||
let finalKey = plugins.smartstring.base64.decode(key);
|
||||
finalKey = finalKey.replace(/['"]+/g, '');
|
||||
let finalValue = plugins.smartstring.base64.decode(originalTransaction[key]);
|
||||
finalValue = finalValue.replace(/['"]+/g, '');
|
||||
decodedTransaction[finalKey] = finalValue;
|
||||
}
|
||||
}
|
||||
// pushing the ready transaction
|
||||
return decodedTransaction;
|
||||
});
|
||||
|
||||
// adjust numberFormat
|
||||
const anf = (numberString: string): number => {
|
||||
return parseFloat(numberString.replace(/\,/g, '.'));
|
||||
};
|
||||
|
||||
const monetaryTransactions: interfaces.IPayPalTransaction[] = [];
|
||||
for (const originalTransaction of payPalTransactions) {
|
||||
const paypalTransaction: interfaces.IPayPalTransaction = {
|
||||
// assigned later
|
||||
transactionHash: null,
|
||||
simpleTransaction: null,
|
||||
|
||||
// assigned now
|
||||
originalTransaction,
|
||||
transactionDate: plugins.smarttime.ExtendedDate.fromEuropeanDateAndTime(
|
||||
originalTransaction.Datum,
|
||||
originalTransaction.Uhrzeit,
|
||||
'Europe/Berlin'
|
||||
),
|
||||
transactionCode: originalTransaction.Transaktionscode,
|
||||
linkedTransactionCode: originalTransaction['Zugehöriger Transaktionscode'],
|
||||
timezone: originalTransaction.Zeitzone,
|
||||
bankAccount: originalTransaction.Bankkonto,
|
||||
bankName: originalTransaction['Name der Bank'],
|
||||
brutto: anf(originalTransaction.Brutto),
|
||||
netto: anf(originalTransaction.Netto),
|
||||
credit: anf(originalTransaction.Guthaben),
|
||||
fee: anf(originalTransaction.Gebühr),
|
||||
processingAndShippingFee: anf(originalTransaction['Versand- und Bearbeitungsgebühr']),
|
||||
currency: originalTransaction.Währung,
|
||||
description: originalTransaction.Beschreibung,
|
||||
invoiceNumber: originalTransaction.Rechnungsnummer,
|
||||
name: originalTransaction.Name,
|
||||
payeeEmail: originalTransaction['Absender E-Mail-Adresse'],
|
||||
transactionTime: originalTransaction.Uhrzeit,
|
||||
vatAmount: anf(originalTransaction.Umsatzsteuer),
|
||||
};
|
||||
|
||||
monetaryTransactions.push(paypalTransaction);
|
||||
}
|
||||
|
||||
const foreignTransactions: interfaces.IPayPalTransaction[] = [];
|
||||
const eurTransactions: interfaces.IPayPalTransaction[] = monetaryTransactions.filter(
|
||||
(payPalTransaction: interfaces.IPayPalTransaction) => {
|
||||
const isEur = payPalTransaction.currency === 'EUR';
|
||||
if (isEur) {
|
||||
return true;
|
||||
} else {
|
||||
foreignTransactions.push(payPalTransaction);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
let finalReturnTransactions = eurTransactions.map((transaction) => {
|
||||
if (transaction.brutto > 0) {
|
||||
return transaction; // lets don't bother with payments from the bank
|
||||
}
|
||||
const eurTime = transaction.transactionDate.getTime();
|
||||
const foreignCandidates: interfaces.IPayPalTransaction[] = [];
|
||||
for (const foreignTransaction of foreignTransactions) {
|
||||
const foreignTime = foreignTransaction.transactionDate.getTime();
|
||||
if (eurTime === foreignTime) {
|
||||
foreignCandidates.push(foreignTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
if (foreignCandidates.length !== 2 && foreignCandidates.length !== 0) {
|
||||
console.log('error! Found a weird amoun of corresponding foreign transactions');
|
||||
}
|
||||
|
||||
if (foreignCandidates.length === 2) {
|
||||
const wantedForeignTransaction = foreignCandidates.find((foreignTransaction) => {
|
||||
return foreignTransaction.brutto < 0;
|
||||
});
|
||||
transaction.description = wantedForeignTransaction.description;
|
||||
transaction.payeeEmail = wantedForeignTransaction.payeeEmail;
|
||||
transaction.name = wantedForeignTransaction.name;
|
||||
}
|
||||
|
||||
return transaction;
|
||||
});
|
||||
|
||||
// lets assign simple transactions at last
|
||||
finalReturnTransactions = finalReturnTransactions.map((transaction) => {
|
||||
transaction.simpleTransaction = {
|
||||
accountId: null,
|
||||
id: transaction.transactionCode,
|
||||
amount: transaction.brutto,
|
||||
date: transaction.transactionDate,
|
||||
description: transaction.description,
|
||||
name: transaction.name,
|
||||
};
|
||||
return transaction;
|
||||
});
|
||||
|
||||
const csvPayPalInstance = new CsvPayPal(finalReturnTransactions);
|
||||
return csvPayPalInstance;
|
||||
}
|
||||
return payments;
|
||||
}
|
||||
}
|
1
ts/paypal/index.ts
Normal file
1
ts/paypal/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './csv-paypal.classes.csvpaypal';
|
1
ts/paypal/interfaces/index.ts
Normal file
1
ts/paypal/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './interfaces.paypaltransaction.js';
|
49
ts/paypal/interfaces/interfaces.paypaltransaction.ts
Normal file
49
ts/paypal/interfaces/interfaces.paypaltransaction.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import * as plugins from '../../csvparser.plugins.js';
|
||||
|
||||
export interface IPayPalCsvOriginalTransaction {
|
||||
Datum: string;
|
||||
Uhrzeit: string;
|
||||
Zeitzone: string;
|
||||
Beschreibung: string;
|
||||
Währung: string;
|
||||
Brutto: string;
|
||||
Gebühr: string;
|
||||
Netto: string;
|
||||
Guthaben: string;
|
||||
Transaktionscode: string;
|
||||
'Absender E-Mail-Adresse': string;
|
||||
Name: string;
|
||||
'Name der Bank': string;
|
||||
Bankkonto: string;
|
||||
'Versand- und Bearbeitungsgebühr': string;
|
||||
Umsatzsteuer: string;
|
||||
Rechnungsnummer: string;
|
||||
'Zugehöriger Transaktionscode': string;
|
||||
}
|
||||
|
||||
export interface IPayPalTransaction {
|
||||
// standardised
|
||||
simpleTransaction: plugins.tsclass.finance.ITransaction;
|
||||
originalTransaction;
|
||||
transactionHash: string;
|
||||
|
||||
// specific
|
||||
transactionCode: string;
|
||||
transactionDate: Date;
|
||||
transactionTime: string;
|
||||
timezone: string;
|
||||
description: string;
|
||||
currency: string;
|
||||
brutto: number;
|
||||
fee: number;
|
||||
netto: number;
|
||||
credit: number;
|
||||
payeeEmail: string;
|
||||
name: string;
|
||||
bankName: string;
|
||||
bankAccount: string;
|
||||
processingAndShippingFee: number;
|
||||
vatAmount: number;
|
||||
invoiceNumber: string;
|
||||
linkedTransactionCode: string;
|
||||
}
|
205
ts/spendesk/csv-spendesk.classes.csvspendesk.ts
Normal file
205
ts/spendesk/csv-spendesk.classes.csvspendesk.ts
Normal file
@ -0,0 +1,205 @@
|
||||
import * as plugins from '../csvparser.plugins.js';
|
||||
|
||||
import * as interfaces from './interfaces/index.js';
|
||||
|
||||
export class CsvSpendesk extends plugins.portablefinance.AcCsvParser<any> {
|
||||
// ========= STATIC ================
|
||||
/**
|
||||
* get the SpendeskData from an extracted direcotory
|
||||
* @param dirPath
|
||||
*/
|
||||
public static async fromFile(filePath: string): Promise<CsvSpendesk> {
|
||||
const reresolvedPath = plugins.path.resolve(filePath);
|
||||
const fileString = plugins.smartfile.fs.toStringSync(reresolvedPath);
|
||||
const csvSpendesk = await CsvSpendesk.fromCsvString(fileString);
|
||||
return csvSpendesk;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the SpendeskData from an extracted direcotory
|
||||
* @param dirPath
|
||||
*/
|
||||
public static async fromDir(dirPath: string): Promise<CsvSpendesk> {
|
||||
const foundFiles: string[] = await plugins.smartfile.fs.listFileTree(
|
||||
dirPath,
|
||||
'**/Spendesk*',
|
||||
true
|
||||
);
|
||||
|
||||
if (foundFiles.length === 0) {
|
||||
throw new Error('no files found!');
|
||||
}
|
||||
|
||||
const csvSpendesks: CsvSpendesk[] = [];
|
||||
|
||||
for (const foundFile of foundFiles) {
|
||||
const fileString = plugins.smartfile.fs.toStringSync(plugins.path.resolve(foundFile));
|
||||
plugins.path.join(dirPath, foundFile);
|
||||
csvSpendesks.push(await this.fromFile(foundFile));
|
||||
}
|
||||
|
||||
let returnCsvSpendesk: CsvSpendesk;
|
||||
for (const csvSpendeskInstance of csvSpendesks) {
|
||||
if (!returnCsvSpendesk) {
|
||||
returnCsvSpendesk = csvSpendeskInstance;
|
||||
} else {
|
||||
await returnCsvSpendesk.concat(csvSpendeskInstance);
|
||||
}
|
||||
}
|
||||
return returnCsvSpendesk;
|
||||
}
|
||||
|
||||
public static async fromCsvString(csvStringArg: string): Promise<CsvSpendesk> {
|
||||
// lets parse the data from the directory
|
||||
const csvInstance = await plugins.smartcsv.Csv.createCsvFromString(csvStringArg, {
|
||||
headers: true
|
||||
});
|
||||
|
||||
// lets differentiate between payments and credits
|
||||
const originalTransactionArray: interfaces.ISpendeskOriginalTransaction[] = (await csvInstance.exportAsObject()) as interfaces.ISpendeskOriginalTransaction[];
|
||||
const paymentsArray: interfaces.ISpendeskTransaction[] = [];
|
||||
for (const originalTransaction of originalTransactionArray) {
|
||||
const finalTransaction: interfaces.ISpendeskTransaction = {
|
||||
// the original transaction
|
||||
original: originalTransaction,
|
||||
|
||||
// assigned later
|
||||
paymentType: null,
|
||||
amount: null,
|
||||
simpleTransaction: null,
|
||||
transactionHash: null,
|
||||
|
||||
// assigned now
|
||||
currency: originalTransaction.Currency as interfaces.TAvailableCurrencies,
|
||||
description: originalTransaction.Description,
|
||||
expenseAccount: originalTransaction['Expense account'],
|
||||
month: originalTransaction.Month,
|
||||
payer: originalTransaction.Payer,
|
||||
paymentDate: new Date(originalTransaction['Payment date']),
|
||||
paymentMethod: originalTransaction['Payment method'],
|
||||
paymentState: originalTransaction.State as interfaces.TPaymentState,
|
||||
settlementDate: new Date(originalTransaction['Settlement date']),
|
||||
receiptAvailable: (() => {
|
||||
if ((originalTransaction['Receipt?'] as any) === 'Yes') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})(),
|
||||
receiptNames: [],
|
||||
supplier: originalTransaction.Supplier,
|
||||
team: originalTransaction.Team,
|
||||
vatAmount: parseFloat(originalTransaction.VAT),
|
||||
vatPercentage: ((): number => {
|
||||
if (!originalTransaction.VAT || originalTransaction.VAT === '0') {
|
||||
return 0;
|
||||
} else {
|
||||
const vatAmount = parseFloat(originalTransaction.VAT);
|
||||
const debitAmount = parseFloat(originalTransaction.Debit);
|
||||
return Math.round((vatAmount / (debitAmount - vatAmount)) * 100);
|
||||
}
|
||||
})()
|
||||
};
|
||||
|
||||
// type
|
||||
finalTransaction.paymentType = (() => {
|
||||
let paymentType: interfaces.TPaymentType;
|
||||
if (parseFloat(finalTransaction.original.Credit) !== 0) {
|
||||
paymentType = 'Load';
|
||||
} else if (parseFloat(originalTransaction.Debit) !== 0) {
|
||||
paymentType = 'Payment';
|
||||
}
|
||||
|
||||
if (originalTransaction.Description.startsWith('FX fee')) {
|
||||
paymentType = 'FXfee';
|
||||
}
|
||||
return paymentType;
|
||||
})();
|
||||
|
||||
// amount
|
||||
finalTransaction.amount = (() => {
|
||||
switch (parseFloat(originalTransaction.Credit)) {
|
||||
case 0:
|
||||
return -parseFloat(originalTransaction.Debit);
|
||||
default:
|
||||
return parseFloat(originalTransaction.Credit);
|
||||
}
|
||||
})();
|
||||
|
||||
// transaction hash
|
||||
finalTransaction.transactionHash = await plugins.smarthash.sha265FromObject({
|
||||
amount: finalTransaction.amount,
|
||||
transactionDate: finalTransaction.paymentDate,
|
||||
settlementDate: finalTransaction.settlementDate,
|
||||
supplier: finalTransaction.supplier
|
||||
});
|
||||
|
||||
// simple transaction
|
||||
finalTransaction.simpleTransaction = {
|
||||
accountId: null,
|
||||
id: finalTransaction.transactionHash,
|
||||
amount: finalTransaction.amount,
|
||||
date: finalTransaction.settlementDate,
|
||||
description: finalTransaction.description,
|
||||
name: finalTransaction.supplier
|
||||
};
|
||||
paymentsArray.push(finalTransaction);
|
||||
}
|
||||
|
||||
const csvSpendeskInstance = new CsvSpendesk(paymentsArray);
|
||||
return csvSpendeskInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the SpendeskData from Spendesk.com
|
||||
* @param dirPath
|
||||
*/
|
||||
public static async fromSpendeskCom(dirPath: string) {
|
||||
// TODO: implement spendesk API
|
||||
throw new Error(`method is not yet implemented`);
|
||||
}
|
||||
|
||||
// ========= INSTANCE ================
|
||||
public paymentProviderName: string = 'Spendesk';
|
||||
public origin: 'api' | 'file' | 'dir';
|
||||
public updateFunction: (
|
||||
fromTimeStamp: plugins.smarttime.TimeStamp,
|
||||
untilTimeStamp: plugins.smarttime.TimeStamp
|
||||
) => interfaces.ISpendeskTransaction[];
|
||||
public transactionArray: interfaces.ISpendeskTransaction[];
|
||||
|
||||
constructor(transactionArrayArg: interfaces.ISpendeskTransaction[]) {
|
||||
super();
|
||||
this.transactionArray = transactionArrayArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets all transactions
|
||||
*/
|
||||
public async getTransactions() {
|
||||
return this.transactionArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets all loads
|
||||
*/
|
||||
public async getLoads() {
|
||||
return this.transactionArray.filter(payment => {
|
||||
return payment.paymentType === 'Load';
|
||||
});
|
||||
}
|
||||
|
||||
public async getDebits() {
|
||||
return this.transactionArray.filter(payment => {
|
||||
return payment.paymentType === 'Payment';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* concat this instance's transactions with those of another one
|
||||
*/
|
||||
public async concat(csvSpendeskInstance: CsvSpendesk): Promise<CsvSpendesk> {
|
||||
this.transactionArray = this.transactionArray.concat(csvSpendeskInstance.transactionArray);
|
||||
return this;
|
||||
}
|
||||
}
|
1
ts/spendesk/index.ts
Normal file
1
ts/spendesk/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './csv-spendesk.classes.csvspendesk.js';
|
1
ts/spendesk/interfaces/index.ts
Normal file
1
ts/spendesk/interfaces/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './interface.spendesktransaction';
|
55
ts/spendesk/interfaces/interface.spendesktransaction.ts
Normal file
55
ts/spendesk/interfaces/interface.spendesktransaction.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import * as plugins from '../csv-spendesk.plugins';
|
||||
|
||||
export type TAvailableCurrencies = 'EUR';
|
||||
export type TPaymentState = 'Settled';
|
||||
export type TPaymentType = 'Load' | 'Credit' | 'Payment' | 'FXfee';
|
||||
|
||||
export interface ISpendeskOriginalTransaction {
|
||||
simpleTransaction: plugins.tsclass.ITransaction;
|
||||
original: any;
|
||||
'Payment date': string;
|
||||
'Settlement date': string;
|
||||
Month: string;
|
||||
Payer: string;
|
||||
Team: string;
|
||||
Description: string;
|
||||
Supplier: string;
|
||||
'Expense account': string;
|
||||
'Payment method': string;
|
||||
Type: string;
|
||||
// 'Local amount': number;
|
||||
// 'Local currency': 'EUR';
|
||||
Debit: string;
|
||||
Credit: string;
|
||||
Currency: string;
|
||||
VAT: string;
|
||||
vatPercentage?: string;
|
||||
State: string;
|
||||
'Receipt?': string;
|
||||
'Receipt name(s)': '';
|
||||
}
|
||||
|
||||
export interface ISpendeskTransaction {
|
||||
simpleTransaction?: plugins.tsclass.ITransaction;
|
||||
original: ISpendeskOriginalTransaction;
|
||||
transactionHash: string;
|
||||
paymentDate: Date;
|
||||
settlementDate: Date;
|
||||
month: string;
|
||||
payer: string;
|
||||
team: string;
|
||||
description: string;
|
||||
supplier: string;
|
||||
expenseAccount: string;
|
||||
paymentMethod: string;
|
||||
paymentType: TPaymentType;
|
||||
// 'Local amount': number;
|
||||
// 'Local currency': 'EUR';
|
||||
amount: number;
|
||||
currency: TAvailableCurrencies;
|
||||
vatAmount: number;
|
||||
vatPercentage?: number;
|
||||
paymentState: TPaymentState;
|
||||
receiptAvailable: boolean;
|
||||
receiptNames: string[];
|
||||
}
|
Reference in New Issue
Block a user