Skip to content

Rebuild Investments with cash-linked trades, performance and portfolio history - #147

Merged
31b4 merged 78 commits into
mainfrom
epic/123-investment-rework
Oct 20, 2026
Merged

31b4 merged 78 commits into
mainfrom
epic/123-investment-rework

Conversation

@31b4

@31b4 31b4 commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Closes #123

Summary

Rebuild Investments around direct cash-linked purchases and sales, a responsive portfolio overview, compact holding details, and historical value/performance tracking. Values, costs and gains are derived from recorded trades, dated manual valuations, market prices and historical exchange rates, with explicit missing-data coverage instead of invented history.

This is the complete epic/123-investment-rework → main integration. All 20 merged child PRs are listed below. Their issues, including #135, are already closed; this PR closes only the parent epic. The existing transaction composer, splits and MCP review workflows from main are retained.

Changes

Portfolio overview and holding details

  • Responsive summary, portfolio-value versus net-invested chart, allocation by holding/type/quote currency, and sortable/filterable holdings with native 30-day trends. Category filters affect holdings without narrowing portfolio totals or history.
  • Compact holding dialogs show instrument identity, value/gain, position details, price charts, average-cost references, dated trade markers and ordered history. Full-row opening retains keyboard-accessible controls. Display charts and markers use the same split-adjusted price basis; stored executions and raw accounting inputs remain unchanged.
  • Distinct figures for lifetime realized/unrealized gains, holding gain against remaining basis, the simple Gain on net invested ratio, and covered daily-linked range estimates. These measures are not interchangeable. Investment price returns exclude dividends.
  • HUF, USD and EUR reporting across summaries, history, holdings and previews; native instrument prices retain their quote currency and source time. Modestly delayed quotes are identified beside prices, while older/unavailable inputs retain warnings.
  • Shared privacy/theme behavior, accessible controls, session-memory snapshots, bounded lazy detail histories and retained data/drafts on failed reads or saves. New holding setup starts with asset search/manual selection before category and pricing fields.

Cash-linked trades, holdings and manual values

  • A dedicated Buy/Sell editor collects units, actual execution price/currency/date, included fees and exact cash settlement. Nonmutating previews show resulting cash, position, basis and sale gain before saving. Cross-currency settlement requires explicit acknowledgement after the review; quotes are draft suggestions, not execution facts.
  • Purchases/sales create reciprocal investment and cash rows in one guarded batch. Versioned edits/deletion update both sides together; replay receipts protect unchanged retries, and timeline validation rejects supported overselling. New investment trades start on Investments; Dashboard income/expense/transfers offer cash accounts, while existing linked ledger rows still open the canonical editor.
  • Separate ETF/stock/crypto/manual categories, pricing methods, holding units and fiat quote currencies. Dated openings/corrections preserve recorded quantities without fake cash transactions. Complete matching recorded trade history can explain a position without requiring a redundant zero-opening confirmation.
  • Legacy purchase-detail review can complete missing execution/payment facts without moving units or cash again. Unknown historical costs, fees, currencies and FX remain explicit rather than being inferred from current prices.
  • Dated total/per-unit manual valuations have independent history, correction controls, as-of dates and reminders. Whole-asset acquisition/disposal controls ownership; a zero appraisal does not dispose of the asset or create a cash flow.

Accounting, history and reliability

  • Moving weighted-average remaining basis, exact net invested and realized/unrealized gains use dated acquisition/cash-flow FX. API/client and independent MCP reads share supported calculation rules, retaining their documented complete-versus-warned-partial total policies. MCP gains no investment write tools.
  • Daily portfolio history uses dated quantities, prices, manual observations and FX, including sold/archived holdings during ownership. Calendar ranges and cash-flow-adjusted estimates preserve unknown coverage and gaps; history is bounded to ten years and explicit work limits.
  • Normalized Yahoo quotes/daily history, dated ECB FX through Frankfurter and a reconstructible source cache reduce repeated requests. Request-scoped provider work avoids cross-request Worker I/O failures. Cache refreshes do not mutate financial facts or the financial revision.
  • Decimal arithmetic and guarded atomic batches protect ordinary cash writes, transfers, splits, account corrections, pending confirmation/decline and recurring occurrence consumption. Balance, ledger and audit changes commit together; stale edits and repeated confirmation cannot silently overwrite or double-apply posted facts. Narrowly evidenced legacy residue recovery preserves genuine fractional balances.
  • Preserve locks/archive rules, pending/MCP-review projection isolation, reciprocal-link exports and revision guards. Dashboard net worth honors holding exclusions; Investments retains all active holdings.
  • Consolidate unreleased investment notes into a dedicated changelog section, preserving general app entries and published release history.

Included pull requests

Every PR below is merged into the epic and its merge commit is an ancestor of the reviewed head. Linked child issues are already closed.

Work Issue Merged PR
Reciprocal transfer links and atomic pair mutations #122 #125
Accounting and legacy-data contract #126 #136
Holding metadata and opening positions #127 #137
Direct cash-linked buys and sells #128 #139
Dated manual valuations and ownership #129 #140
Normalized/cached market prices, history and dated FX #130 #141
Shared values, cost basis, gains and previews #131 #142
Historical portfolio values and range returns #132 #143
Responsive overview, allocation and holdings #133 #144
Holding details and exact-cash trade editor #134 #145
Integrated validation and atomic shared cash writes #135 #146
Decimal balance drift and verified residue recovery #148 #149
Recorded-history support and legacy cost confirmation #150 #151
Concurrent chart reads and historical FX boundaries #159 #160
Dividend-excluding price returns without losing known costs #161 #162
Delayed-quote presentation #163 #164
EUR reporting #165 #166
Holdings presentation and supported return percentages #167 #168
Main integration, split compatibility and migration verification #169 #170
Final overview/detail polish and unified trade entry #171 #172

Verification

  • Current head: 42b818c1aa02adf5cf753ead31528b91adb77e39. Both epic push CI and PR merge CI completed successfully, including their aggregate CI passed checks: workflow validation, API/client/MCP tests, the additional Node 26 client suite, real Worker/D1 integration, deployment tests, API/MCP types, client production build and lint.
  • Main at f2b5711e803516fce225518b0c0903b8a06bffe0 is included in the epic; GitHub currently reports no merge conflicts. The required approving review remains outstanding. This description update creates no commit or deployment.
  • Recorded database evidence: disposable October 8/12 export rehearsals covered preservation of existing financial columns/row IDs and migration history, integrity/foreign keys, exports, reads and mutation round trips. The combined-schema follow-up verified all 22 fresh migration files and combined/main-first/epic-first upgrades, including injected late-failure rollback. The October 12 rehearsal was repeated at implementation head 59f93bb; the only subsequent commit changes the changelog. Original exports were unchanged, private copies removed, and export rehearsals made no outbound provider requests.
  • Recorded UI/behavior evidence: earlier integrated browser review used real local Workers/D1 with synthetic financial/market fixtures for desktop/mobile, light/dark, privacy, fractional buys, partial sales, linked edits/deletion, failed appraisal saves, stale refresh and navigation/focus. Later UI polish is covered by client/chart/editor regressions and final-head CI; that earlier browser review is not a claim of a new full visual pass over the latest design.
  • Detailed methods, bounds and historical evidence: integrated validation, accounting, current metrics and decimal balances. Earlier test counts in child PRs describe those checkpoints, not current suite sizes.

Migration and rollout

Five investment migrations are added relative to main: 017-investment-transfer-links.sql, 018-investment-holding-metadata.sql, 019-investment-trade-facts.sql, 020-manual-investment-valuations.sql and 021-market-data-cache.sql. Keep main's independent 017-transaction-splits.sql unchanged too: the custom migration ledger tracks complete migration names, not numeric prefixes. Fresh installs apply all 22 files; upgrades apply only missing names. See the migration guide.

  1. Before production action, retain a fresh SQL backup and rerun scripts/rehearse-investment-upgrade.mjs locally against it. October snapshots do not certify later live activity.
  2. Arrange a write-free window covering browser/API/MCP writers and scheduled execution; there is no built-in maintenance switch. Review the deployment plan before applying changes.
  3. Apply pending investment migrations in order 017 links → 018 → 019 → 020 → 021, preserving the existing split migration/history, then deploy API → MCP → client against the same D1 schema. API/MCP-only deployment refuses pending migrations. The documented full rollout is npm run deploy -- --with-mcp after separate authorization.
  4. Verify cash/units, reciprocal links, legacy unknowns, manual valuation dates, exports and financial revision/forecast freshness. Existing holdings need no recreation; unknown history is not backfilled with guessed facts.
  5. On failure, stop writes, preserve the database and inspect schema/history before remediation. Do not blindly replay applied SQL or assume an old writer is safe after upgrade; rehearse recovery on a copy. Restoring a backup would discard later activity and requires its own decision.

Boundaries

No broker cash wallet, tax-lot accounting, automated dividend/corporate-action posting or MCP investment writes. Free/unofficial provider availability, bounded history and incomplete opening/cash/price/FX/event coverage can limit values or returns. Split-adjusted display charts do not rewrite original trades. Local fixtures and CI do not certify live provider uptime, Access/OAuth or production migration recovery. No version bump, release, main merge or production rollout is performed by updating this PR.

31b4 added 30 commits October 17, 2026 00:46
…links

Make investment transfer links reciprocal and mutations atomic
…g-contract

Define investment accounting and legacy-data compatibility
…g-metadata

Add explicit investment holding metadata and opening positions
…-trades

Record direct cash-linked investment buys and sells
…-valuations

Track dated manual investment values and whole-asset ownership
Normalize and cache investment market inputs
@31b4 31b4 added this to the Investment Page Rework milestone Oct 20, 2026
@31b4 31b4 changed the title Rework investments with linked trades and historical portfolio tracking Rebuild Investments with cash-linked trades, performance and portfolio history Oct 20, 2026
@31b4
31b4 merged commit 5ca00c7 into main Oct 20, 2026
22 checks passed
@31b4
31b4 deleted the epic/123-investment-rework branch October 20, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Epic: Rework the Investments page and portfolio foundations

1 participant