fix(transactions): drop suppressed transactions from the transactions page #19

Merged
notid merged 3 commits from worktree-revert-include-in-reports into staging 2026-08-16 08:40:49 -07:00
Owner

Suppressed transactions were showing up on the transactions page.

The cause

The SSR transactions page never excluded :transaction-approval-status/suppressed. The GraphQL/CLJS transactions page has always excluded them unconditionally (auto_ap/datomic/transactions.clj, the true branch of its cond->>), as do the ledger queries in auto_ap/ledger.clj.

The scan-transactions ion does no status filtering of its own — it is a bare index-range over :transaction/client+date — so nothing downstream was dropping them either. Suppressing a transaction is the user's way of saying "stop showing me this", and it stayed visible on the page it was suppressed from.

Impact

22,813 suppressed transactions exist db-wide out of 621,492. For the worst-affected client, a five-year range returned 14,736 rows against 3,641 real ones — the other 11,095 were suppressed.

The fix

One not clause in the main scan in auto_ap/ssr/transaction/common.clj, applied inside the query rather than after it so the row count and the amount total — both derived from fetch-ids — match the rows actually rendered. Measured 6ms -> 29ms on that worst-case client and range.

The three status routes (approved, unapproved, requires-feedback) constrain the status themselves and there is no suppressed route, so no page loses its own rows.

Note on the commit list

This branch carries 6e7f66a7 (include-in-reports in the register) and its revert. That commit was only ever on a local staging; it never reached this remote. The net diff of this branch against staging is exactly the transactions fix below — the add and the revert cancel out. Both are kept so local staging reconciles cleanly after merge.

Testing

  • New test/clj/auto_ap/ssr/transaction/common_test.clj — 6 assertions, passing. Covers the suppressed row being dropped from ids, all-ids and count; the approved status route still listing its rows; and an all-suppressed client returning empty.
  • auto-ap.ssr.transaction.import-test and auto-ap.ssr.ledger-test pass, with one exception: external-import-remove-button-test fails identically with and without these changes, so it is pre-existing and unrelated.
  • auto-ap.ssr.transaction.edit-test still has its known apply-rule does not exist compile break, untouched here.
  • lein cljfmt check clean.

Loose end, not addressed

:transaction/exclude-from-ledger is defined in resources/schema.edn but read nowhere in the codebase — only :invoice/exclude-from-ledger is honored. If anything ever wrote that attribute expecting it to hide transactions, it never did.

🤖 Generated with Claude Code

Suppressed transactions were showing up on the transactions page. ## The cause The SSR transactions page never excluded `:transaction-approval-status/suppressed`. The GraphQL/CLJS transactions page has always excluded them unconditionally (`auto_ap/datomic/transactions.clj`, the `true` branch of its `cond->>`), as do the ledger queries in `auto_ap/ledger.clj`. The `scan-transactions` ion does no status filtering of its own — it is a bare `index-range` over `:transaction/client+date` — so nothing downstream was dropping them either. Suppressing a transaction is the user's way of saying "stop showing me this", and it stayed visible on the page it was suppressed from. ## Impact 22,813 suppressed transactions exist db-wide out of 621,492. For the worst-affected client, a five-year range returned **14,736 rows against 3,641 real ones** — the other 11,095 were suppressed. ## The fix One `not` clause in the main scan in `auto_ap/ssr/transaction/common.clj`, applied inside the query rather than after it so the row count and the amount total — both derived from `fetch-ids` — match the rows actually rendered. Measured 6ms -> 29ms on that worst-case client and range. The three status routes (approved, unapproved, requires-feedback) constrain the status themselves and there is no suppressed route, so no page loses its own rows. ## Note on the commit list This branch carries `6e7f66a7` (include-in-reports in the register) and its revert. That commit was only ever on a local staging; it never reached this remote. The net diff of this branch against `staging` is exactly the transactions fix below — the add and the revert cancel out. Both are kept so local staging reconciles cleanly after merge. ## Testing - New `test/clj/auto_ap/ssr/transaction/common_test.clj` — 6 assertions, passing. Covers the suppressed row being dropped from `ids`, `all-ids` and `count`; the approved status route still listing its rows; and an all-suppressed client returning empty. - `auto-ap.ssr.transaction.import-test` and `auto-ap.ssr.ledger-test` pass, with one exception: `external-import-remove-button-test` fails identically with and without these changes, so it is pre-existing and unrelated. - `auto-ap.ssr.transaction.edit-test` still has its known `apply-rule does not exist` compile break, untouched here. - `lein cljfmt check` clean. ## Loose end, not addressed `:transaction/exclude-from-ledger` is defined in `resources/schema.edn` but read nowhere in the codebase — only `:invoice/exclude-from-ledger` is honored. If anything ever wrote that attribute expecting it to hide transactions, it never did. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
notid added 3 commits 2026-08-16 08:35:25 -07:00
A journal entry with a line posted to a bank account flagged
:bank-account/include-in-reports false shows on the SSR register but not on
the GraphQL/CLJS ledger page, which has always dropped those entries in
auto-ap.datomic.ledger/graphql-results (and the CSV export does the same in
auto-ap.routes.exports). Same entry, same filters, visible on one page and
missing from the other. The admin client form defaults the flag to false, so
any bank account saved without ticking the box is affected -- 33 of 676 bank
accounts carry an explicit false today.

Resolve the affected entries up front off VAET and drop them before sorting
rather than excluding them inside the query: the equivalent not-join measured
~36ms against ~3ms for the bare scan on a wide date range, while the two
lookups cost ~2ms and are skipped entirely for clients with nothing flagged.

Unlike the GraphQL page, which filters after pagination and so quietly serves
short pages against an unfiltered total, this runs before pagination, so the
row count matches what the register renders.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This reverts commit 6e7f66a78f.
The SSR transactions page listed transactions flagged
:transaction-approval-status/suppressed, which the GraphQL/CLJS page has
always excluded (auto-ap.datomic.transactions, the true branch of its
cond->>), as do the ledger queries in auto-ap.ledger. Suppressing a
transaction is the user's way of saying 'stop showing me this', so the same
transaction stayed visible on the page it was suppressed from.

The scan-transactions ion does no status filtering of its own, so nothing
downstream was dropping them: for the worst-affected client a five-year range
returned 14,736 rows against 3,641 real ones -- the other 11,095 were
suppressed. 22,813 suppressed transactions exist db-wide.

Filtered inside the query rather than after it so that the row count and the
amount total, both derived from fetch-ids, match the rows rendered. Measured
6ms -> 29ms on that worst-case client and range. The three status routes
(approved, unapproved, requires-feedback) constrain the status themselves and
there is no suppressed route, so no page loses its own rows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
notid merged commit 58f6714399 into staging 2026-08-16 08:40:49 -07:00
notid deleted branch worktree-revert-include-in-reports 2026-08-16 08:40:53 -07:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: notid/integreat#19