Commit graph

32 commits

Author SHA1 Message Date
54f6f66ff8 Fix demo tax page: seed UK tax rate configs for demo user
The demo user was created after migrations ran, so TaxRateConfig rows
were never inserted for them. seed_demo() now calls seed_default_rates()
to add 2025 and 2026 UK defaults, making the tax report page load.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 23:03:19 +00:00
5ed9c52929 Fix subscriptions page including income transactions
Salary and other income marked is_recurring=True were being returned
alongside expense subscriptions. Added type='expense' filter so only
outgoing recurring transactions appear.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 23:00:09 +00:00
8fff5f4217 Extend demo seed transactions through April 2026
Adds salary, all recurring bills, groceries, eating out, coffee, and
shopping for April 2026 so the demo feels current (today is 23/04/2026).
Also adds an April net worth snapshot row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:57:39 +00:00
664b530136 Seed historical net worth snapshots and trigger live price sync on demo startup
- seed.py: adds 30 weekly NetWorthSnapshot rows (Sep 2025 → Apr 2026) so the
  Net Worth chart has full history on first boot, not just today's value
- main.py: fires price_sync_job and fx_sync_job in the background immediately
  after the scheduler starts in demo mode, so portfolio valuations are live
  from the moment the container becomes healthy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:47:44 +00:00
48c9e1acab Fix demo seed: compute account balances from transactions, fix VWRP cost basis
Account balances are now summed from the actual transaction data after insert
rather than hardcoded estimates. VWRP avg cost basis corrected to £102.21.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:38:54 +00:00
520a5a7d96 Fix demo healthcheck — use python3 urllib instead of curl (not in image)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:32:49 +00:00
fec3b809c5 Fix demo snapshot volume mount (named volume must point to directory not file)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:26:08 +00:00
58ab921068 Add DEMO_MODE=true to demo .env.example for clarity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:16:49 +00:00
db2b9898db Add demo README and mention demo in main README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:10:32 +00:00
9897d03d91 Add public demo mode with auto-seeding, hourly reset, and Portainer deploy guide
- DEMO_MODE=true env flag: disables password changes and backup endpoints (403),
  exposes GET /demo/status for frontend detection
- Auto-seed on first startup: creates demo user (demo@mymidas.app / demo123)
  with 6 months of transactions, investments, budgets, subscriptions, and tax
  payslips; takes a pg_dump snapshot immediately after for hourly restore
- Hourly reset: resetter Alpine container with cron restores DB from snapshot
  and purges uploaded attachments every hour on the hour
- Frontend: amber demo banner on all pages, login page shows credentials,
  password change disabled with notice, backups section replaced with notice
- demo/ directory: self-contained docker-compose.yml (ports 4001/8091),
  .env.example, reset.sh, and step-by-step Portainer DEPLOY.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 22:08:24 +00:00
afb5e99bb2 Add recurring transaction detection, subscriptions page, and UK tax reporting
- Recurring service: auto-detects direct debits/subscriptions from CSV imports
  using frequency analysis; manual toggle in transaction detail drawer
- Subscriptions page (/subscriptions): groups recurring payments with monthly
  cost equivalents, next-payment badges, and re-scan trigger
- UK Tax page (/tax): payslips/P60 entry, income tax + NI + CGT + dividend tax
  calculations, configurable rate tables per tax year (pre-seeded 2024/25 and
  2025/26), editable in-app so Budget changes need no rebuild
- Migration 0006: tax_rate_configs, tax_profiles, payslips, manual_cgt_disposals
  with RLS; seeds 2025/2026 rate configs for existing users
- Chart tooltip fix: all Recharts tooltips now use TOOLTIP_STYLE constant so
  they render correctly across all dark/light themes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 21:40:02 +00:00
0b326cbd87 fix: theme consistency — chart colours, axis readability, warning system
- Recharts axes: add fill to tick objects so labels are visible on dark themes
- Recharts axes: wrap stroke/gridcolor in hsl() so var() resolves to valid colour
- Chart primary lines/gradients: replace hardcoded #6366f1 with hsl(var(--primary))
  so charts adopt each theme's accent (gold on Vault, green on Terminal, etc.)
- Plotly charts: add cssVar() helper (reads getComputedStyle) to pass actual
  computed colour strings instead of unresolved var() references
- Budget radial gauge: use hsl(var(--destructive/success/warning)) for SVG colours
- Add --warning CSS variable to all 7 themes with per-theme appropriate values;
  wire into Tailwind config as themed colour
- Replace all text-yellow-500 / text-orange-500 / bg-yellow-500 with text-warning
  / bg-warning across Dashboard, Budget, Account, Predictions, Settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:58:06 +00:00
da59fa9f23 wip: transaction form and list updates (pre-theme-fixes snapshot)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:44:14 +00:00
6111424f47 Add category management UI and service layer
Users can now create, edit, and delete custom categories from Settings → Categories. System categories (45 built-in) are shown read-only. Backend adds update_category() and delete_category() service functions; frontend has a new categories API module and a full CRUD section in SettingsPage with filter tabs, colour picker, and delete confirmation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 11:50:28 +00:00
8ef3bb2965 Fix audit findings: budget editing, dead code, logging, multi-currency
- Add budget editing: updateBudget() API, edit button on budget cards,
  BudgetFormModal adapted for create/update (category locked on edit)
- Remove permanently-broken POST /auth/totp/verify stub and its unused
  TOTPVerifyRequest schema
- Wire getHoldingTransactions() to AssetDetail page — transaction history
  table now shows above the candlestick chart, sorted newest-first
- Fix multi-currency net worth in account_service: account balances are
  now converted to base_currency via ExchangeRate table before summing
- Replace silent bare pass exception handlers with logger.warning() in
  transactions.py (OCR/AI pipeline) and price_feed_service.py (search)
  — ValueError in date/number regex parsing left silent (control flow)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 10:54:32 +00:00
312594f3d2 Include investment holding values in net worth and account balances
- Net worth report, balance sheet, and daily snapshots now add holding
  market values (falling back to cost basis) to investment-type account
  balances (investment, pension, stocks_shares_isa, crypto_wallet)
- Accounts list shows total value for investment accounts with a
  breakdown line ("£X cash + £Y holdings") when both are non-zero
- Add Holding modal gains a "Debit account for this purchase" toggle
  that creates a matching withdrawal transaction, enabling proper cash
  flow tracking for users who fund their brokerage via transfer first
- Both simple (holdings-only) and full cash-flow workflows produce
  correct net worth figures without double-counting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 10:10:19 +00:00
cdc1e67321 Investment portfolio charts, search fix, and holding creation fixes
- Add four portfolio charts: allocation donut by holding, allocation
  donut by asset type, cost basis vs current value bar, return % bar
- Fix asset search to use yf.Search() full-text instead of ticker-only
  lookup — name searches like "vanguard ftse all world" now work
- Fix holding creation double-quantity bug: holdings now created with
  quantity=0 so buy transaction is sole source of quantity/cost basis
- Add per-share / total price toggle in Add Holding modal with live
  calculated equivalent shown as you type
- Add ErrorBoundary in AppShell so render errors show a message instead
  of a blank page
- Fix donut charts using || instead of ?? when falling back from
  current_value to cost_basis_total (0 was not falling through ??)
- Allow HoldingCreate.quantity >= 0 (was gt=0) to support zero-init
- Fix error display for Pydantic v2 array-of-objects validation errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 23:06:41 +00:00
26e2a055db Add AI receipt scanning with OCR pipeline and debug toggle
- OCR pipeline: Tesseract (images) + pdfplumber (PDFs) → AI text prompt →
  rule-based regex fallback; works with any text model, not just vision models
- Scan Receipt toolbar button parses a photo and pre-fills the transaction form;
  receipt image is automatically attached to the created transaction
- AI settings page: provider, API key (AES-256-GCM encrypted), custom URL,
  model, and per-user debug toggle that gates the OCR/AI debug panel
- Fix CSRF cookie secure=False so HTTP deployments work; add 7-day max_age
- Fix attachment_refs missing from _to_response (attachments never appeared in UI)
- Fix multipart boundary lost when Content-Type was set manually in axios calls
- nginx: raise client_max_body_size to 15 MB, add 120s proxy timeout for OCR
- Migration 0005: add ai_debug boolean to users table
- Update README and CLAUDE.md with AI scanning docs and architecture notes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 22:07:38 +00:00
a7c54ca61c Add raw AI response to parse result for debugging
- Backend returns raw AI text alongside parsed fields
- Drawer shows expandable "Raw AI response" section when result has empty fields
- Scan Receipt shows raw response inline if no fields were extracted
- Helps diagnose model output issues without needing server logs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 20:36:43 +00:00
1ece0908af Add Test Connection button to AI settings with plain-English error messages
- POST /settings/ai/test sends a minimal text prompt to verify the provider
- Returns ok/message — maps HTTP status codes to human-readable explanations
- 405 → "URL pointing at wrong place, check custom URL has no path suffix"
- 401 → invalid key, 404 → wrong path, 429 → rate limited, etc.
- Test button appears once a key is saved; result shown inline below buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 19:28:20 +00:00
e676e698ff Fix unused TransactionInitialValues import causing TS build error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 19:19:30 +00:00
024a8330fa Add Scan Receipt button to create transactions from receipt photos
- New backend endpoint POST /transactions/parse-receipt (file upload, no existing txn needed)
- Refactored AI call logic into shared _call_ai_parse helper (no duplication)
- Scan Receipt button in transactions toolbar → file picker → AI parse → pre-filled form
- TransactionFormModal accepts initialValues prop to pre-populate fields from receipt
- "Fields pre-filled from receipt" banner shown in form when AI-populated
- Scan error displayed inline with dismiss button
- Supports JPEG, PNG, WebP, PDF (Anthropic) or images (OpenAI)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 19:15:59 +00:00
d6118bac54 Add custom API URL and model to AI settings
- Settings → AI: optional base URL and model name fields
- Defaults to Anthropic/OpenAI public APIs when left blank
- Custom URL enables Open WebUI, LM Studio, Ollama, and any OpenAI-compatible endpoint
- Parse endpoint uses custom base URL and model if configured
- Migration 0004: ai_base_url + ai_model columns on users
- OpenAI provider label updated to "OpenAI-compatible"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 19:01:00 +00:00
b1c160f607 Fix TypeScript error: type AiSettings query result explicitly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 17:09:19 +00:00
22fc1ce2f1 Add AI receipt parsing with provider API key settings
- Settings → AI: configure Anthropic or OpenAI provider with encrypted API key
- Sparkle button on each attachment in transaction drawer sends image/PDF to AI
- AI extracts merchant, amount, date, description, category hint
- "Apply to transaction" button patches the transaction with parsed fields
- Anthropic supports images and PDFs; OpenAI supports images only
- API key stored AES-256-GCM encrypted in users table (migration 0003)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 17:07:24 +00:00
fe4e69b9ad Complete Phase 3, Phase 5 polish and hardening
Phase 3 — Investments:
- Multi-currency support: holdings track purchase currency, FX rates convert to base for totals
- Capital gains report using UK Section 104 pool method, grouped by tax year
- Capital Gains tab added to Reports page

Phase 5 — Polish & Hardening:
- Mobile-responsive layout: bottom nav, sidebar hidden on mobile, logo in TopBar, compact header buttons, hover-only actions now always visible on touch
- Backup system: encrypted GPG backups via backup.sh, nightly scheduler job, admin API (list/trigger/download/restore), Settings UI with drag-to-restore confirmation
- Docker entrypoint with gosu privilege drop to fix bind-mount ownership on fresh deployments
- OWASP fixes: refresh token now bound to its session (new refresh_token_hash column + migration), CSRF secure flag tied to environment, IP-level rate limiting on login, TOTPEnableRequest Pydantic schema replaces raw dict
- AES-256-GCM key rotation script (rotate_keys.py) with dry-run mode and atomic DB transaction
- CLAUDE.md added for AI-assisted development context
- README updated: correct reverse proxy port, accurate backup/restore commands, key rotation instructions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 14:59:11 +00:00
74e57a35c0 Fix Net Worth tab crash and rebuild for balance sheet endpoint
- Replace invalid currency="%"/currency="" StatCard calls that caused
  Intl.NumberFormat to throw RangeError and blank the page
- Render 30d change % and snapshot count as plain inline cards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:50:28 +00:00
eaea2c6ce9 Fix doubled /api/v1/api/v1 URL prefix in reports, budgets, investments
The axios client already has baseURL="/api/v1" so API calls must use
short paths (/reports/..., /budgets, /investments/...) not the full
/api/v1/... prefix. This was causing all report, budget, and investment
requests to 404.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:40:04 +00:00
dd66b2d5fe Add Balance Sheet report
New first-tab report showing a full breakdown of where money sits:
- Three KPI cards: total assets, total liabilities, net worth
- Proportional stacked bars showing asset and liability composition
- Side-by-side account lists grouped by type (Cash, Savings, ISAs,
  Investments, Pension, Crypto vs Credit Cards, Loans, Mortgages)
- Backend endpoint GET /api/v1/reports/balance-sheet with typed schema
- Balance Sheet is now the default tab on the Reports page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:33:34 +00:00
70db18e89f Add README for MyMidas
Full project documentation covering features, security architecture,
tech stack, setup instructions, backup/key rotation, and env vars.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 15:00:48 +00:00
c7b868e585 Rebrand to MyMidas
- Browser tab title: MyMidas
- Sidebar logo: Coins icon + MyMidas text
- Login page header: MyMidas
- TOTP issuer name: MyMidas (shows in authenticator apps)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 12:11:52 +00:00
61a7884ee5 Initial commit: MyMidas personal finance tracker
Full-stack self-hosted finance app with FastAPI backend and React frontend.

Features:
- Accounts, transactions, budgets, investments with GBP base currency
- CSV import with auto-detection for 10 UK bank formats
- ML predictions: spending forecast, net worth projection, Monte Carlo
- 7 selectable themes (Obsidian, Arctic, Midnight, Vault, Terminal, Synthwave, Ledger)
- Receipt/document attachments on transactions (JPEG, PNG, WebP, PDF)
- AES-256-GCM field encryption, RS256 JWT, TOTP 2FA, RLS, audit log
- Encrypted nightly backups + key rotation script
- Mobile-responsive layout with bottom nav

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 11:56:10 +00:00