T 110
uid: T-110 title: Records page β restore WOPC list after the T-089 migration + drop the All tab status: done area: accounting-records created: 2026-06-24 updated: 2026-06-24 related: T-089, I-011
Why¶
Two Records-page tab problems the owner reported on 2026-06-24, fixed in one PR:
- The WOPCs tab showed nothing. A previous change reshaped how WOPC documents are
stored β it moved the "created" timestamp and the reference number out of the top level and
into a
WOPC.*group (T-089, the WOPC doc-shape restructure, done 2026-06-24). But the code that lists WOPCs for the Records page still asked Firestore to "sort by the top-level createdAt" β and Firestore silently drops every document that doesn't have the field you sort by. After the migration no WOPC has a top-levelcreatedAt, so the list came back empty even though all 34 WOPCs are still there. (See I-011 for the symptom record.) - The "All" tab was misleading. It combined WOPCs + project invoices + coaching invoices but never included receipts or bank statements, so it was never actually "all documents." The owner asked to drop it.
Verified (live Firestore, tebs-epl)¶
- 34 WOPCs exist:
payees/JC/wopc/*(33) +payees/JN/wopc/*(1). - 0 / 34 carry a top-level
createdAt; it now lives atWOPC.created.at. The reference number likewise moved toWOPC.refNumber(top-levelreferenceNumberis gone; the doc id is the storage form, e.g.ERL-WOPC|2024-001). - So
getAllWOPCs'.orderBy('createdAt','desc')matched nothing β empty tab.
What changed¶
lib/wopc.server.tsβgetAllWOPCs+getWOPCsForPayee:- Dropped
.orderBy('createdAt', 'desc')from the Firestore query (it was the silent filter). The subcollection is now read unordered so every doc comes back. - Reconstruct the display
referenceNumberfromWOPC.refNumber(fallback: the doc id viatoDisplayFormat) and surface it at the top level of the returned object, so the Records serializer + CSV export (which readw.referenceNumber) keep working unchanged. - Sort in memory by the bucketed
WOPC.created.at(via the canonicalgetCreatedaccessor inlib/wopcDocShape). The old in-memory sort read the now-absent top-levelcreatedAt, so it was a silent no-op too. components/records/RecordsApp.tsxβ removed thealltab, its now-deadallRows/allColumns/totalCount, the orphanedWOPC_STATUS_COLOR/WOPC_STATUS_LABELmaps and theAnyRowtype; added a?tab=allβwopcsdeep-link remap so stale links land on a real tab.
Why it's built this way¶
- Reconstruct the ref number at the seam (
getAllWOPCs) instead of rewriting every downstream consumer. The Records serializer readsw.referenceNumberin ~6 places (row key, Drive lookups, CSV links). Normalising once where the docs are loaded keeps the blast radius to one function and avoids touching the serializer / CSV / detail-drawer paths that already work viatoView. - Read unordered + sort in memory rather than
.orderBy('WOPC.created.at'): there are only ~34 WOPCs across 2 payees, so the in-memory sort is trivial and needs no composite index, and it tolerates the handful of legacy docs whose timestamp shape differs.
Decision log¶
2026-06-24 β opened + fixed¶
- β
Attestation (Records (Infrastructure)): read
AGENTS.md; scope-scanned the board by scope β T-089 is the migration (done); this is the read-path regression it left in the Records list, which no existing task covers. The All-tab drop is a sibling owner request landing in the same PR. - Source: Records (Infrastructure) Β· https://claude.ai/code/session_018RDB37kCqfouHdygVXTAtD
- Proposed by: the owner. Approved by: the owner (verbatim, 2026-06-24):
"I have recently restructured the fields in WOPCs and I think that's probably why the WOPC tab on the Records page is now showing no WOPCs at allβ¦ Can you help me look into it?" "Let's proceed to fix the WOPCβ¦" "β¦I'd rather that we drop the All tab once and for all as I don't think I'll ever look at mixed type of documents in a single tab anyways"
- Commit:
6dfb0a1don branchclaude/records-wopc-empty-drop-all-tabβ PR tomain(branch policy 2026-06-24:mainπ’ /nightlyπ΄ β merge tomainonly). - Verification: root cause proven against live Firestore (0/34 WOPCs have top-level
createdAt). Could not runtscin-sandbox (nonode_modules); the change is a small, self-contained edit using the existinglib/wopcDocShapeaccessors already used by the Records serializer. Owner to confirm the WOPC tab populates after deploy. - Blast radius:
getAllWOPCsfeeds the Records WOPC tab + its CSV export;getWOPCsForPayeefeeds payee-scoped WOPC reads. Both now return the bucketed-shape WOPCs. No change to the WOPC write path, the signing flow, ortoView. The All-tab removal touches onlyRecordsApp.tsx(the per-type tabs are unchanged). The Coaching Invoices tab is not addressed here β it's empty for a different reason (see I-012).