diff --git a/converters/santanderConverter.js b/converters/santanderConverter.js index bbbecad..3bb0fca 100644 --- a/converters/santanderConverter.js +++ b/converters/santanderConverter.js @@ -16,12 +16,16 @@ const columns = [ ]; const parseAmount = (amount) => parseFloat(amount.replace(",", ".")); +function normalisePayer(payer) { + return payer.replace(/^.*PLN /, '') +} function descriptionToPayer(description) { if (description.startsWith("Suma nagród za płatności")) { return "Santander returns"; } - return description; + return normalisePayer(description); } + function parsePayer(payer, description) { return payer || descriptionToPayer(description); } diff --git a/converters/santanderConverter.spec.js b/converters/santanderConverter.spec.js index 118a913..aabffd6 100644 --- a/converters/santanderConverter.spec.js +++ b/converters/santanderConverter.spec.js @@ -7,7 +7,7 @@ test('should be able to convert Santander CSV files format', (done) => { }; const input = `2022-10-23,25-09-2022,'11 2222 3333 4444,Owner address,PLN,,,17, 21-10-2022,19-04-2019,Description 1,KASOWNIK 12,11 2222 3333,"-3,20",,1, -20-10-2022,19-04-2019,Description 2,H AND M GAL. BALTYCKA,22 3333 44444,"-48,78",,2,` +20-10-2022,19-04-2019,VISA SEL 123456******1234 PŁATNOŚĆ KARTĄ 48.78 PLN H AND M GAL. BALTYCKA,,22 3333 44444,"-48,78",,2,` const expected = `19.04.2019,-3.2,Transport,Public transport,Credit Card,,,KASOWNIK 12,,,Santander 19.04.2019,-48.78,Personal,Clothing,Credit Card,,,H AND M GAL. BALTYCKA,,,Santander ` diff --git a/converters/velobankConverter.js b/converters/velobankConverter.js new file mode 100644 index 0000000..921e40a --- /dev/null +++ b/converters/velobankConverter.js @@ -0,0 +1,33 @@ +const { parse } = require('csv-parse/sync') +const { transform } = require('stream-transform') +const categoryResolver = require('../categoryResolver') +const { sanitize } = require('../utils') + +const columns = ['date', 'realDate', 'description', 'amount', 'balance'] + +const parseAmount = amount => parseFloat(amount.replace(' ', '').replace(',', '.')) + +const parseDescription = description => { + const descriptionParts = description.split(',') + if (descriptionParts.length === 1) { + return descriptionParts[0] + } + const payerPart = descriptionParts[1] + return payerPart.replace('w ', '').replace(/\d+ PLN/, '').trim() +} + +const getExpenseManagerRecord = recordCategoryResolver => record => { + const payer = parseDescription(record[columns[2]]); + const amount = parseAmount(record[columns[3]]) + const { category, subCategory } = recordCategoryResolver(payer, amount); + return record[columns[0]] + ',' + + amount + ',' + category + ',' + subCategory + + ',Credit Card,,,' + sanitize(payer) + + ',,,GetIn\n' +} + +exports.convertCvsFileData = (input, categoriesMapping) => { + const getExpenseManagerWithMapping = getExpenseManagerRecord(categoryResolver.resolveCategory(categoriesMapping)) + return transform(parse(input, { delimiter: ',', columns, relax: true, relax_column_count: true, bom: true }), + record => getExpenseManagerWithMapping(record)) +} diff --git a/converters/velobankConverter.spec.js b/converters/velobankConverter.spec.js new file mode 100644 index 0000000..913814e --- /dev/null +++ b/converters/velobankConverter.spec.js @@ -0,0 +1,31 @@ +const citiConverter = require('./velobankConverter') + +const categoriesMapping = { + 'Play': { category: 'Utilities', subCategory: 'Telephone' }, + 'Employer': { category: 'Income', subCategory: 'Salary' }, + 'Deposit': { category: 'Income', subCategory: 'Deposit' } +}; + +test('should be able to convert Velobank manually created CSV files format', (done) => { + const input = `30.10.2019,24.11.2023,Employer,"9 839,29 PLN","1 574,59 PLN" +28.10.2019,24.11.2023,"Operacja kartą na kwotę 17,99 PLN w Play, GDANSK, PL","-10,00 PLN","2 374,59 PLN"` + const expected = `30.10.2019,9839.29,Income,Salary,Credit Card,,,Employer,,,GetIn +28.10.2019,-10,Utilities,Telephone,Credit Card,,,Play,,,GetIn +` + let transformedData = ''; + + const converter = citiConverter.convertCvsFileData(input, categoriesMapping) + .on('readable', () => { + let row = converter.read() + while (row) { + transformedData += row + row = converter.read() + } + }) + .on('finish', () => { + setTimeout(() => { + expect(transformedData).toEqual(expected) + done() + }) + }) +}) diff --git a/e2e/index.test.js b/e2e/index.test.js index 3ef61b0..0299650 100644 --- a/e2e/index.test.js +++ b/e2e/index.test.js @@ -80,3 +80,17 @@ test('should download converted csv without mapping for Santander', async t => { await t.expect(file).eql('30.10.2019,9839.29,Income,,Credit Card,,,Employer,,,Santander\n28.10.2019,-10,,,Credit Card,,,Play,,,Santander\n') }) .after(() => unlinkSync(expectedFile)) + +test('should download converted csv without mapping for Velobank', async t => { + expectedFile = join(`${homedir()}`, 'Downloads', 'testDataVelobank-converted.csv') + await t + .setFilesToUpload(Selector('#file'), 'testDataVelobank.csv') + .click(Selector('#velobank')) + .click(Selector('button')) + + await waitForFile(expectedFile) + const file = readFileSync(expectedFile, 'utf-8') + + await t.expect(file).eql('30.10.2019,9839.29,Income,,Credit Card,,,Employer,,,GetIn\n28.10.2019,-10,,,Credit Card,,,Play,,,GetIn\n') +}) + .after(() => unlinkSync(expectedFile)) diff --git a/e2e/testDataVelobank.csv b/e2e/testDataVelobank.csv new file mode 100644 index 0000000..f774ccf --- /dev/null +++ b/e2e/testDataVelobank.csv @@ -0,0 +1,2 @@ +30.10.2019,24.11.2023,Employer,"9 839,29 PLN","1 574,59 PLN" +28.10.2019,24.11.2023,"Operacja kartą na kwotę 17,99 PLN w Play, GDANSK, PL","-10,00 PLN","2 374,59 PLN" diff --git a/index.html b/index.html index 95f9e23..99ba907 100644 --- a/index.html +++ b/index.html @@ -27,13 +27,17 @@