* feat(import): add Wise (TransferWise) CSV import format
Wise exports a single multi-currency transaction history (one row per balance
movement). Add it as a bank-file format plugin so it flows through the existing
upload -> preview -> confirm -> execute wizard.
- lib/import/bank-file/formats/wise.ts: quote-aware parse (dates contain a
space), Direction IN/OUT drives the sign, booked on the moved side (target
for IN, source for OUT). Native currency preserved; SEK conversion is left to
the downstream FX/booking pipeline (Riksbanken).
- Non-zero Wise fees become their own negative "Wise avgift" row (source and
target), so the fee books separately and the balance ties out.
- Only COMPLETED rows import. external_id keys on the stable Wise ID
(TRANSFER-/PLAN_ORDER-, -fee suffix for fee rows) via a new 'wise' branch in
generateExternalId, so re-imports dedup exactly.
- Register the format (types, parser list), add it to the manual-format picker
and the v1 /imports/bank format enum.
Tests cover detection, IN/OUT signing + currency, fee splitting, stable
external_id, and COMPLETED-only filtering.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Reinthal <email@reinthal.me>
* fix(import): harden Wise parser against malformed rows (CodeRabbit #1018)
- Strict amount parsing: reject "12abc"/"1,234" instead of parseFloat coercing
them to 12/1 and silently corrupting the imported amount.
- Require Status to be exactly COMPLETED: a blank/missing status no longer
slips through the completed-only filter.
- Fail hard on an unsupported Direction: a blank or non-IN/OUT value (e.g.
NEUTRAL for a balance conversion) throws instead of being guessed as income;
the parse route surfaces it as BANK_FILE_PARSE_FAILED. Proper conversion
support is tracked in #1019.
- Never invent currencies: a missing movement currency skips the row with a
warning (no SEK default), and a fee with no currency of its own is dropped
with a warning rather than inheriting the movement currency.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Alexander Reinthal <email@reinthal.me>
---------
Signed-off-by: Alexander Reinthal <email@reinthal.me>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jakob Wennberg <jakob.wennberg@gmail.com>