- org_home.html: fix Requests/Ledger links (were pointing to non-existent
/years/{id}/requests routes; corrected to /orgs/{slug}/requests and
/orgs/{slug}/ledger). Add Analysis link. Add Close year button for admins.
- OrgRequestNew: pass events + teams to GET template so dropdowns are
populated (were silently discarded with _ = events).
- OrgRequestDetailData: add NewEvents/NewTeams fields for new-request form.
- OrgRequestUpload: implement file upload handler — saves to
/data/org-files/{org_id}/{req_id}/{id} and records metadata in MongoDB.
Register POST /orgs/{slug}/requests/{req_id}/upload route.
- org_request_detail.html: show upload form in attachments section;
populate event/team selects on new request form.
Co-authored-by: Gonçalo Rodrigues <guga@Goncalos-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds multi-tenant organisation support inside the existing finance namespace.
Users can create organisations, invite others via a copy-paste token link,
and manage teams/members with RBAC (admin, finance, member, viewer).
Fiscal year lifecycle is gated: activation requires all planned events to
be approved first. All org data lives in `org_`-prefixed MongoDB collections.
New files:
- models_org.go — domain types (Org, OrgTeam, OrgMember, OrgInvite,
FiscalYear, OrgEvent, BudgetLine, EventComment,
TxRequest with full StatusLog audit trail, etc.)
- store_org.go — MongoDB store methods for all org collections
- handler_org.go — HTTP handlers + RegisterOrgRoutes(); join invite
route lives at /join/{token} to avoid ServeMux
conflict with /orgs/{slug}/... wildcard routes
- templates/org_*.html — list, create, home, teams, members, invite, join
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove erroneous /100 in currentValue calculation (portfolio values
were 100x too small, causing net worth card to show ~€0)
- Add User-Agent header to Yahoo Finance requests (avoids 429s)
- Wrap ES module chart body in if(total>0){} block (return at top
level of a module is a SyntaxError — chart was silently broken)
- Add mobile hamburger menu: full-screen drawer at ≤720px with
animated open/close, all nav links, scroll lock while open
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Provides the 5-row Trade Republic securities CSV that
TestParseSecuritiesCSV_FromFile expects; CI was failing
with "no such file or directory".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace indigo accent palette with deep black backgrounds and
cyan-teal accents (#00c9b8 dark, #00897b light). Borders, glows,
text muted tones and background gradients all updated to match.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a holding has no price (ISIN not in the built-in map and Yahoo
rejects the raw ISIN), the portfolio page now shows an amber banner
listing each missing ISIN with an inline text input and a "Look up"
link to Yahoo Finance symbol search.
Submitting the form POSTs to /portfolio/ticker which upserts the mapping
into a finance_ticker_mappings collection keyed by (user_id, ISIN).
On the next page load custom mappings are resolved first, before the
hardcoded isinToTicker table, so user overrides always win.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
`return` at the top level of a <script type="module"> is a SyntaxError
in strict mode, so the entire Three.js chart script was killed before
executing regardless of whether prices were available.
Replaced `if (total <= 0) return` with `if (total > 0) { ... }` wrapping
the full chart body. Also filter out holdings with value=0 before building
the arc geometry so a single un-priced ISIN can't produce a zero-arc slice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without it the API returns "Too Many Requests" (not JSON), prices map
stays empty, currentValue = 0, and every holding shows -100% P&L with
an empty allocation chart.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
currentPrice is already in cents, so currentValue = price * shares.
The extra /100 made every holding appear worth 100x less than its cost,
producing ~-100% P&L on every position and an empty allocation chart
(values too small for Chart.js to render).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Merge Sharing + Household → /people (tab switcher: sharing | household)
- Merge Accounts + Categories → /settings (tab switcher: accounts | categories)
- Add Analysis dropdown in nav: Reports, Projections, Tax, Net Worth, What If
- Add Settings dropdown in nav: Accounts & Categories, Import CSV, Import Guide
- Legacy GET /sharing, /household, /accounts, /categories redirect 301 to new URLs
- Remove Import and Import Guide as standalone nav links
- New People handler consolidates all people-related mutations (_action field)
- New Settings handler renders both account and category lists in one page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Auto Import page replaced with a static Import Guide: step-by-step
instructions for CGD/Trade Republic/generic CSV export, duplicate
detection explanation, and a curl example for headless automation
- Removed POST /auto-import and DELETE /auto-import/{id} routes and
their handler logic; schedule CRUD was misleading since no bank
exposes an unauthenticated CSV endpoint
- Nav label changed from "Auto Import" to "Import Guide"
- Transactions page now renders an amber banner when redirected with
?notice=all_duplicates (every row in the uploaded file was skipped)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Compute a sha256 fingerprint (date|description|amount|account_id, first
16 hex chars) for every CSV row and store it as bank_ref. At preview
time, existing fingerprints are fetched and matching rows are shown
greyed out with a "duplicate" label. At confirm time, those rows are
silently skipped — only truly new transactions are inserted.
If every row is a duplicate the user is redirected with ?notice=all_duplicates
instead of inserting an empty batch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tax Summary (/tax): annual gross income from Income transactions,
FIFO capital gains/losses from trades, expenses by category, CSV export
- Household Mode (/household): link a partner account, combined
income/expense/disposable view for current month, shared goals list
- Auto Import (/auto-import): schedule recurring CSV imports with
account, format and optional source URL; delete schedules; webhook docs
- New store methods for households and import_schedules collections
- storeIface extended; mockStore updated; all tests still pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds server-computed alert banners to the dashboard:
- Budget exceeded (red): when a category spend is over 100% of budget
- Budget pace warning (amber): 80%+ of budget used but <80% of month elapsed
- Goal deadline risk (amber): avg savings rate too low to hit a goal on time
- Spend pace warning (amber): disposable spending is 20%+ ahead of month progress
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds /simulator page with live sliders for income change, one-off
expenses, and fixed cost shifts. Goal timelines update in real time
showing months gained/lost. Includes a savings rate bar chart from
historical monthly data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds /networth page with hero total, cash/portfolio breakdown cards,
and a month-by-month historical chart. Also shows net worth as a
value card on the dashboard with a link to the full breakdown.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Committed goals now appear in the Fixed Costs panel on the dashboard
with a "committed goal" label, and the total line uses TotalCommittedCents
(fixed costs + goal contributions) instead of total monthly expenses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Commit/uncommit button on each goal card
- Committed goals are deducted from disposable income on the dashboard
(Available to spend now reflects reserved goal contributions)
- Conflict detection: warning banner when committed goals exceed
disposable income, showing the shortfall
- Goals summary bar: disposable before goals, reserved per month,
free to spend after committed goals
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Goals page where users can plan financial goals before committing
to them. Each goal shows:
- Required monthly contribution to hit the deadline
- Months remaining vs months at current savings rate
- Disposable income impact (what's left after the contribution)
- Feasibility banner (green if on track, red with month delta if not)
- Progress bar once savings are tracked
Goal types: one-off purchase, deposit/down-payment, emergency fund,
recurring investment — each with a description hint in the creation modal.
Data: Goal model + store CRUD in finance_goals collection.
Nav: Goals tab added between Portfolio and Sharing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Exclude FixedCategories (Housing, Utilities, Subscriptions, Investments)
from budget health panel — they are committed costs, not variable spend
- Portfolio card and stocks panel now degrade gracefully to cost basis
when Yahoo Finance prices are unavailable, instead of showing €0
- Stocks panel shows "cost basis" label per holding when live prices
are not available
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the old KPI/chart dashboard with a focused layout that
answers the three key questions immediately:
- Hero block: "Available to spend" = income − fixed costs − spent so far,
with a progress bar showing % of disposable used vs month elapsed
- Bank math panel: detects recurring fixed expenses (Housing, Utilities,
Subscriptions, Investments) from last 3 months and shows the minimum
bank balance needed right now including a 2-week safety buffer
- Savings rate card with month-over-month delta
- Portfolio snapshot card with total value and P&L
- Stocks at a glance panel: per-holding value and P&L inline
- Budget health: thin bars per category, red when over limit
- Recent activity: last 5 transactions with category color dots
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GitHub Actions now only runs tests (free, cloud runners, no setup).
Deployment is manual via `make deploy-finance` / `make deploy-all`
which builds locally, imports into k3d, and applies with kubectl.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes all ghcr.io and registry dependencies. Workflows now build
images locally, import them into k3d, and deploy with kubectl set image
— all on the self-hosted runner which already has Docker and kubectl.
Also removes the github Terraform provider and ci.tf since no registry
pull secrets or GitHub Actions secrets are needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds github provider + ci.tf which provisions:
- KUBECONFIG GitHub Actions secret (from local kubeconfig)
- ghcr-credentials k8s pull secret in finance and auth namespaces
Run `terraform apply -var github_token=<PAT>` once after cluster setup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three path-filtered workflows (finance-api, auth-users, auth-gateway)
each build, push to ghcr.io, and rollout to k3s on push to main.
Deployment manifests updated from local image refs to ghcr.io with
imagePullSecrets referencing a ghcr-credentials k8s secret.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>