* fix(import): per-currency totals and row currency in bank-file preview Fixes #1170. ParsedBankTransaction carries a per-row currency (Wise emits genuinely mixed rows; camt.053 reads Ccy per entry), but the preview and confirm steps formatted every amount as kr and rendered parser-level income/expense totals that sum across currencies. Adds summarizeByCurrency() (income positive / expenses negative, ore rounding, SEK default) and renders one total line per currency on both steps; preview table rows format amount and balance with the row's own currency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(import): use roundOre from lib/money (antipattern ratchet) The naive Math.round(x * 100) / 100 form is blocked by check:guards (subtly wrong on exact-half values); lib/money.roundOre is canonical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { summarizeByCurrency } from '../currency-summary'
|
|
import type { ParsedBankTransaction } from '../types'
|
|
|
|
function tx(overrides: Partial<ParsedBankTransaction>): ParsedBankTransaction {
|
|
return {
|
|
date: '2026-07-01',
|
|
description: 'Test',
|
|
amount: 0,
|
|
currency: 'SEK',
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
describe('summarizeByCurrency', () => {
|
|
it('groups income and expenses per currency instead of mixing them', () => {
|
|
const result = summarizeByCurrency([
|
|
tx({ amount: 2500, currency: 'USD' }),
|
|
tx({ amount: -100.5, currency: 'USD' }),
|
|
tx({ amount: 1000, currency: 'SEK' }),
|
|
tx({ amount: -250, currency: 'SEK' }),
|
|
tx({ amount: -30, currency: 'EUR' }),
|
|
])
|
|
|
|
expect(result).toEqual([
|
|
{ currency: 'EUR', total_income: 0, total_expenses: -30 },
|
|
{ currency: 'SEK', total_income: 1000, total_expenses: -250 },
|
|
{ currency: 'USD', total_income: 2500, total_expenses: -100.5 },
|
|
])
|
|
})
|
|
|
|
it('defaults a missing currency to SEK and rounds to ore', () => {
|
|
const result = summarizeByCurrency([
|
|
tx({ amount: 0.105, currency: '' }),
|
|
tx({ amount: 0.105, currency: '' }),
|
|
])
|
|
|
|
expect(result).toEqual([{ currency: 'SEK', total_income: 0.21, total_expenses: 0 }])
|
|
})
|
|
|
|
it('returns an empty list for no transactions', () => {
|
|
expect(summarizeByCurrency([])).toEqual([])
|
|
})
|
|
})
|