## Ergebnis: Frontend-Inventar Sprint 14 ### 1. Routing und Navigation - Das Portfolio besitzt aktuell **nur eine Sammelroute**: - `/portfolio` → `PortfolioPage.vue` (`frontend/src/router/index.ts:41`) - Fachseiten: TrueWealth, PostFinance und Cash unter `/portfolio/*` (`router/index.ts:42-44`), Aktien und Crypto dagegen als `/equity` bzw. `/crypto` (`router/index.ts:45-47`). - `/analysis/performance` ist weiterhin eine **veraltete Roadmap-Seite** mit dem Text, Performance werde „nicht in diesem Sprint gebaut“ (`router/index.ts:93`), obwohl die Performance bereits in `/portfolio` eingebettet ist. - Die Hauptnavigation führt „Vermögen“ auf `/portfolio`; Unterpunkte existieren nur für Cash, Aktien/ETFs, Crypto und TrueWealth (`frontend/src/navigation/userNav.ts:60-73`). - Seitentitel und Hilfe hängen am Routennamen; `/portfolio` nutzt `meta.title = Portfolio` (`router/index.ts:41`, `components/AppLayout.vue:30-33`, `help/pageHelp.ts:15`). ### 2. Aktuelle Komposition von `PortfolioPage.vue` Alle Bereiche werden untereinander auf einer sehr langen Seite angezeigt (`frontend/src/pages/PortfolioPage.vue:5-30`): 1. Gesamt-KPIs (`:6`) 2. Links zu PostFinance und TrueWealth (`:7`) 3. `PortfolioAnalyticsPanel` mit Benchmark **und** Risiko (`:8`) 4. kompakter Kontenabgleich/Datenstand (`:9-20`) 5. `DataIngestionReconciliationPanel` (`:21`) 6. `PortfolioPerformancePanel` (`:22`) 7. `PortfolioPolicyManager` (`:23`) 8. Asset-/Plattform-Allokation (`:24-25`) 9. Advisor-/Investment-Signale („Allokations- und Datenchecks“) (`:26-29`) 10. Top- und unbewertete Positionen (`:30`) Ein bestätigter Import remountet das Performance-Panel und lädt Übersicht sowie Analytics neu (`PortfolioPage.vue:44-45,64-65`). ### 3. Performance-/Benchmark-Dopplung #### `PortfolioPerformancePanel.vue` - Eigene Periodensteuerung mit YTD, 1 Jahr oder benutzerdefiniert sowie TWR/MWR-Auswahl (`frontend/src/components/performance/PortfolioPerformancePanel.vue:11-35`). - Zeigt TWR, XIRR/MWR, Anfang/Ende, Cashflows, Gebühren, Steuern (`:46-77`), Portfolio-Zeitreihe (`:53-63`) und Reproduzierbarkeitsmetadaten (`:79-84`). - Verwendet `/api/portfolio/performance` mit exakten Von-/Bis-Daten und aktuellem `data_cutoff` (`:127-133`; `frontend/src/api/portfolio.ts:63-68`). - Der API-Typ enthält bereits eine optionale `attribution` mit Marktpreis-, FX-, Ertrags-, Gebühren-, Steuer- und Cashflow-Beiträgen (`api/portfolio.ts:26`). **Diese Attribution wird im Panel derzeit überhaupt nicht gerendert und nicht getestet.** #### `PortfolioAnalyticsPanel.vue` - Enthält zwei fachlich unterschiedliche Karten: - „Performance gegen Benchmark“ (`frontend/src/components/portfolio-data/PortfolioAnalyticsPanel.vue:8-45`) - „Risiko und Verteilung“ (`:47-82`) - Die Benchmark-Karte zeigt erneut Portfolio-TWR, Benchmark, Differenz und eine zweite Portfolio-Zeitreihe (`:28-39`). - Verwendet `/api/portfolio/analytics?period=…` mit relativen Perioden 1m–2y (`:15-18,152-160`; `api/portfolio.ts:58`). #### Fachliches Drift-Risiko Die beiden Oberflächen verwenden unterschiedliche Verträge und Einheiten: - Performance: `summary.twr` als Dezimalrendite, z. B. `0.21` → `21.00%` (`api/portfolio.ts:23`; `PortfolioPerformancePanel.vue:120`). - Analytics: `twr_pct` als Prozentpunkte, z. B. `8.4` → `8.40 %` (`api/portfolio.ts:40`; `PortfolioAnalyticsPanel.vue:105`). - „1 Jahr“ kann wegen exakter Datumsgrenzen/Data-Cutoff versus Backend-Preset unterschiedlich ausfallen. Damit können auf derselben Seite zwei ähnlich bezeichnete Portfolio-Performances und zwei Charts mit abweichenden Ergebnissen erscheinen. ### 4. Daten-/Importbereiche Es bestehen drei nahe verwandte Oberflächen: - Kompakter Konten-/Snapshot-Abgleich direkt in `PortfolioPage.vue:9-20`, gespeist durch `/api/portfolio/reconciliation-snapshot` (`api/portfolio.ts:55`). - `DataIngestionReconciliationPanel` mit: - Quellenstatus (`frontend/src/components/portfolio-data/DataIngestionReconciliationPanel.vue:11-16`) - PostFinance-DOCX bzw. kanonischen Quellen, Preview → Confirm (`:18-40`) - Reconciliation/Coverage (`:43-58`) - Ingestion-Historie (`:60`) - Separate PostFinance-Fachseite mit vollständigerem ZIP+PDF-Import und eigener Historie (`frontend/src/pages/PostFinancePage.vue:17-35,47-50`). Die beiden PostFinance-Importwege sind fachlich verschieden, aber für Nutzer nicht klar abgegrenzt: DOCX-Stichtagsbestand im Portfolio-Panel versus offizielle ZIP/PDF-Depot-/Ledger-Quellen auf der PostFinance-Seite. ### 5. Strategie - `PortfolioPolicyManager` enthält aktive Policy-Auswertung, versionierte Preview/Confirm-Schreibstrecke und Historie (`frontend/src/components/policy/PortfolioPolicyManager.vue:14-69,116-122`). - Historische Details zeigen Benchmarks und Einschränkungen (`:109-112`). - Der Draft-Typ unterstützt `benchmarks` (`frontend/src/api/portfolio.ts:6`), aber das Bearbeitungsformular bietet **kein Benchmark-Eingabefeld** (`PortfolioPolicyManager.vue:26-58`). Gleichzeitig verweist die Benchmark-Analyse darauf, eine aktive Policy mit Benchmark zu konfigurieren (`PortfolioAnalyticsPanel.vue:131-138`). Das ist derzeit ein UX-Sackgassenhinweis. - Die read-only Advisor-Signale liegen separat in `PortfolioPage.vue:26-29` und passen fachlich ebenfalls in „Strategie“. ## Kleinste empfohlene Restrukturierung Keine neuen Seitenkomponenten und keine vier neuen Router-Routen. Stattdessen: - `/portfolio` kompatibel belassen. - Vier direkt verlinkbare Query-Tabs einführen: - `/portfolio?tab=uebersicht` – Default auch bei fehlendem Parameter - `/portfolio?tab=performance` - `/portfolio?tab=daten` - `/portfolio?tab=strategie` - `/analysis/performance` auf `/portfolio?tab=performance` umleiten, statt die widersprüchliche Roadmap-Seite zu zeigen. Empfohlene Zuordnung: - **Übersicht:** KPIs, Risiko/Verteilung, Asset-/Plattform-Allokation, Top-/unbewertete Positionen. - **Performance:** ein konsolidierter `PortfolioPerformancePanel` mit TWR/MWR, Attribution und Benchmarkvergleich. - **Daten & Importe:** Datenquellenlinks, kompakter Konten-/Snapshot-Abgleich, Ingestion/Reconciliation/History; klarer Link zum vollständigen ZIP/PDF-PostFinance-Import. - **Strategie:** `PortfolioPolicyManager` und Advisor-Signale. Für den kleinsten Komponentenumbau sollte `PortfolioAnalyticsPanel` einen Modus wie `risk | benchmark` erhalten. Im Benchmark-Modus nur Benchmark, relative Differenz und Vergleichskurve anzeigen; das zweite eigenständige Portfolio-TWR-KPI entfernen. Alternativ kann dieser Benchmarkteil direkt in `PortfolioPerformancePanel` integriert werden. Der Analytics-Risikoteil bleibt unverändert in „Übersicht“. Der Query-Ansatz vermeidet Änderungen an globaler Sidebar, Mobile Navigation, PageHelp und Route-Metadaten und unterstützt trotzdem Direktlinks sowie Browser-History. ## Testauswirkungen - `PortfolioPage.test.ts:33-70`: auf vier Tabzustände aufteilen; bisher erwartet der Test Policy, Abgleich, Advisor und Übersicht gleichzeitig. - Neue Assertions für Default/Fallback bei unbekanntem Tab, Direktlink und sichtbare Exklusivität der Bereiche. - `PortfolioAnalyticsPanel.test.ts:47-101`: Risiko- und Benchmarkmodus getrennt testen; bisher wird die kombinierte Karte vorausgesetzt. - `PortfolioPerformancePanel.test.ts:23-64`: Benchmark-Integration und vor allem `attribution` einschließlich partial/unavailable/null ergänzen. - `DataIngestionReconciliationPanel.test.ts:48-99` und `PortfolioPolicyManager.test.ts:85-195` können weitgehend unverändert bleiben. - `UserNavigationSmoke.test.ts:8-58`: Redirect von `/analysis/performance` und Auflösung des Performance-Deep-Links ergänzen; bei Query-Tabs sind keine neuen Sidebar-Routen erforderlich. - `api/client.test.ts:10-39` deckt aktuell nur `getOverview` aus `portfolio.ts` ab. URL-/Query-Verträge für Analytics und Performance fehlen und sollten ergänzt werden. - Falls echte Unterrouten statt Query-Tabs gewählt würden, müssten zusätzlich `pageHelp.ts`, Routentitel und Mobile-/Navigationstests erweitert werden. ## Verifikation / Arbeitsbaum - Inventar erfolgte auf Base `9f2102ae25407dec1d8800e976186a112aea7825`. - Keine Dateien erstellt oder geändert; `git status --short` und `git diff --check` waren leer/grün. - Der fokussierte Vitest-Lauf konnte nicht starten, da im Worktree die Frontend-Abhängigkeiten `vite` und `@vitejs/plugin-vue` nicht installiert sind. Das ist ein Umgebungsblocker, kein festgestellter Testfehler.