docs/design/changelog-import-refactor.md
Branch: refactor/import-event-driven-validation Scope: 107 files
changed, ~9,200 insertions, ~2,600 deletions
The CSV import experience has been redesigned to be more reliable, faster, and easier to use. Here's what changed:
Smarter asset matching. Before importing, Wealthfolio now shows you exactly how each ticker in your CSV will be matched to an asset in your portfolio. If something looks off — a symbol that could belong to multiple exchanges, or a delisted stock — you can fix it right there with a search, instead of finding out after the import that something went wrong.
Saved templates. If you import from the same broker regularly, Wealthfolio remembers your column mapping. Pick your broker from the list, and the columns map themselves. You can also save your own custom templates and link them to specific accounts so the right one loads automatically.
ISIN support. CSVs from brokers like Trading 212 include ISIN codes (the international security identifier). Wealthfolio now reads these and uses them to match assets precisely — no more guessing which exchange a ticker belongs to.
Better handling of special transactions. Dividend reinvestments (DRIP), dividends paid in shares, and staking rewards are now recognized during import and matched to the correct asset automatically.
Skip rows you don't need. See a transaction you don't want to import? Mark it as skipped. It stays visible in the review grid but won't be imported.
Faster imports. Asset lookups now run in parallel instead of one at a time. Large CSVs with many different tickers resolve noticeably faster.
Automatic encoding detection. CSVs exported from Windows programs in non-standard encodings (like Windows-1252) are detected and handled automatically. No more garbled characters in transaction descriptions.
Duplicate protection. If you accidentally import the same CSV twice, Wealthfolio detects the overlap and skips transactions that already exist. You'll see exactly how many were skipped and why.
ISIN column mapping. When present, the backend uses ISIN for unambiguous
exchange resolution before falling back to ticker search.looksLikeIsin() heuristic auto-detects ISIN columns during header mapping.activity_import_profiles table with import_templates +
import_account_templates (many-to-many).SYSTEM / USER) and kinded (CSV_ACTIVITY /
CSV_HOLDING / BROKER_ACTIVITY).kind = BROKER_ACTIVITY.FieldMappingValue supports fallback — a secondary column to try when the
primary is empty (e.g., Symbol falling back to ISIN).quantity and amount: negative values auto-flip to SELL
/ WITHDRAWAL when the mapped type is ambiguous.needsImportAssetResolution() ensures asset-backed income rows
go through symbol resolution even when the activity type alone wouldn't
require it.validationRunRef / previewRunRef pattern prevents stale async responses
from overwriting current state. Back navigation increments both refs to cancel
in-flight requests.draftRevision / lastValidatedRevision tracking lets the UI know when
drafts have changed since the last validation without re-running validation
eagerly.SET_DRAFT_ACTIVITIES,
SET_VALIDATED_DRAFT_ACTIVITIES, UPDATE_DRAFT, BULK_UPDATE_DRAFTS, etc.).assetPreviewItems, pendingImportAssets) lives in
context alongside draft state.updatesAffectAssetPreview() clears preview state when asset-relevant fields
change.check_activities_import / import_activities Splitcheck_activities_import is now purely validation — resolves symbols, detects
duplicates via idempotency keys, returns enriched ActivityImport objects
with errors/warnings.import_activities does a lightweight pre-insert validation, then converts
and bulk-inserts. Duplicate detection uses ON CONFLICT DO NOTHING on
idempotency keys.preview_import_assets is a new endpoint that runs check_activities_import
on synthetic activities to preview asset resolution without side effects.resolve_symbols_batch does concurrent resolution with
buffer_unordered(10).(symbol, currency) pairs drive exchange suffix
selection (e.g., .TO for CAD).quoteCcy is included in the asset candidate key so
same-symbol/different-currency rows resolve independently.activity_import_profiles → import_templates2026-03-19-000001_import_templates/up.sql renames the table, adds scope,
kind, source_system, config_version columns, creates the
import_account_templates join table, and migrates existing data.down.sql reverses the migration.sync_table_state entries are updated for device sync compatibility.import_type → context_kind to match the frontend
adapter's contextKind parameter naming.alias = "importType" fallback — all clients now
use contextKind exclusively.buffer_unordered(10).(symbol, instrumentType, quoteMode, exchangeMic, quoteCcy) key.previewRunRef + validationRunRef prevent race
conditions when navigating between steps while async work is in flight.DataGridRow memo comparison fix prevents unnecessary
re-renders in large grids.exchanges.json.04-csv-import and 07-asset-creation updated for new wizard step
names and flow.import-asset-rules.test.ts, activity-utils.test.ts.