From 3edcc277813796728fa8b6ad52154ec13dfeed8f Mon Sep 17 00:00:00 2001 From: siddharthd Date: Thu, 13 Aug 2026 15:08:50 +1000 Subject: [PATCH] csv import: map a currency column, or foreign rows land as AUD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deleting the Frollo importer dropped its currency handling and nothing replaced it: ColumnMapping had no currency column, so applyMapping could never produce foreign_currency_code and batchInsertCSVTransactions' support for it was unreachable from the UI. The USD 10,782 salary imported as A$10,782 — about a third under, sitting in a column of AUD figures looking entirely normal, which is the same defect the owner spotted in the first place. An optional Currency column now sets foreign_currency_code and foreign_currency_amount when the cell is a three-letter code other than AUD, and leaves amount_aud NULL rather than inventing a rate. That is the shape order ingestion already uses and what AMOUNT_UNCONVERTED looks for, so the row renders as its native figure with "no AUD rate" and the statement supplies the real number when it arrives. Caught by reading the imported row rather than the import summary: the summary said 171 inserted and was right about everything it reported. --- .../unit/csv-import-coverage.test.ts | 33 +++++++++++++++++++ src/components/csv-import-modal.tsx | 4 ++- src/lib/csv-parser.ts | 23 +++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/__tests__/unit/csv-import-coverage.test.ts b/src/__tests__/unit/csv-import-coverage.test.ts index ae57901..1f67ec8 100644 --- a/src/__tests__/unit/csv-import-coverage.test.ts +++ b/src/__tests__/unit/csv-import-coverage.test.ts @@ -169,6 +169,39 @@ describe("applyMapping with account and row-id columns", () => { expect(out[0].transaction_type).toBe("credit"); }); + it("marks a non-AUD row as native and unconverted", () => { + // The 2026-08-12 salary is USD. Stored without this it reads as A$10,782 — + // about a third under — and sits in a column of AUD figures looking normal. + const out = applyMapping( + [["1", "HDR Global Services", "10782.00", "2026-08-12", "xxxx4830", "USD"]], + [...labels, "currency"], + { ...mapping, currencyCol: "currency" }, + "YYYY-MM-DD" + ); + expect(out[0].foreign_currency_code).toBe("USD"); + expect(out[0].foreign_currency_amount).toBe(10782); + }); + + it("leaves an AUD row unmarked", () => { + const out = applyMapping( + [["1", "SOMETHING", "-42.50", "2026-08-12", "xxxx4830", "AUD"]], + [...labels, "currency"], + { ...mapping, currencyCol: "currency" }, + "YYYY-MM-DD" + ); + expect(out[0].foreign_currency_code).toBeUndefined(); + }); + + it("ignores a currency cell that is not a code", () => { + const out = applyMapping( + [["1", "SOMETHING", "-42.50", "2026-08-12", "xxxx4830", ""]], + [...labels, "currency"], + { ...mapping, currencyCol: "currency" }, + "YYYY-MM-DD" + ); + expect(out[0].foreign_currency_code).toBeUndefined(); + }); + it("leaves both undefined when the columns are not mapped", () => { const out = applyMapping( [["1", "SOMETHING", "-42.50", "2026-08-12", "xxxx4830"]], diff --git a/src/components/csv-import-modal.tsx b/src/components/csv-import-modal.tsx index 08d5a34..80d74c7 100644 --- a/src/components/csv-import-modal.tsx +++ b/src/components/csv-import-modal.tsx @@ -300,12 +300,14 @@ export function CsvImportModal({ onClose }: { onClose: () => void }) { setMapping((m) => ({ ...m, merchantCol: v || undefined }))} options={columnLabels} /> setMapping((m) => ({ ...m, categoryCol: v || undefined }))} options={columnLabels} /> setMapping((m) => ({ ...m, accountCol: v || undefined }))} options={columnLabels} /> + setMapping((m) => ({ ...m, currencyCol: v || undefined }))} options={columnLabels} /> setMapping((m) => ({ ...m, sourceRefCol: v || undefined }))} options={columnLabels} />

Map Account when the file covers more than one account: rows already covered by that account's statements are then left out. Map Row ID to - make re-importing the same file do nothing. + make re-importing the same file do nothing. Map Currency for a + multi-currency file, or foreign rows are stored as if they were AUD.