Make the GCP/Workspace auto-matcher arrears-aware (catch the recurring charges)
Goal¶
From the T-030 / unexplained-charge analysis: GCP & Workspace charges match their invoice EXACTLY on amount (Β±HK$0.01) but post ~1 month in ARREARS β the charge lands 2β24 days (GCP) / 2β154 (Workspace, median 5) AFTER the invoice period closes. So Β±1-day date matching catches NONE; amount is the reliable signal. Adjust the matcher: 1. Pair a Google charge to the PRIOR-period invoice (arrears), match on amount Β±0.01 + a forward date window wide enough for the arrears (~45β60d covers GCP max 24 and most Workspace; the 154-day Workspace outlier is an edge case to LOG, not chase). (GCP linker dateWindowDays is already 45; the Workspace/vendor path's 14-day window is likely too tight β widen for the Google sources.) 2. RE-RUN the GCP + Workspace auto-linkers β all invoices show transactionCount:0 (never linked). Consider triggering this from the new auto-sync-on-app-usage (T-023). 3. Keep amount tolerance TIGHT (Β±0.01) β it's exact; widening it would risk false hits.
Residual (NOT fixable by tuning β flag, don't chase)¶
- 26 Workspace invoices truly-unmatched = mostly recurring HK$156.70 from 2022β2023, which PREDATE the bank-tx history (~2024+). No bank tx exists β can't match; acknowledge/exclude.
- 3 GCP truly-unmatched (HK$14.82 Aug-2025, 759.91 May-2026, 301.02 Jun-2026) β tie to the May/Jun 2026 spend-spike + prepaid top-ups; investigate separately.
Log¶
- 2026-06-14 created from the T-030 / "unexplainable" analysis. Not started.
- 2026-06-14 DONE (code). Two changes, both arrears-driven:
- GCP
lib/gcpBilling/types.tsDEFAULT_MATCHING_CONFIG: dateTolerance 21β45 (max observed arrears was 24d, so 21 missed the tail); amountToleranceAbsolute 5.00β1.00 (the $5 floor was absurd for sub-$1 charges). - Workspace
pages/api/workspace-billing/auto-link.ts: auto-link window 14β45d (review 45β90); ADDED ausedTxnIdsguard + oldest-first ordering so the wide window can't double-link the recurring HK$156.70 charges to two invoices. Verified (dry-run, greedy 1:1): - GCP: 15/18 invoices now auto-link (was 0). The 3 left are the anomalies β 202508 $14.82, 202605 $759.91, 202606 $301.02 (the spend-spike/top-ups).
- Workspace: ~13 link. KEY FINDING: there are 46 Workspace invoices but only ~16 Workspace bank charges β the other ~30 have NO matching payment (mostly 2022β2023 pre-bank-history + months not charged to this account / different amount). So the matcher is no longer the bottleneck; bank-charge availability is. The fix catches everything that HAS a payment. The linkers run from the GCP/Gadgets view (components/gadgets/GcpDetailApp,GadgetsApp) β the backlog auto-links on next view-open. (Did NOT bulk-write the ~28 links from a script β left to the view-trigger / owner go-ahead.) Typecheck clean.