How the numbers work
Duplicates and re-imports
You should be able to export "the last 90 days" every month and import it without a thought. That works because identity is decided per transaction, not per file.
The fingerprint#
Every transaction carries one, computed from:
account · date · amount · currency · normalized title · counterparty account · occurrence index
The title is normalized first — whitespace collapsed, lowercased — so a bank that changes its spacing doesn't produce a second copy of the same row.
The occurrence index lets genuinely identical transactions survive. Buy the same 12,00 coffee twice in one day and the statement has two rows agreeing on every field; they are numbered first and second, so both import. Re-import that file and both match what is already there. If a third such coffee later appears, two match and only the new one lands.
The fingerprint is unique in the database, and committing ignores collisions, so even if something slipped past review a row cannot be written twice.
Two consequences#
Fingerprints are per account. The same file into a different account dedupes nothing — every row is new. The review screen watches for this and warns before you commit.
They use the file's own amount and currency, not the converted PLN value. Identity must not depend on an exchange rate, or a rate correction would turn one transaction into two.
What you see when you re-import#
Rows already present stage as duplicates, counted in their own bucket, and ▸ Record in the dock naming where the existing copy came from — "already imported from statement-june.csv on 3 July". They are not written.
If the byte-identical file was imported before, a banner says so up front rather than letting you discover it in the tally.
Re-importing an unchanged file writes zero rows.
The balance continuity check#
If the layout maps a running-balance column, the review screen verifies the whole statement: each row's balance must equal the previous one plus everything since. It tries both directions, since banks export newest-first about as often as chronologically.
A single mismatch is hard evidence that a row was dropped, doubled or parsed wrong — which no row count and no duplicate check can see. When it holds you get balance continuous · 1 240,00 → 3 981,55; when it breaks, a red banner names the line and prints expected against actual.
One export can carry the column and the next not — banks let you generate a statement with the running balance hidden. That file still imports; the pill reads balance not checked so the missing check is visible rather than silent.
Corrections don't change identity#
A fingerprint is computed at import and stored. Recategorizing, adding a note, or converting to PLN later leaves it alone — it answers "is this the same transaction", and your notes about it are not part of the answer.
Undoing an import#
The Import tab's past-imports list has delete on every row: the import and all its transactions, after asking. For a single junk row, the Transactions tab deletes one at a time.
Once an import is deleted its fingerprints go with it, so the same file imports cleanly again.