Commit Graph

22 Commits

Author SHA1 Message Date
666acb65fa Add financing route unit tests
Tests cover remainingPeriods pure function (single/split plans, boundary
cases), GET/POST/GET:id/PUT/DELETE /api/financing, and
PATCH /api/financing-payments/:id/paid including auto-close when fully paid.
Uses mid-month dates in pure function tests to avoid UTC timezone boundary issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:10:44 -04:00
1106ec770c Add paychecks route unit tests
Tests cover GET /api/paychecks (virtual + saved), GET /api/paychecks/months,
POST /api/paychecks/generate, PATCH /api/paychecks/:id (gross/net),
PATCH /api/paycheck-bills/:id/amount, and PATCH /api/paycheck-bills/:id/paid
(paid toggle + amount_override locking).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:08:49 -04:00
e9f5a48f2d Add unit testing infrastructure with Vitest
Set up Vitest for both server (Node + Supertest) and client (jsdom + React
Testing Library). Extract Express app into app.js for testability. Add example
tests covering bills validation, bills route CRUD, ThemeContext, and App nav
rendering. Update CLAUDE.md with testing docs and requirement to write tests
with features.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 21:03:29 -04:00
6e771ad20b Fix variable bill amount lost on paid toggle; revert gross/net protection
- PATCH paycheck-bills/:id/paid: variable bills now preserve amount_override
  rather than overwriting it with b.amount (which may be null/0). Fixed bills
  continue to lock in b.amount on paid and clear on unpaid.
- generatePaychecks: revert gross/net protection — refresh always updates
  gross/net from current settings as originally intended.
- CLAUDE.md: remove gross/net protection note; add td approve sub-agent rule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:41:57 -04:00
5aaa5cfed8 Fix timezone hazard in financing start_date guard
Replace new Date(date_string) + getFullYear/getMonth with direct string
parsing (split('-').map(Number)) so month comparisons are never shifted
by UTC offset. Affects both buildVirtualPaychecks and generatePaychecks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:39:47 -04:00
119d53c33a Add start_date to financing plans and protect paid paychecks from refresh
- Migration 004: adds start_date column to financing_plans (DEFAULT CURRENT_DATE)
- generatePaychecks: skips financing plans whose start_date is after the target month
- buildVirtualPaychecks: same start_date guard for virtual previews (already applied)
- generatePaychecks upsert: preserves gross/net when paycheck has any paid bills
- financing.js POST/PUT: accept and store start_date
- Financing.jsx: add Start Date field to create/edit form (defaults to today)
- CLAUDE.md: document start_date guard and paid-paycheck refresh protection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:37:37 -04:00
2d152f301d Add special financing feature
Data model:
- Migration 003: financing_plans and financing_payments tables
- Plans track total amount, due date, paycheck assignment (1, 2, or split)
- Payments linked to paycheck records, one per period

Payment calculation:
- Auto-calculated: (total - paid_so_far) / remaining_periods
- Split plans halve the per-period amount across both paychecks
- Recalculates each period as payments are made

Financing page (/financing):
- Create/edit/delete plans with name, amount, due date, paycheck assignment
- Progress bar showing paid vs total
- Overdue badge when past due with remaining balance
- Paid-off plans moved to a separate section

Paycheck view:
- New Financing section per column with payment checkbox
- Overdue badge on individual payments
- Running paid/total shown in bill meta
- Financing payments included in remaining balance calculation
- Auto-closes plan and reloads when fully paid off
- Lazy generation works: first interaction generates paycheck and payment records

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:28:09 -04:00
45383b80cf Add variable amount bills
- Migration 002: variable_amount boolean column on bills (default false)
- Bills form: 'Variable amount' checkbox; amount field becomes optional
  'Typical amount' when checked; table shows 'varies (~$X)' and a 〜 badge
- Paycheck view: variable bills show a pencil edit button to enter the
  month's actual amount, stored as amount_override on paycheck_bills
- New PATCH /api/paycheck-bills/:id/amount endpoint
- Lazy generation still works: setting an amount on a virtual paycheck
  generates it first then saves the override

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:14:08 -04:00
3bac852a40 Lazy paycheck generation, regenerate button, inline gross/net edit
- GET /api/paychecks returns virtual data (id: null) without writing to
  DB when no records exist for the month
- First interaction (bill toggle, OTE add, actual add) lazily calls
  POST /api/paychecks/generate to persist the paycheck
- New PATCH /api/paychecks/:id to update gross and net
- Regenerate/refresh button syncs gross/net from current Settings
- Inline pencil edit for gross/net on each paycheck column header
- 'preview' badge and info banner shown for unsaved months

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:06:41 -04:00
195a36c8a5 Add Recharts charts to Monthly Summary and Annual Overview
Monthly Summary:
- Spending breakdown donut (bills / variable / one-time)
- Variable spending by category bar chart
- Added actuals.by_category to /api/summary/monthly response

Annual Overview:
- Income vs. spending grouped bar chart
- Surplus/deficit bar chart (green/red per month)
- Stacked variable spending by category across all months
- New /api/summary/annual endpoint (single DB round trip for full year)
- AnnualOverview now uses /api/summary/annual instead of 12 parallel calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:58:50 -04:00
ea2ee9c5e6 Lock bill amount_override when marked paid, clear on unpaid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:53:46 -04:00
00b55338af Fix pay_date NaN: parse DATE columns as strings in pg
pg returns DATE columns as JS Date objects which serialize to ISO
timestamps, causing split('-') to produce NaN for the day portion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:51:05 -04:00
3d41c623bc Fix dev compose: npm install on container startup
The ./server bind mount overwrites /app/server including node_modules
installed during the Docker build. Running npm install on startup
ensures deps are present after the volume mount.

Also reverts the node_modules named-volume workaround in favor of
this cleaner approach (requires node installed locally for non-Docker dev).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:27:52 -04:00
22b1cfbe6b Add monthly summary view
GET /api/summary/monthly returns income, bills, actuals,
and one-time expense totals. Summary page shows stat cards
and a breakdown table with surplus/deficit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:15:25 -04:00
17af71a7c7 Add variable expense actuals logging
API for expense categories and actuals with full CRUD.
Paycheck view shows actuals section and includes them in
remaining balance calculation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:12:25 -04:00
9ada36deda Add one-time expenses per paycheck
API for adding, removing, and marking one-time expenses paid.
Paycheck view supports inline add form and paid/delete actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:12:07 -04:00
8a9844cf72 Add paycheck-centric main view
Two-column monthly view showing bills, amounts, paid status,
and remaining balance per paycheck. Month navigation included.
Also adds PATCH /api/paycheck-bills/:id/paid endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:09:51 -04:00
afe3895210 Add paycheck generation and retrieval API
Auto-generates paycheck records from config and active bills.
GET /api/paychecks auto-generates if month not yet created.
Idempotent generation preserves existing paid status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:08:03 -04:00
0835b86c1a Add bills CRUD API and management UI
Full REST API for bill definitions with validation.
Bills page supports add, edit, toggle active, and delete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:06:43 -04:00
5f5f1111c5 Add config API and settings UI
GET/PUT /api/config for pay dates and amounts.
Settings page fetches and saves configuration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:04:33 -04:00
adebe10f52 Add PostgreSQL schema and migration runner
All tables per PRD data model with default config seeds.
Migration runner tracks applied migrations in DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:03:57 -04:00
83abac52f6 Add Docker Compose project scaffold
Sets up the full monorepo structure with:
- Multi-stage Dockerfile (client-build + production stages)
- docker-compose.yml for production, docker-compose.dev.yml overlay for development
- Express server (port 3000) with pg pool, health route, and SPA static file serving
- React 18 + Vite client with react-router-dom v6, nav bar, and placeholder page components
- .env.example with PostgreSQL and app config
- Empty db/migrations/ directory for future migrations
- CLAUDE.md updated with development workflow commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:02:17 -04:00