b2b.bank_transaction_reconcile_queue_view — every unhidden
bank_transaction row whose data -> 'reconciliation' is still '{}', with
ownership resolved through bank_account_view.
The name is load-bearing at both ends and neither is compiler-checked. Two
contract tests discover their arms by suffix against
information_schema.views: test/transactionViewContract.integration.test.ts
matches LIKE '%transaction_view' and
test/bankAccountViewContract.integration.test.ts matches
LIKE '%bank_account_view', and each asserts the discovered set equals its
own declared arm list exactly. A new view in b2b ending in either suffix
fails those tests as a bogus extra arm — which is what the original name here
(unreconciled_bank_transaction_view) did. Any view added to this schema must
end in neither.
Declared .existing(): the body is hand-written SQL in
packages/db/migrations/20261106165600_bank_transaction_hidden.sql
and drizzle-kit must not try to own it. What this declaration buys is typed
columns — bankTransactionReconcileQueueView.feedSource stops compiling if
the name moves, where a sqlfeed_source`` fragment would keep typechecking
green against a view that no longer projects it.
The two filters callers actually need are the two the base table cannot
express: customer_id (which lives behind the view's LATERAL join to
bank_account_view) and feed_source (raw ->> 'source').
BankTransactionService.search has neither, which is why the backfill reads
here rather than there.
customerId is null on the large majority of rows. Of 841 unreconciled
rows in prod, 811 are metcap FBO omnibus activity with no customer
attribution; customer_id IS NOT NULL is what reproduces the wire desk's
working list. A caller that fans out over this view unfiltered is almost
certainly doing the wrong thing.
Names come from the ambient casing: "snake_case" mapping, so feedSource
serializes to "feed_source".
b2b.bank_transaction_reconcile_queue_view— every unhiddenbank_transactionrow whosedata -> 'reconciliation'is still'{}', with ownership resolved throughbank_account_view.The name is load-bearing at both ends and neither is compiler-checked. Two contract tests discover their arms by suffix against
information_schema.views:test/transactionViewContract.integration.test.tsmatchesLIKE '%transaction_view'andtest/bankAccountViewContract.integration.test.tsmatchesLIKE '%bank_account_view', and each asserts the discovered set equals its own declared arm list exactly. A new view inb2bending in either suffix fails those tests as a bogus extra arm — which is what the original name here (unreconciled_bank_transaction_view) did. Any view added to this schema must end in neither.Declared
.existing(): the body is hand-written SQL inpackages/db/migrations/20261106165600_bank_transaction_hidden.sqland drizzle-kit must not try to own it. What this declaration buys is typed columns —bankTransactionReconcileQueueView.feedSourcestops compiling if the name moves, where asqlfeed_source`` fragment would keep typechecking green against a view that no longer projects it.The two filters callers actually need are the two the base table cannot express:
customer_id(which lives behind the view's LATERAL join tobank_account_view) andfeed_source(raw ->> 'source').BankTransactionService.searchhas neither, which is why the backfill reads here rather than there.customerIdis null on the large majority of rows. Of 841 unreconciled rows in prod, 811 are metcap FBO omnibus activity with no customer attribution;customer_id IS NOT NULLis what reproduces the wire desk's working list. A caller that fans out over this view unfiltered is almost certainly doing the wrong thing.Names come from the ambient
casing: "snake_case"mapping, sofeedSourceserializes to"feed_source".