Skip to content

Coaching page showed missing/partial sessions, wrong balances, no vouchers/invoices for migrated students — page still read the pre-T-079 top-level Sessions location

Symptom

Owner, 2026-07-01 (verbatim): "look into the Coaching page and the information that page fetch and write on Firestore, and see why some information are not being shown (I have previously migrated and restructured coaching related firestore docs, and apparently, some of the things didn't get re-write or re-routed afterwards)."

On the coaching dashboard, students whose sessions had been migrated showed missing or partial data — empty/short session lists, wrong (often zero) Balance Due, no voucher counts, and no invoice indicators. Other students looked fine, so it read as "some information not being shown."

Root cause

The T-079 "sessions under students" migration moved coaching sessions from the top-level Sessions/ collection to Students/{abbr}/Sessions/{id} (new shape: inline origStartTimestamp/origEndTimestamp, invoice as a map field), and converted the accounting/records consumers to collectionGroup('Sessions'). The coaching page readers were never re-pointedCoachingSessionsApp, SessionsTab, lib/billing/compute.ts, lib/coaching/useBillingInfo.ts, RetainersTab, lib/sessions.ts all kept querying the old top-level Sessions where sessionName == account, and SessionDetail/RateModal wrote vouchers/rates to the old top-level path.

Live-data audit (tebs-mel, 2026-07-01): 67 sessions had moved to Students/{abbr}/Sessions, while 46 legacy sessions remained orphaned in top-level Sessions/ (the T-079 migration script skips docs with no abbr/studentAbbr). Zero id-overlap. So the page (reading only top-level) saw only the orphan scraps per student — e.g. Nancy Kwai showed 2 of 21, Kiri T 22 of 50, Lok Chow 1 of 12, Jake Ngai 0 of 1; students never migrated (Asa/Ceh/ET/ML/OJ) looked fine.

Fix

Escalated to T-146 (structural): all coaching-page session reads/writes routed through a new shared source lib/coaching/sessionsSource.ts (canonical nested location + legacy fallback); new-shape awareness (inline timestamps, invoice map field); the 46 orphans re-homed into Students/{abbr}/Sessions (scripts/rehome-orphan-coaching-sessions.ts); stale root-doc session summaries backfilled; Firestore rule added for the nested session sub-subcollections. See T-146 for the full decision record, verification, and blast radius.