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
+2 -1
View File
@@ -61,6 +61,7 @@ type App struct {
bank banking.Provider
classifier classification.Client
previews map[string]Preview
csvImports map[string]CSVImport
authStates map[string]authorization
callbackURL string
bankingSettings bankingSettings
@@ -72,7 +73,7 @@ func Open(dir string) (*App, error) {
if err != nil {
return nil, err
}
a := &App{dir: dir, journal: j, previews: make(map[string]Preview), authStates: make(map[string]authorization), syncRequested: make(chan struct{}, 1)}
a := &App{dir: dir, journal: j, previews: make(map[string]Preview), csvImports: make(map[string]CSVImport), authStates: make(map[string]authorization), syncRequested: make(chan struct{}, 1)}
fail := func(e error) (*App, error) { j.Close(); return nil, e }
if err = os.MkdirAll(filepath.Join(dir, "state"), 0700); err != nil {
return fail(err)