I-030 β Hardcoded payee blocks have drifted from the bank-account registry¶
Symptom (verified against Firestore + the I-023 bank statements)¶
The full ERL payee block (bank name, account number, FPS ID) is hardcoded in
7+ files instead of resolved from the bankAccount/{id} registry β and it
has drifted, in two ways that are live, customer-facing wrong:
- Wrong account number. Hardcoded:
802-756699-831. The registry β and the actual OCBC statements (I-023) β say802-757699-831(756 vs 757, one digit off). Any payer who typed the account number from a payment request got a wrong account. (FPS payers were unaffected β the request's FPS ID115278533is correct for ERL-OCBC-S β which is likely why this went unnoticed.) Sites:app/coaching/invoice/[sessionId]/client.tsx:48(DEFAULT_PAYEE),components/tools/ToolsApp.tsx:418,lib/share/fetchSharedDoc.server.ts:300(shared payment-request docs),app/tools/payment-request-preview/client.tsx:55,91. - Closed account's FPS ID on receipts. Payment receipts hardcode
fpsReceiverId: 114418007β that is ERL-DSB-S's FPS ID, a closed Dah Sing account (registry-verified). Current receipts should carry the active receiving account. Sites:components/tools/ToolsApp.tsx:404,app/tools/payment-receipt-preview/client.tsx:51,88,app/coaching/[studentId]/payment/[paymentId]/receipt/client.tsx:410. - Related seed drift:
scripts/migrate-coa.ts:61-66linksERL-DBS-S/Cwhere the canonical seed (lib/accounting/types.ts:2553) saysERL-DSB-S/C(Dah Sing). Bank name string also inconsistent ("Overseas Chineseβ¦" vs the registry's "Oversea-Chineseβ¦").
Root cause¶
The bank-account registry (bankAccount/{id} + resolveBankAccountIdentifier)
is the intended single source and works on the invoice-PDF path β but the
coaching payment-request / receipt / Tools / shared-doc surfaces predate or
bypassed it, each baking its own copy of the payee block. Copies drifted; the
registry stayed right. (Exactly the owner's suspicion: the bank-account
identifier is under-utilized.)
Escalation¶
Structural (7+ call sites need one shared resolver) β T-158 carries the
fix: a getCompanyPayeeBlock(bankAccountId) helper resolving name / clearing
code / account number / FPS ID from the registry, replacing every hardcoded
block; historical issued documents keep their frozen values by design.
Decision log¶
2026-07-02 β β Read AGENTS.md. Source: Accounting (Diagnostics) Β· https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea
Owner confirmation + hotfix (same day): owner (verbatim): "I confirm that
757699-831 is the correct one." The five wrong 802-756699-831 literals (plus
one type-comment example) were hot-fixed to 802-757699-831 immediately β
repo-wide grep now clean. The structural fix (registry resolver replacing
all literals) and the receipts' closed-account FPS ID question (nuance: a
re-rendered receipt of a DSB-era payment may legitimately reference the old FPS
ID, so it must not be blind-swapped) remain with T-158.
Found by the owner-requested hardcode sweep ("investigate whether that bank
information are hardcoded or written anywhere"). Verified against the live
registry docs (SA read-only) and the I-023 statement reconciliation before
recording: registry ERL-OCBC-S accountNumber=802-757699-831 fpsId=115278533;
ERL-DSB-S fpsId=114418007 status=closed.
2026-07-03 β renumbered I-029 β I-030¶
- β
Read AGENTS.md; renumber-on-merge (I-029 taken on
mainby the coaching-invoice-links recovery ticket). Scope unchanged; task cross-link now T-158. - Source: Accounting (Diagnostics) Β· https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea
2026-07-09 β FIXED in production¶
- β
Read
AGENTS.md. T-158 merged (PR #838 @c5e1cf75) and deployed 2026-07-03; verified still live on the current prod sha. Customer-facing payee blocks resolve from the registry; the wrong account number and the closed-account FPS ID can no longer render. Status β fixed. - Source: Accounting (Diagnostics) Β· https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea