Upload statements from the web app
The Accounts screen gets an Add statements panel: pick an account, drop files on it or choose them, and they are saved into that account's folder and imported. The folder stays the source of truth -- an upload only puts a file where `money import` looks, then runs the same import as the Import button, so deleting index.db and re-importing still loses nothing. Files travel base64 inside JSON rather than as multipart. There is no auth, and the JSON-only rule is what keeps another site's form from posting here; multipart is exactly what such a form can send. An upload never replaces a statement: identical contents are a no-op and different ones are refused with 409. Names import would not read back -- not a plain file name, dotfiles, account.toml, outside the account's include patterns -- are refused, and a batch is checked whole before any of it is written. Files are written through a dotfile and renamed, so a concurrent import never reads half of one. The overview now lists the account folders on disk, read fresh so one created after startup is a valid target; it replaces the configured count the empty accounts screen used. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -237,6 +237,17 @@ otherwise name a different rule. Covered by `TestStalePositionIsRefused`.
|
||||
There is no auth by design (`--addr` defaults to loopback). Non-GET requests
|
||||
must be `application/json`, which is what keeps a cross-site form from posting
|
||||
to it; do not relax that without putting something else in its place.
|
||||
That is why `/api/upload` takes files base64 inside JSON rather than as
|
||||
multipart: multipart is precisely what a cross-site form can send.
|
||||
|
||||
**An upload only puts a file where `money import` looks.** It writes into an
|
||||
existing account folder and then runs the same import as `/api/import`, so the
|
||||
statements stay the source of truth and nothing reaches the index any other
|
||||
way. It never overwrites a statement (identical contents are a no-op, different
|
||||
ones a 409), refuses any name import would not read back — not a plain file
|
||||
name, a dotfile, `account.toml`, outside the account's `include` — and checks a
|
||||
whole batch before writing any of it. Covered by
|
||||
`TestUploadNeverReplacesAStatement` and `TestUploadRefusesBadNames`.
|
||||
|
||||
## Adding a bank parser
|
||||
|
||||
|
||||
Reference in New Issue
Block a user