diff --git a/src/components/TransactionImportDialog.vue b/src/components/TransactionImportDialog.vue index 0624dafc..16664ef7 100644 --- a/src/components/TransactionImportDialog.vue +++ b/src/components/TransactionImportDialog.vue @@ -165,6 +165,7 @@ import FileInput from './FileInput.vue'; import Upload from 'vue-material-design-icons/Upload.vue'; + import { Utils } from '../utils/utils'; const transactionService = useTransactionService(); const splitStore = useSplitStore(); @@ -214,7 +215,7 @@ lines: [], isValid: false, validator: (line) => { - return !Number.isNaN(Number(line)); + return !Number.isNaN(Utils.parseNumber(line, decimalSeparator.value)); } } }); diff --git a/src/utils/utils.spec.ts b/src/utils/utils.spec.ts index ab3f4a5d..f06a90d1 100644 --- a/src/utils/utils.spec.ts +++ b/src/utils/utils.spec.ts @@ -37,4 +37,23 @@ describe('Utils', () => { ]); }); }); + + describe('parseNumber', () => { + it('should return a number of a string', () => { + expect(Utils.parseNumber('123.456')).to.be.equal(123.456); + }); + + it('should return NaN if it is not a parseable number', () => { + expect(Utils.parseNumber('abc')).to.be.NaN; + }); + + it('should respect decimal separator', () => { + expect(Utils.parseNumber('123,456', ',')).to.be.equal(123.456); + }); + + it('should ignore thousand separators', () => { + expect(Utils.parseNumber('12,345.678')).to.be.equal(12345.678); + expect(Utils.parseNumber('12.456,789', ',')).to.be.equal(12456.789); + }); + }); }); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 5451ebd8..e38fec1f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -56,4 +56,13 @@ export class Utils { decimalDigits ? `${decimalSeparator}${decimalDigits}` : '' }`; } + + public static parseNumber(numberString: string, decimalSeparator = '.'): number { + return Number( + numberString + .replace(decimalSeparator, '#') + .replace(/[\s,.]+/, '') + .replace('#', '.')); + } + }