From 8be867f8846b3e239d13bb80d4dfd3b484e0b3f0 Mon Sep 17 00:00:00 2001
From: youngcw <calebyoung94@gmail.com>
Date: Sun, 4 Aug 2024 10:21:53 -0700
Subject: [PATCH] Fix a few number parsing issues (#3044)

* revert built in number parse

* note

* tests

* remove trivial test

* more tests

---------

Co-authored-by: Julian Dominguez-Schatz <julian.dominguezschatz@gmail.com>
---
 .../loot-core/src/server/accounts/parse-file.test.ts | 12 ------------
 packages/loot-core/src/server/accounts/parse-file.ts |  2 +-
 packages/loot-core/src/shared/util.test.ts           | 12 ++++++++++++
 packages/loot-core/src/shared/util.ts                |  2 +-
 upcoming-release-notes/3044.md                       |  6 ++++++
 5 files changed, 20 insertions(+), 14 deletions(-)
 create mode 100644 upcoming-release-notes/3044.md

diff --git a/packages/loot-core/src/server/accounts/parse-file.test.ts b/packages/loot-core/src/server/accounts/parse-file.test.ts
index c84e30e4a..04cfc9f08 100644
--- a/packages/loot-core/src/server/accounts/parse-file.test.ts
+++ b/packages/loot-core/src/server/accounts/parse-file.test.ts
@@ -84,18 +84,6 @@ describe('File import', () => {
     expect(await getTransactions('one')).toMatchSnapshot();
   }, 45000);
 
-  test('ofx import works with multiple decimals in amount', async () => {
-    const ofxFile = __dirname + '/../../mocks/files/data-multi-decimal.ofx';
-
-    const { transactions } = (await parseFile(ofxFile)) as {
-      transactions: { amount: number }[];
-    };
-
-    expect(transactions).toHaveLength(2);
-    expect(transactions[0].amount).toBe(-30.0);
-    expect(transactions[1].amount).toBe(-3.77);
-  }, 45000);
-
   test('ofx import works (credit card)', async () => {
     prefs.loadPrefs();
     await db.insertAccount({ id: 'one', name: 'one' });
diff --git a/packages/loot-core/src/server/accounts/parse-file.ts b/packages/loot-core/src/server/accounts/parse-file.ts
index ffbc1d28a..0dd086086 100644
--- a/packages/loot-core/src/server/accounts/parse-file.ts
+++ b/packages/loot-core/src/server/accounts/parse-file.ts
@@ -137,7 +137,7 @@ async function parseOFX(
     errors,
     transactions: data.transactions.map(trans => {
       return {
-        amount: Number(trans.amount),
+        amount: trans.amount,
         imported_id: trans.fitId,
         date: trans.date,
         payee_name: trans.name || (useMemoFallback ? trans.memo : null),
diff --git a/packages/loot-core/src/shared/util.test.ts b/packages/loot-core/src/shared/util.test.ts
index 6f2be8a81..ce5117bf0 100644
--- a/packages/loot-core/src/shared/util.test.ts
+++ b/packages/loot-core/src/shared/util.test.ts
@@ -8,6 +8,8 @@ describe('utility functions', () => {
     expect(looselyParseAmount('3')).toBe(3);
     expect(looselyParseAmount('3.4')).toBe(3.4);
     expect(looselyParseAmount('3.45')).toBe(3.45);
+    // cant tell if this next case should be decimal or different format
+    // so we set as full numbers
     expect(looselyParseAmount('3.456')).toBe(3456);
     expect(looselyParseAmount('3.45000')).toBe(3.45);
     expect(looselyParseAmount('3.450000')).toBe(3.45);
@@ -24,6 +26,15 @@ describe('utility functions', () => {
     expect(looselyParseAmount('3,4500000')).toBe(3.45);
     expect(looselyParseAmount('3,45000000')).toBe(3.45);
     expect(looselyParseAmount('3,450000000')).toBe(3.45);
+    expect(looselyParseAmount("3'456.78")).toBe(3456.78);
+    expect(looselyParseAmount("3'456.78000")).toBe(3456.78);
+    expect(looselyParseAmount('1,00,000.99')).toBe(100000.99);
+    expect(looselyParseAmount('1,00,000.99000')).toBe(100000.99);
+  });
+
+  test('looseParseAmount works with leading decimal characters', () => {
+    expect(looselyParseAmount('.45')).toBe(0.45);
+    expect(looselyParseAmount(',45')).toBe(0.45);
   });
 
   test('looseParseAmount works with negative numbers', () => {
@@ -42,6 +53,7 @@ describe('utility functions', () => {
     // `3_45_23` (it needs a decimal amount). This function should be
     // thought through more.
     expect(looselyParseAmount('3_45_23.10')).toBe(34523.1);
+    expect(looselyParseAmount('(1 500.99)')).toBe(-1500.99);
   });
 
   test('number formatting works with comma-dot format', () => {
diff --git a/packages/loot-core/src/shared/util.ts b/packages/loot-core/src/shared/util.ts
index 0f2a10c10..7a8c9681b 100644
--- a/packages/loot-core/src/shared/util.ts
+++ b/packages/loot-core/src/shared/util.ts
@@ -415,7 +415,7 @@ export function looselyParseAmount(amount: string) {
   // Look for a decimal marker, then look for either 1-2 or 5-9 decimal places.
   // This avoids matching against 3 places which may not actually be decimal
   const m = amount.match(/[.,]([^.,]{5,9}|[^.,]{1,2})$/);
-  if (!m || m.index === undefined || m.index === 0) {
+  if (!m || m.index === undefined) {
     return safeNumber(parseFloat(extractNumbers(amount)));
   }
 
diff --git a/upcoming-release-notes/3044.md b/upcoming-release-notes/3044.md
new file mode 100644
index 000000000..63158f9c5
--- /dev/null
+++ b/upcoming-release-notes/3044.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [youngcw,wdpk]
+---
+
+Fix decimal comma parsing for ofx files
\ No newline at end of file
-- 
GitLab