Import ING and Kontist statements behind a reviewed column mapping

CSV import is now mapping-driven: N26, ING (metadata preamble, Windows-1252,
German decimals) and Kontist exports are recognized locally, and any other
layout can have its columns proposed by the configured model from a sample in
which letters are replaced by x and digits by 0. Proposals are untrusted: every
column must name a supplied header, money must come from one signed column or
one debit/credit pair, and formats must be from a closed list.

Uploading no longer imports. /api/import is replaced by prepare/confirm/cancel:
prepare parses, deduplicates and previews the exact facts, and only confirming
at the reviewed revision writes them. ING and AI-mapped facts carry no
transaction reference, because repeating SEPA mandate references must never
become a transaction identity.
This commit is contained in:
Lars Nolden
2026-09-11 17:49:03 +02:00
parent 6f791b1277
commit dc767799bc
16 changed files with 2182 additions and 301 deletions
+20
View File
@@ -143,6 +143,26 @@ export interface Preview {
unchanged: number;
errors: { id: string; error: string }[];
}
export interface CSVColumn {
field: string;
column: string;
}
// PreparedImport is a parsed statement that has not been imported yet: the
// mapping and sample must be confirmed before any transaction is written.
export interface PreparedImport {
id: string;
revision: string;
account_id: string;
source: string;
source_label: string;
mapped_by: "preset" | "openrouter";
model?: string;
columns: CSVColumn[];
records: number;
new: number;
duplicates: number;
samples: Facts[];
}
export class APIError extends Error {
constructor(
message: string,