From 5aa5c0cc0e0f493af2d452eedb1e41dfd735c897 Mon Sep 17 00:00:00 2001 From: null Date: Fri, 3 Jul 2026 13:34:37 -0500 Subject: [PATCH] docs(qa): mark IMP-CODE-02 fully shipped (database.js 4174 -> 1297) Co-Authored-By: Claude Opus 4.8 --- HISTORY.md | 2 +- docs/QA_PLAN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index bc47d0c..af89494 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -23,7 +23,7 @@ ### ๐Ÿงน QA Cleanup -- **[DB] Extracted the subscription-catalog seed out of `database.js`** โ€” `db/database.js` was 4,174 lines; the largest self-contained block was ~315 lines of static `subscription_catalog` seed rows. Moved them to `db/subscriptionCatalogSeed.js` (pure data, imported back), trimming the DB module to 3,859 lines. Behavior-preserving โ€” a fresh DB still seeds 291 catalog rows and the full server suite passes. (The ~2,700-line migrations array remains in place; splitting the DB core safely is a separate, dedicated task.) (was IMP-CODE-02, partial) +- **[DB] Split `database.js` from 4,174 โ†’ 1,297 lines** โ€” the DB module was dominated by three big blocks, now each in its own file: the static `subscription_catalog` seed (`db/subscriptionCatalogSeed.js`), the ~1,740-line versioned migration list (`db/migrations/versionedMigrations.js`), and the ~830-line legacy-reconcile list (`db/migrations/legacyReconcileMigrations.js`). The two migration lists are `build*(deps)` factories: each `run`/`check` body closes over the live `db` + a few schema helpers, injected so behavior is byte-identical. Verified behavior-preserving โ€” full server suite (125) passes, a fresh DB applies all 79 migrations and is idempotent, and the real production DB copy (v1.06) migrates as a clean no-op with data intact. `tests/migrationModules.test.js` locks the version-sync invariant between the two lists. (was IMP-CODE-02) - **[Banking] One canonical writer for transaction match state** โ€” a transaction's `match_status`, `matched_bill_id` and `ignored` columns must move together, but they were updated by copy-pasted inline `UPDATE`s across six routes/services โ€” the same drift that produced QA-B5-04 (a `matched` row with a `NULL` bill). Added `services/transactionMatchState.js` (`markMatched`/`markUnmatched`/`markIgnored`, ownership-scoped) and routed every single-transaction transition (match, unmatch, ignore, unignore, and unmatch-on-payment-delete) through it. Guarded bulk auto-match sweeps and the retention purge keep their own queries by design (their `WHERE` carries idempotency guards). Test: `tests/transactionMatchState.test.js`. (was IMP-CODE-03) - **[Client] One source of truth for money formatting** โ€” the client had ~15 hand-rolled currency formatters (local `fmt`/`money`/`fmtFull`/`fmtDollars`/โ€ฆ across pages and components) alongside a canonical `fmt` in `lib/utils` used at ~190 sites โ€” the same rules copy-pasted with inconsistent handling of negatives, whole-dollar, cents-vs-dollars, and blank input. Added `client/lib/money.js` (`formatUSD` / `formatUSDWhole` / `formatCentsUSD`, with `signed`/`dash`/`whole` options) as the single implementation; inputs are coerced so `null`/`''`/`NaN` never render as `$NaN` and `-0` never shows as `-$0.00`. `lib/utils.fmt` now delegates to it (byte-identical โ€” guarded by the existing `utils.test.js` suite) and the 15 local formatters were removed in favor of it. Tests: `client/lib/money.test.js`. (was IMP-CODE-01) - **[Build] Split the vendor bundle** โ€” the main `index` chunk was ~659 kB (over Vite's 500 kB warning). Added `build.rollupOptions.output.manualChunks` (`vite.config.mjs`) to split React, Radix, framer-motion, and TanStack into separately-cacheable vendor chunks; the index chunk dropped to ~334 kB and the warning is gone. (was QA-B0-01) diff --git a/docs/QA_PLAN.md b/docs/QA_PLAN.md index 2bdb7b5..8f9d49b 100644 --- a/docs/QA_PLAN.md +++ b/docs/QA_PLAN.md @@ -215,7 +215,7 @@ graduate to `roadmap.md`/`FUTURE.md`. | ID | Lens | Area (`file`/page) | Proposal (what & why) | Effort | Status | |----|------|--------------------|-----------------------|--------|--------| | IMP-CODE-01 | Code | `client/lib/money.js` (+16 files) | ~~No shared client money formatter.~~ **Shipped `a15f00c`:** added `client/lib/money.js` (`formatUSD`/`formatUSDWhole`/`formatCentsUSD`); `lib/utils.fmt` delegates to it and 15 local formatters were removed. `null`/`NaN`/`-0` all handled. Test `client/lib/money.test.js`; full client suite + build green. | M | โœ… Shipped | -| IMP-CODE-02 | Code | `db/database.js` (4,174โ†’3,859 ln) | **Partly done `7f2faea`:** extracted the ~315-line static subscription-catalog seed to `db/subscriptionCatalogSeed.js`. **Remaining:** the ~2,700-line migrations array is the biggest block but is the DB core โ€” splitting it needs a dedicated, carefully-tested pass (a bad move corrupts every DB on boot), not a blind autonomous refactor. | L | ๐ŸŸก Partial | +| IMP-CODE-02 | Code | `db/database.js` (4,174โ†’1,297 ln) | ~~Oversized module.~~ **Shipped `7f2faea`,`026c6a5`,`12d9d4c`:** split into `subscriptionCatalogSeed.js` (data), `migrations/versionedMigrations.js` (~1,740 ln factory), `migrations/legacyReconcileMigrations.js` (~830 ln factory) โ€” db + helpers injected, behavior byte-identical. Verified: suite 125, fresh DB 79 migrations idempotent, real prod DB no-op with data intact. Test `tests/migrationModules.test.js`. | L | โœ… Shipped | | IMP-CODE-03 | Code | `services/transactionMatchState.js` | ~~Overlapping match logic.~~ **Shipped `fa24322`:** added canonical `markMatched`/`markUnmatched`/`markIgnored`; routed the 6 single-transaction transitions through it (guarded bulk sweeps keep their own queries by design). Test `tests/transactionMatchState.test.js`. | M | โœ… Shipped | | IMP-IA-01 | IA | Sidebar ยท `/data` | ~~Central features under an overflow menu.~~ **Shipped `0b1c6a8`:** Data moved into the main app nav (desktop dropdown + mobile) alongside Bills/Categories/Spending; same default-admin gate preserved; removed the redundant account-dropdown entry. | S | โœ… Shipped | | IMP-UX-01 | UX | Bills delete | ~~Retention isn't surfaced.~~ **Shipped `aace5a4`:** Bills shows a "Recently deleted (N)" button opening a restore dialog (amount, category, days-left); `GET /api/bills/deleted` (30-day window). Test `tests/billsDeletedRoute.test.js`. _Categories/payments could get the same treatment later._ | M | โœ… Shipped |