Skip to content

Delete operations, one or several, with undo and a trash - #17

Merged
armysyn merged 1 commit into
mainfrom
feat/delete-operations
Oct 9, 2026
Merged

armysyn merged 1 commit into
mainfrom
feat/delete-operations

Conversation

@armysyn

@armysyn armysyn commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Why

Operations could only be marked "Not spending". A wrong Wallet payment, a manual entry made by mistake, or a statement operation the person does not want could not be removed.

What changed

  • Delete one operation. Every operation's ✎ menu has Delete operation, with a confirmation. Incoming money gets a ✎ menu too, holding only Delete.
  • Delete several at once. Select on the operations page turns the avatars into checkboxes. A sticky bar offers "All shown", a count and Delete selected.
  • Undo and the trash. The message after deleting offers Undo. Deleted operations (/ui/trash, linked from the operations page) lists them and restores one, several or all.
  • How the trash works (migration 0010_trash.sql): a deleted operation is kept whole: its fields, its category parts (trash_splits) and its statement operation keys (trash_links). Then it is removed from transactions. The cascade removes its parts, questions and links, and the existing trigger tells ClickHouse.
    • Restored operations get new ids, because ClickHouse has already deleted the old ones.
    • Merging categories also moves the parts kept in the trash.
  • Statements.
    • Importing a statement again does not bring a deleted operation back. Neither does a newer version of the statement, which matches operations by content: ImportTwins now finds deleted twins too.
    • The import result says how many were left out.
    • Reconciliation still counts deleted statement operations, because the bank did, and says "counting N deleted operations".
  • Wallet. A payment sent again with the same key is not added (InsertTx reports a duplicate with id 0).

Checks

  • gofmt -l . prints nothing; go vet ./... passes; go test -race ./... passes; CLICKHOUSE_TEST_URL=… go test ./... passes; golangci-lint run ./... reports 0 issues.
  • New tests:
    • TestTrash (store): parts, Wallet resend, category merge, list, restore.
    • TestDeletedStaysDeleted (importer): re-import, a newer version, reconciliation, restore.
    • TestDeleteOperations (web): one, Undo, select mode, several, the trash page, nothing picked, unsafe back.
    • /ui/trash and /ui/operations?select=1 are added to TestPagesRender.
  • Looked at select mode (dark) and the trash page (light) on invented data.

🤖 Generated with Claude Code

Operations could only be marked "not spending"; a wrong Wallet payment, a manual entry made
by mistake or a statement operation the person does not want could not be removed.

Now the ✎ menu of every operation has Delete, and Select on the operations page picks several
to delete at once. A deleted operation goes to the trash whole (migration 0010): its fields,
its category parts and the keys of the statement operations it came from. So:

- the message after deleting offers Undo, and Deleted operations lists them to restore one,
  several or all; restored operations get new ids, since ClickHouse has deleted the old ones;
- importing the statement again, or a newer version of it, does not bring a deleted operation
  back (by key, or by content like a live twin), and the import result says how many were left
  out; a Wallet payment sent again with the same key is not added either;
- reconciliation still counts deleted statement operations, as the bank did, and says so;
- merging categories updates the parts kept in the trash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@armysyn
armysyn merged commit 44166ec into main Oct 9, 2026
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant