import * as plugins from '../csvparser.plugins.js'; import * as interfaces from './interfaces/index.js'; export class CsvPayPal extends plugins.portablefinance .AcCsvParser { // 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; } }