378 lines
17 KiB
Markdown
378 lines
17 KiB
Markdown
# Bill Tracker — Future Improvements
|
||
|
||
**This document tracks potential future enhancements for Bill Tracker.**
|
||
|
||
**Last Updated:** 2026-05-11
|
||
**Current Version:** v0.24.3
|
||
|
||
## How to Use This Document
|
||
|
||
This file is a living document. Agents should:
|
||
1. Read this file before proposing changes
|
||
2. Add new recommendations with priority levels
|
||
3. Never add completed items — move those to HISTORY.md instead
|
||
4. Reference this file when dispatching improvement tasks
|
||
5. Only Ripley can remove items from this list. Notify Ripley if something neds to be removed.
|
||
|
||
### Priority Format
|
||
|
||
All items must include the priority emoji in their heading, matching the section they belong to:
|
||
|
||
| Priority | Emoji | Heading Format |
|
||
|----------|-------|---------------|
|
||
| CRITICAL | 🔴 | `### 🔴 Title — CRITICAL` |
|
||
| HIGH | 🟠 | `### 🟠 Title — HIGH` |
|
||
| MEDIUM | 🟡 | `### 🟡 Title — MEDIUM` |
|
||
| LOW | 🔵 | `### 🔵 Title — LOW` |
|
||
| NICE TO HAVE | 💭 | `### 💭 Title — NICE TO HAVE` |
|
||
|
||
Items are grouped under their priority section heading (`## 🔴 CRITICAL`, `## 🟠 HIGH`, etc.) and sorted most-impactful-first within each tier.
|
||
|
||
|
||
## Pending Recommendations
|
||
|
||
### 🔴 Import XLSX Dual-Column Layout Not Parsed — CRITICAL
|
||
**Priority:** CRITICAL
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
The real-world spreadsheet (`backups/monthly bills.xlsx`) uses a **dual-column layout** — each monthly sheet is split into two halves representing two payment periods:
|
||
- **Left half (columns A-E):** Bills due around the **1st** of the month
|
||
- **Right half (columns G-K):** Bills due around the **15th** of the month
|
||
|
||
Each half has its own `Due Date | Bill | Amount | Paid Date | Date Cleared` headers. The current parser only detects headers in the first row and processes columns linearly, so it captures the 1st-of-month bills but completely misses all 15th-of-month bills (roughly half the data).
|
||
|
||
Example from Apr 2026 sheet:
|
||
```
|
||
Left (1st): auto | Roadrunner ATV | $225.64 | paid 2026-03-01 (due ~1st)
|
||
Right (15th): | Amazon chase card | $366 | paid 2026-04-20 (due ~15th)
|
||
```
|
||
|
||
**Rationale:**
|
||
- This is the actual production spreadsheet the app needs to import
|
||
- ~100 monthly sheets spanning 2017–2026, each with two payment periods
|
||
- The 15th-of-month bills (credit cards, loans, subscriptions) are completely lost during import
|
||
- Without dual-column support, the import feature is broken for real data
|
||
- The "1st vs 15th" split is semantically meaningful — it maps to `due_day` in the bill model
|
||
|
||
**Additional Issues in This Spreadsheet:**
|
||
- Rows 1–2 contain paycheck/leftover summary data, not bills — parser must skip these
|
||
- Non-numeric amount values: "double pay", blank amounts, "past due" — need graceful handling
|
||
- Due date column contains non-date values: "auto" (autopay indicator), "24th" (day-of-month shorthand), account numbers like "9522104"
|
||
- Some sheets have slight column layout variations (extra column, merged cells)
|
||
- Sheet names have typos: "Januaru 2021", "Novevmber 2019", "Febuary 2023" — parser already handles these
|
||
- 3 non-month sheets ("2018 taxes", "debt totoals", "home ownership expenses") should be skipped — already handled by `NON_MONTH_SHEET_RE`
|
||
- "auto" in the Due Date column is an autopay flag, not a date — should be detected as a label, not parsed as a date
|
||
|
||
**Implementation Notes:**
|
||
- Modify `spreadsheetImportService.js` to detect dual-column headers in a single sheet row
|
||
- When two sets of bill headers are found (A-E and G-K), process each half independently
|
||
- Left half rows should default `due_day` to ~1, right half rows should default `due_day` to ~15
|
||
- Each half produces its own set of rows with the same sheet name/month context
|
||
- Handle non-numeric amount cells gracefully (null amount, "double pay" as a note/label)
|
||
- "auto" in Due Date column → set `autopay` label/detected label, don't try to parse as date
|
||
- "24th" in Due Date column → parse as day-of-month (24)
|
||
- Skip rows where the bill name cell is blank AND the amount cell is blank or non-numeric
|
||
- Filter out paycheck/summary rows (Row 1: Paycheck amounts, Row 2: Left Over calculations)
|
||
- The `backups/monthly bills.xlsx` file is in `backups/` (gitignored) for testing
|
||
- Files to modify: `services/spreadsheetImportService.js`, possibly `routes/import.js`
|
||
- Estimated effort: 4-6 hours
|
||
|
||
### 🔴 No Confirmation Before Destructive Actions — CRITICAL
|
||
**Priority:** CRITICAL
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
Deleting a bill or payment is one click with no confirmation dialog and no undo. For a financial app, accidental data loss destroys user trust.
|
||
|
||
**Rationale:**
|
||
- Bills and payments represent real financial commitments and history
|
||
- No "are you sure?" prompt before delete
|
||
- No undo mechanism, no soft delete, no recovery
|
||
- One misclick = gone forever — unacceptable for financial data
|
||
- This is a trust and data integrity issue, not a UX nicety
|
||
|
||
**Implementation Notes:**
|
||
- Add confirmation dialog to all delete actions (bills, payments, categories)
|
||
- Consider soft delete (`deleted_at` column) with a grace period before permanent removal
|
||
- Add undo toast after delete that allows restoration within a short window
|
||
- Files to modify: `BillModal.jsx`, `BillsTableInner.jsx`, `TrackerPage.jsx`, `CategoriesPage.jsx`
|
||
- Estimated effort: 3-4 hours
|
||
|
||
|
||
### 🟠 HIGH
|
||
|
||
### 🟠 No Search or Filter Across Bills — HIGH
|
||
**Priority:** HIGH
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
No way to find a bill by name, category, or amount. Users must scroll through the entire list to find anything. Every bill tracker on the market has instant search.
|
||
|
||
**Rationale:**
|
||
- With dozens of bills, scrolling is slow and error-prone
|
||
- No search bar on BillsPage, TrackerPage, or CalendarPage
|
||
- Can't filter by category, amount range, autopay status, or billing cycle
|
||
- Can't quickly find "where's that electric bill?" without visually scanning
|
||
- Table stakes for any list-based app
|
||
|
||
**Implementation Notes:**
|
||
- Add search input to BillsPage (filter by name, category, notes)
|
||
- Add filter chips/dropdowns for category, billing cycle, autopay, active/inactive
|
||
- Add search to TrackerPage (filter visible rows by bill name)
|
||
- Consider a global `Cmd+K` / `Ctrl+K` command palette for instant bill lookup
|
||
- Files to modify: `BillsPage.jsx`, `TrackerPage.jsx`, `client/api.js`
|
||
- Estimated effort: 6-8 hours
|
||
|
||
### 🟠 No Visible Overdue Indicators — HIGH
|
||
**Priority:** HIGH
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
Overdue bills aren't visually flagged on the tracker. An unpaid past-due bill looks the same as one not due yet. The `notify_overdue` setting exists but there's no visual distinction in the UI.
|
||
|
||
**Rationale:**
|
||
- The whole point of a bill tracker is to not miss payments
|
||
- Overdue bills should be impossible to overlook — red highlight, badge count, sticky alert
|
||
- Data model supports overdue notifications but tracker grid shows no overdue state
|
||
- Users scanning the tracker won't notice a missed bill buried in the list
|
||
|
||
**Implementation Notes:**
|
||
- Add overdue detection: if today > due date for current month and no payment logged, mark overdue
|
||
- Red/amber background on overdue tracker rows
|
||
- Overdue count badge in Sidebar next to Tracker nav link
|
||
- Optional: overdue summary banner at top of TrackerPage
|
||
- Files to modify: `TrackerPage.jsx`, `Sidebar.jsx`, `routes/tracker.js` (add overdue count to API response)
|
||
- Estimated effort: 4-6 hours
|
||
|
||
### 🟠 Filtered Export for Reports — HIGH
|
||
**Priority:** HIGH
|
||
**Added:** 2026-05-11 by Ripley (upgraded from LOW)
|
||
|
||
**Description:**
|
||
No way to export filtered data (e.g., "all bills in category X for last 6 months", "everything overdue in 2026"). Export dumps everything or nothing.
|
||
|
||
**Rationale:**
|
||
- Exporting filtered reports is core functionality for a bill tracker, not a nice-to-have
|
||
- Users need "all Q1 utility bills" or "overdue payments this year" for reconciliation and tax prep
|
||
- `/api/export/user-excel` exports everything — no query params for date range, category, or status
|
||
- This is how people actually use financial data outside the app
|
||
|
||
**Implementation Notes:**
|
||
- Add query params to export endpoints: `category_id`, `start`, `end`, `status` (paid/unpaid/overdue)
|
||
- Files to modify: `routes/export.js`, `client/pages/DataPage.jsx`
|
||
- Estimated effort: 6 hours
|
||
|
||
|
||
### 🟡 MEDIUM
|
||
|
||
### 🟡 No Bill Template / Duplicate Bill — MEDIUM
|
||
**Priority:** MEDIUM
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
Creating a new bill means filling 10+ fields every time. No way to duplicate an existing bill or use a template. If you have 3 utilities from the same provider, you're retyping everything.
|
||
|
||
**Rationale:**
|
||
- Bill creation has many fields (name, category, due day, amount, autopay, website, account, 2FA, notes)
|
||
- Common pattern: similar bills from same provider or same category with slight variations
|
||
- "Duplicate bill" is table stakes in every bill tracker
|
||
- Reduces friction and errors during bill setup
|
||
|
||
**Implementation Notes:**
|
||
- Add "Duplicate" button/action on each bill row and in BillModal
|
||
- Pre-fill all fields from source bill, clear `name` and set "(Copy)" suffix
|
||
- Files to modify: `BillModal.jsx`, `BillsPage.jsx`, `routes/bills.js` (POST endpoint can accept `source_bill_id` param)
|
||
- Estimated effort: 3-4 hours
|
||
|
||
### 🟡 No Partial Payment Support — MEDIUM
|
||
**Priority:** MEDIUM
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
The UI only supports logging a single payment per bill per month. The `payments` table schema supports multiple entries per bill, but the frontend doesn't surface this. Split payments (half now, half later) can't be tracked.
|
||
|
||
**Rationale:**
|
||
- Many bills get paid in installments (medical, tuition, large utilities)
|
||
- Payment plan arrangements require tracking multiple payments against one bill
|
||
- The data model already supports it — it's purely a frontend gap
|
||
- Without this, users either over-record or under-record partial payments
|
||
|
||
**Implementation Notes:**
|
||
- Show payment history per bill in tracker (expandable row or modal tab)
|
||
- Allow "Add partial payment" with amount + date, summing to bill total
|
||
- Display remaining balance on partially-paid bills
|
||
- Files to modify: `TrackerPage.jsx`, `routes/payments.js`, possibly `BillModal.jsx`
|
||
- Estimated effort: 6-8 hours
|
||
|
||
### 🟡 No Year-Over-Year Comparison in Analytics — MEDIUM
|
||
**Priority:** MEDIUM
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
Analytics shows monthly trends within a single year but there's no "this month vs same month last year" view. Users can't evaluate whether spending is improving.
|
||
|
||
**Rationale:**
|
||
- The whole point of analytics is answering "am I doing better or worse?"
|
||
- Within-year trends are useful but don't show long-term improvement
|
||
- Comparing April 2026 to April 2025 is the natural question people ask
|
||
- Available in every competing app (YNAB, Monarch, etc.)
|
||
|
||
**Implementation Notes:**
|
||
- Add YoY comparison toggle or tab to AnalyticsPage
|
||
- Query: same month range across current and previous year, diff the totals
|
||
- Show percentage change and absolute change per category
|
||
- Files to modify: `AnalyticsPage.jsx`, `routes/analytics.js` (add YoY endpoint or params)
|
||
- Estimated effort: 6-8 hours
|
||
|
||
### 🟡 No Bulk Actions — MEDIUM
|
||
**Priority:** MEDIUM
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
Every action is one-at-a-time. Can't select multiple bills and mark them paid, skip them for a month, or change their category.
|
||
|
||
**Rationale:**
|
||
- End-of-month reconciliation means marking many bills as paid in a row
|
||
- Category reorganization affects multiple bills at once
|
||
- Skipping seasonal bills for summer/winter requires individual clicks
|
||
- Bulk actions are standard in any list-based management UI
|
||
|
||
**Implementation Notes:**
|
||
- Add checkbox selection to BillsPage rows (with select-all toggle)
|
||
- Bulk action toolbar: Mark Paid, Skip This Month, Change Category, Delete
|
||
- Backend: batch endpoints or loop with progress indicator
|
||
- Files to modify: `BillsPage.jsx`, `BillsTableInner.jsx`, `routes/bills.js`, `routes/payments.js`
|
||
- Estimated effort: 8-10 hours
|
||
|
||
### Architecture: Business Logic Mixed with Route Handlers
|
||
**Priority:** MEDIUM
|
||
**Added:** 2026-05-08 by Neo
|
||
|
||
**Description:**
|
||
Many routes contain business logic that should be extracted to service layers.
|
||
|
||
**Rationale:**
|
||
- `bills.js` contains `parseDueDay()`, `parseInterestRate()` — validation logic
|
||
- `tracker.js` contains date/range calculations that are reused across routes
|
||
- `admin.js` has complex OIDC config building mixed with routing
|
||
- `analytics.js` has complex date-building logic (`buildMonths`, `monthKey`, etc.)
|
||
|
||
**Implementation Notes:**
|
||
- Files to modify: Multiple route files + new service files in `/services/`
|
||
- Estimated effort: 8 hours
|
||
- Proposed structure:
|
||
```
|
||
/services/billsService.js
|
||
/services/trackerService.js
|
||
/services/analyticsService.js
|
||
/services/authService.js (existing)
|
||
/services/oidcService.js (existing)
|
||
/services/cleanupService.js (existing)
|
||
```
|
||
- Route handlers should call services, not contain business logic
|
||
|
||
|
||
### 🔵 LOW
|
||
|
||
### 🔵 Payment Method Tracking and Summary — LOW
|
||
**Priority:** LOW
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
The `payments` table has a `method` column (free-text) but no way to see "how much did I pay via autopay vs manual vs credit card this month." No standardized method options, no summary.
|
||
|
||
**Rationale:**
|
||
- Useful for reconciling credit card statements vs bank statements
|
||
- Autopay vs manual tracking helps identify bills that should be switched to autopay
|
||
- Payment method breakdown is a common analytics view in financial apps
|
||
- Current `method` field is unvalidated free text — no consistency
|
||
|
||
**Implementation Notes:**
|
||
- Standardize payment methods: enum or controlled list (autopay, bank_transfer, credit_card, check, cash, other)
|
||
- Add payment method breakdown to analytics or summary page
|
||
- Files to modify: `routes/payments.js`, `AnalyticsPage.jsx` or `SummaryPage.jsx`, schema migration for method validation
|
||
- Estimated effort: 4-6 hours
|
||
|
||
### 🔵 No Keyboard Navigation or Shortcuts — LOW
|
||
**Priority:** LOW
|
||
**Added:** 2026-05-11 by Ripley
|
||
|
||
**Description:**
|
||
Only a skip link exists for keyboard accessibility. No `Cmd+K` to find a bill, no `Esc` to close modals, no arrow keys to navigate the tracker grid. Power users and accessibility need keyboard support.
|
||
|
||
**Rationale:**
|
||
- Keyboard accessibility is required for WCAG compliance
|
||
- Power users navigate faster with keyboard shortcuts
|
||
- Modal dismiss on `Esc` is expected behavior in any modern app
|
||
- Command palette (`Cmd+K`) pairs with the search feature (also missing)
|
||
|
||
**Implementation Notes:**
|
||
- `Esc` closes any open modal/dialog
|
||
- `Cmd+K` / `Ctrl+K` opens search/command palette
|
||
- Arrow keys navigate tracker rows when grid is focused
|
||
- Tab order follows logical flow, not DOM order
|
||
- Files to modify: `App.jsx`, `BillModal.jsx`, `TrackerPage.jsx`, all dialog components
|
||
- Estimated effort: 6-8 hours
|
||
|
||
### Add comprehensive unit and integration tests
|
||
**Priority:** LOW
|
||
**Added:** 2026-05-08 by Scarlett
|
||
|
||
**Description:**
|
||
Currently no unit tests exist for components or hooks. The only testing appears to be functional tests in `test-functional.js`. Component-level testing is missing.
|
||
|
||
**Rationale:**
|
||
Code quality and maintainability. Unit tests catch regressions and document component behavior. Bill Tracker has complex business logic (bill calculations, monthly state, analytics) that should be tested.
|
||
|
||
**Implementation Notes:**
|
||
- Set up Jest + React Testing Library
|
||
- Test key components: BillModal, TrackerPage row, BillsTableInner
|
||
- Test hooks: useAuth, custom form hooks
|
||
- Test utility functions in `client/lib/utils.js`
|
||
- Consider vitest for faster test execution
|
||
- Add CI integration for test execution
|
||
- Files likely to be modified: Add `client/test/` directory, add `jest.config.cjs`
|
||
- Estimated effort: 8-12 hours for baseline coverage
|
||
|
||
### Features: Missing Bill Grouping and Reorganization API
|
||
**Priority:** LOW
|
||
**Added:** 2026-05-08 by Neo
|
||
|
||
**Description:**
|
||
No way to reorder bills, drag-and-drop, or group by custom criteria.
|
||
|
||
**Rationale:**
|
||
- `bills` table has `due_day` ordering but no manual sort order
|
||
- Frontend likely orders by `due_day` only
|
||
- Users cannot create bill groups or categories for bills
|
||
- No way to mark bills as "hidden" or "archived" without deactivating
|
||
|
||
**Implementation Notes:**
|
||
- Files to modify: `/home/kaspa/.openclaw/Projects/bill-tracker/db/schema.sql`, `/routes/bills.js`
|
||
- Estimated effort: 6 hours
|
||
- Add:
|
||
- `sort_order` column to bills table (default NULL, ordered first by sort_order then due_day)
|
||
- `PUT /api/bills/reorder` endpoint accepting `{bill_id: new_index}`
|
||
- `PUT /api/bills/:id/archived` to soft-dearchive (sets `archived` flag)
|
||
|
||
|
||
### 💭 NICE TO HAVE
|
||
|
||
### Add consistent form state management pattern
|
||
**Priority:** MEH
|
||
**Added:** 2026-05-08 by Scarlett
|
||
|
||
**Description:**
|
||
Form state management is inconsistent across components. Some use `useState` for each field, others use form libraries. Validation patterns vary.
|
||
|
||
**Rationale:**
|
||
Consistency and maintainability. A consistent pattern makes it easier to add new forms and reduce bugs.
|
||
|
||
**Implementation Notes:**
|
||
- Consider react-hook-form for complex forms
|
||
- Create reusable form field components (InputField, SelectField, etc.)
|
||
- Standardize validation approach
|
||
- Files likely to be modified: `client/components/*.jsx`
|
||
- Estimated effort: 4-6 hours for migration
|