Commit Graph

20 Commits

Author SHA1 Message Date
siddharthd b8cd1b0f89 fix(reconcile): prevent split/tag double-counting on reconciled transactions
Move splits, tags and overrides from manual to statement side on reconcile
(delete from manual after copying) instead of just copying. Add read-time
filter to exclude reconciled manual transactions from balance and shared
transaction queries. Also adds participant filter to shared expenses page.
2026-05-11 19:15:41 +10:00
siddharthd 0c1f88ed9c feat(transactions): add imported date column, split filter, and sortable columns
- Show created_at as "Imported" column in transactions and shared views
- For reconciled transactions, show original CSV import date (not statement processing date) via LEFT JOIN on reconciled_with_id
- Add has_split filter (all/split only/unsplit only) to transactions page
- Transactions table: sortable by imported date; split filter dropdown
- Shared table: client-side sort by date, imported, and amount
2026-05-10 16:04:54 +10:00
siddharthd 4a49add277 feat: CSV import and batch reconciliation UI
- Add reconciled_with_id column to transactions (links manual → statement tx)
- CSV import wizard: 4-step modal (upload → map columns → review → done)
  - Handles any bank format via column mapping with localStorage presets
  - Single signed or separate debit/credit column modes
  - Editable preview table before committing
  - Auto-tags all imported rows with 'csv-import'
- Batch reconcile page: shows all unreconciled manual transactions with
  potential statement matches (date ±3 days, amount ±1%) pre-fetched
  - Select matches across multiple rows, apply all at once
  - Copies overrides/tags/splits from manual → statement tx atomically
  - Manual tx marked reconciled (linked), hidden from main transactions view
  - Transactions with no matches shown separately
- Import CSV button on transactions page
- Reconcile nav item in sidebar
2026-04-13 06:23:08 +10:00
siddharthd 0a1f6b48a2 feat(ui): mobile-responsive sidebar + rules improvements
- Sidebar: hidden on mobile, opens as slide-out drawer with hamburger
  toggle; auto-closes on navigation; desktop layout unchanged
- Layout: responsive padding accounting for mobile header bar
- Rules: add tag as a condition field (has/not-has tag)
- Rules: apply a single rule via per-rule Apply button
- Rules: splits-from defaults to 2026-01-09
2026-03-21 08:33:08 +11:00
siddharthd d53d3106f2 fix(shared): tag filter SQL precedence, balance cards filter by tag 2026-03-14 21:30:33 +11:00
siddharthd 02ac136e19 fix(payment): crash on open due to amount.toFixed on numeric string
feat(shared): tag filter on shared transactions list
2026-03-14 21:27:08 +11:00
siddharthd 85e7801407 feat(shared): replace settle buttons with payment ledger
- New split_payments table records actual payments between participants
- Balance = total split obligations - total payments (splits never marked settled)
- Record Payment modal per participant: direction toggle, amount pre-filled with balance, date, notes
- Payment history inline on each balance card with +/- display and delete
- Per-transaction Settle button removed; Action column removed from shared table
- Splits always show the true cost breakdown regardless of payment state
2026-03-14 21:09:00 +11:00
siddharthd 5206388958 feat(filters): smart query bar with amount operators and multi-select dropdowns
- Query bar parses >500, >=500, <500, <=500, 500-1500 into amount_min/max filters
- Parsed tokens shown as dismissable chips below the query bar
- Category, Bank, Tag, Type filters upgraded from single-select to multi-select
- MultiSelect dropdown component with checkbox list and active-state border
- Backend: TransactionFilters uses string[] for categories/bank_names/tag_ids/transaction_types
- SQL: ANY($n::text[]) / ANY($n::int[]) for array filters
2026-03-14 20:39:28 +11:00
siddharthd fc22a61a43 feat(transactions): manual transaction support and multi-owner query infrastructure
- Add POST /api/transactions to create manual transactions (statement_id=NULL, owner_id set directly)
- Queries switch from JOIN to LEFT JOIN statements so manual transactions are visible
- COALESCE(t.owner_id, s.owner_id) throughout for owner resolution
- Add "Manual" bank filter option in getTransactions
- Search extended to include merchant_normalized override
- Split data fetched via lateral subquery on every transaction row
- getParticipantBalances rewritten as UNION for bidirectional net balances
  (credits/refunds negate, split from either side of the relationship)
- getSharedTransactions: remove my_share_percent from SELECT (fixes GROUP BY error),
  WHERE rewritten as two distinct cases (owner with others split vs participant on others' txn)
- getTransactions: OR EXISTS condition so split participants see shared transactions
- add-transaction-modal component for creating manual transactions with splits
- 0008_my_share_percent migration adds my_share_percent to transaction_overrides
2026-03-14 20:04:00 +11:00
siddharthd af4c64bba7 feat(splits): save split as rule from split modal
- Checkbox in split modal: 'Also save as rule for <merchant>'
- Creates a rule with apply_split action storing the participant shares
- Rules engine now handles apply_split: deletes existing splits and re-applies
- Bulk split mode hides the checkbox (rule wouldn't make sense for ad-hoc bulk)
2026-03-11 12:40:03 +11:00
siddharthd 7b3fd4b65f fix(merchants): net spend accounting for refunds/credits
- Merchant totals now show net spend (gross debits minus refunds)
- Refund count and amount shown in profile drawer and table
- Scatter plot Y-axis uses net_spend, X-axis uses debit_count
- Per-merchant transaction history includes refunds (shown as negative)
- Monthly trend chart reflects net spend per month
2026-03-10 00:43:58 +11:00
siddharthd dd11019fdf fix(transactions): editable transaction type, fee/interest counted as spend, fees category
- TypeBadge is now clickable — opens inline select to change debit/credit/fee/interest/etc.
- PATCH /api/transactions/[id] now accepts transaction_type, updates transactions table directly
- Analytics monthly query includes fee and interest types as spend (not just debit)
- fee and interest amounts show red in transaction list (same as debit)
- Add fees category to taxonomy
2026-03-10 00:24:42 +11:00
siddharthd 714c5a9b25 feat(merchants): scatter plot, merchant profiles, and per-merchant transaction history
- /merchants page with spend-vs-frequency scatter chart (click to open profile)
- Merchant profile drawer: stats, monthly trend line, full transaction history
- /api/analytics/merchants: split-adjusted merchant aggregates + monthly trends
- /api/analytics/merchants/[merchant]: per-merchant transaction list
- Add Merchants nav item to sidebar
2026-03-10 00:05:48 +11:00
siddharthd c1d031511a feat(insights): committed/discretionary chart, recurring charge detection, fees & interest audit 2026-03-09 23:04:52 +11:00
siddharthd d1a0eedf03 feat(analytics): cashflow view with income/investment/net — split-adjusted + multi-currency
- Add 'investment' category (shares, ETFs, super)
- Analytics API: separate income, investment, expense queries; use amount_aud for FX-aware sums
- Analytics page: cashflow summary (income/expenses/invested/net cash), grouped bar chart,
  income + invested rows in 6-month trend table
- MonthlyAnalytics interface: add income, investments, net fields to totals
- DB: amount_aud + exchange_rate_to_aud columns added and backfilled (in prior migration)
2026-03-08 19:15:20 +11:00
siddharthd be85822cc7 merge: Phase 5 (Rules Engine) + Phase 6 (Budget & Analytics)
Resolve additive conflicts in schema.prisma and hooks.ts — both models and all hooks retained.
2026-03-08 17:09:57 +11:00
siddharthd d455738732 feat(finance): Phase 6 — Budget & Analytics
Add monthly budgets per category with spend-vs-budget dashboard and 6-month trend table.
Includes upsert budget API, monthly analytics endpoint, inline budget editing, and route auth fixes.
2026-03-08 16:57:33 +11:00
siddharthd 31cffbe1bb feat(finance): Phase 5 — Rules Engine
Add rules engine with CRUD API, condition/action evaluation, and apply-all endpoint.
UI: rule builder form with field/operator/value conditions, tag multi-select, apply button with result stats.
2026-03-08 16:56:13 +11:00
siddharthd 93450f7caa feat(finance): Phase 4 — Tags
- tags table: name, color; transaction_tags junction table
- GET/POST /api/tags; DELETE /api/tags/:id
- POST/DELETE /api/transactions/:id/tags for per-transaction tagging
- Bulk tag/untag via /api/transactions/bulk (action: tag/untag)
- Tags returned inline with transaction list via LATERAL join
- Tag filter on Transactions page
- Bulk "Tag as..." in bulk action bar
- Tag pills + "+" picker on each transaction row
- /tags page: create with color picker, list with counts, delete
2026-03-08 16:28:03 +11:00
siddharthd 35a5be97b0 feat: initial finance SPA — phases 1 & 2
Next.js 16 personal finance dashboard connected to postgres-personal.

Phase 1 (Foundation):
- API routes: GET /api/transactions (paginated, filterable, sortable),
  GET /api/statements, GET /api/merchants
- Transactions data table with date/category/bank/search filters, pagination, sort
- Statements card grid with period, due date, amount, transaction count
- Sidebar layout with nav for all planned sections

Phase 2 (Normalisation):
- PATCH /api/transactions/[id] — upsert transaction_overrides
- POST /api/transactions/bulk — bulk categorize/normalize
- Inline click-to-edit category (22 options) and merchant name
- Blue dot override indicator, bulk action bar
- Effective values via COALESCE(override, llm_value) pattern

Stack: Next.js 16 (App Router, standalone), Prisma 7.x + @prisma/adapter-pg,
TanStack Query, Tailwind CSS. Auth via Traefik chain-oauth@file.
2026-03-07 23:31:40 +11:00