Zum Inhalt

ARCH-2026-002 – Snapshot-basierte Reportdatenpipeline und reporttypspezifische ViewModels

Status: Entwurf
Proposal-Status: under_review
Kategorie: architecture
Erstellt: 2026-07-05
Stand: 2026-07-07
Geprüfter Repository-Stand: f84c881aace65ff9aa857b43fc2de4b0a7998397

Anlass

Die verbindliche Reporting-Spezifikation erlaubt ausschließlich einen unveränderbaren aktuellen AnalysisResult-Snapshot oder einen gespeicherten PropertyRecord-Snapshot als Reportquelle.

Die aktive Implementierung kombiniert diese Snapshots weiterhin mit bereits formatierten und gerenderten DOM-Inhalten. Zusätzlich fehlen eine normalisierte Reportquelle, der spezifizierte ReportData-Aufbau, vollständige Reportmetadaten und klar abgegrenzte reporttypspezifische ViewModels.

Bestätigte Teilentscheidung 1 – Umfang

Am 2026-07-07 wurde Variante B bestätigt:

ARCH-2026-002 wird nicht auf die Entfernung einzelner DOM-Lookups aus
reports.js begrenzt.

Das Proposal umfasst die vollständige Datenkette von AnalysisResult oder
PropertyRecord bis zu strukturiertem, kanonischem und reporttypspezifischem
ReportData.

Alle Reporttexte, Tabellen und Charts, die fachliche Snapshotinformationen
darstellen, müssen aus dieser Datenkette entstehen. Gerenderte Dashboard-
oder Reportelemente sind keine Datenquelle.

Die konkrete Zielstruktur, die Annahme des Gesamtproposals und die spätere Integration bleiben offen.

Ausgangsproblem

Die heutige Reporting-Pipeline ist keine reine Snapshot-Pipeline:

AnalysisResult
+ PropertyInput-Snapshot
+ gerenderte KPI-Karten
+ gerenderte Szenariotabelle
+ gerenderte Annahmen
+ gerenderte Plausibilitätsdarstellung
-> reports.js getReportData()
-> Report-HTML
-> nachgelagerte Chart-Ersetzung

Der Report kann dadurch von UI-Labels, DOM-Strukturen, Renderreihenfolge und globalem Frontend-State abhängen.

Relevanter bestehender Stand

Führende Regeln:

docs/specification/user-interface-and-reporting/reporting.md
  Reportvorschau aus AnalysisResult
  gespeicherter Bericht aus PropertyRecord
  Formular und gerenderte UI sind keine Reportquelle
  ReportDataBuilder strukturiert vorhandene Werte
  Report rendert und erklärt

docs/specification/user-interface-and-reporting/report-types.md
  One Pager, Investment Report und Bank Report besitzen eigene Pflichtinhalte
docs/specification/model-and-calculations/calculation-interfaces.md
  Reports rechnen keine Fachwerte, Schwellen oder Ratings neu
docs/specification/data-quality-and-validation/validation.md
  unberechnete Formularwerte verändern keinen Report
  ältere PropertyRecords werden nicht still neu berechnet

Betroffene Implementierung mindestens:

frontend/assets/js/reports.js
frontend/assets/js/reports-entry.js
frontend/assets/js/chart-standardization-ui.js
frontend/assets/js/analysis-result.js
frontend/assets/js/result-compatibility.js
frontend/assets/js/property-record-adapter-v2.js
frontend/assets/js/property-record-ui.js
frontend/assets/js/property-record-store.js

Betroffene Prüfungen mindestens:

scripts/check-single-analysis-controller.mjs
scripts/check-single-analysis-browser.mjs
scripts/check-chart-standardization.mjs
scripts/check-chart-standardization-browser-v3.mjs
scripts/check-browser-acceptance-readiness.mjs
scripts/check-property-record-adapter.mjs
scripts/check-property-record-store.mjs
scripts/check-analysis-contract.mjs

Nachgewiesene aktuelle Architekturabweichungen

1. Gemischte Reportquellen

reports.js liest gleichzeitig Snapshotfelder und die gerenderten Bereiche:

#summary
#kpi-grid
#scenario-table-body
#assumption-list
#plausibility-list

Damit werden kanonische Daten und sichtbare UI-Texte vermischt.

2. Sichtbare Labels als technische Schlüssel

KPI-Werte werden unter anderem über sichtbare Texte wie Cashflow Jahr 1, Anfangs-LTV oder Net vs ETF Ende gesucht. Eine redaktionelle UI-Änderung kann daher Reportwerte verändern, obwohl der Snapshot unverändert ist.

3. Heutiges getReportData entspricht nicht dem spezifizierten ReportData

Die Spezifikation nennt Bereiche wie:

report_meta
property_summary
input_summary
scenario_summary
financing_summary
cashflow_summary
wealth_summary
rent_estimate_summary
rating_summary
data_quality_summary
assumption_origins
scenario_policies
scenario_controls
warnings
open_checks
decision_summary_text
model_limits

Das heutige Zwischenobjekt enthält nur eine unvollständige Mischung aus inputs, results, kpis, DOM-Zeilen und DOM-Texten.

4. Unvollständige Reportmetadaten

Es fehlen insbesondere die vollständige Zuordnung zu:

report_id
report_type
analysis_result_id
object_id optional
Modell- und Engine-Version
Schema-, Konfigurations- und Methodenversionen
PropertyRecord-Version optional
Mietdaten-Dataset-Metadaten optional

5. Nicht snapshotgetreue Herkunftsangaben

Zentrale Eingaben werden pauschal als manual oder manual/default bezeichnet. Die tatsächliche Herkunft kann unter anderem default, derived, object_type_adjusted, estimated oder missing sein und muss aus dem gebundenen PropertyInput stammen.

6. Unstrukturierte Szenario- und Plausibilitätsdaten

Szenariozeilen und Plausibilitätsmeldungen werden aus sichtbarem Zell- und Elementtext übernommen. Dadurch werden ScenarioRating, Begründung und Befunde vermischt und können von nachträglichen DOM-Umbauten abhängen.

7. Reportcharts umgehen eine einheitliche Datenpipeline

reports.js erzeugt Reportcharts. chart-standardization-ui.js beobachtet anschließend den Report-DOM, liest erneut den globalen AnalysisResult und ersetzt Charts anhand sichtbarer Überschriften.

8. Kanonische und Legacy-Felder werden vermischt

Neue Reportdaten müssen kanonische Feldnamen wie terminal_net_vs_etf_after_exit verwenden. Legacy-Aliase dürfen nur in einem klar abgegrenzten Eingangsadapter gelesen werden.

9. Kein gemeinsamer Reportquellenvertrag

Ein PropertyRecord wird aktuell zu einer AnalysisResult-kompatiblen Sicht normalisiert. Dabei müssen jedoch PropertyRecord-Metadaten wie object_id, Schemaversion und Legacy-Status erhalten bleiben. Ein formaler gemeinsamer Reportquellenvertrag fehlt.

10. Reporttypen sind nicht vollständig abgebildet

One Pager, Investment Report und Bank Report enthalten derzeit nicht durchgängig alle spezifizierten Bereiche, insbesondere Versionen, Datenqualität, Mietschätzung, Szenario-Controls, offene Prüfungen und Rating-Komponenten.

Dokumentationswiderspruch vor Integration

reporting.md verlangt für jeden Case ScenarioAssessment, ScenarioRating und Begründung. report-types.md sagt für den One Pager, Best und Stress zeigten ScenarioAssessments, aber kein vollständiges Rating.

Dieser Widerspruch muss vor der Integration geklärt werden. ARCH-2026-002 darf ihn nicht still im Code entscheiden.

Abgrenzung zu ARCH-2026-001

ARCH-2026-001 verantwortet

wann ein Report aktualisiert wird
welcher AnalysisState den Renderauftrag auslöst
welches Modul #report-preview besitzt
wie Initial-, Calculated-, Dirty-, Loaded- und Error-State wirken
wie globale Setter, Timer, künstliche Klicks und MutationObserver entfallen

ARCH-2026-002 verantwortet

welche Snapshotquelle zulässig ist
wie AnalysisResult und PropertyRecord normalisiert werden
welche kanonischen Reportdaten entstehen
welche Daten jeder Reporttyp erhält
wie Tabellen, Texte und Charts aus ReportData entstehen
wie Metadaten, Versionen und Herkunft transportiert werden
wie Snapshottreue und Reportvollständigkeit getestet werden

Gemeinsame Integrationsgrenze:

ARCH-2026-001 liefert einen expliziten, konsistenten Snapshot und Renderauftrag.
ARCH-2026-002 erzeugt daraus deterministisch ReportData, ein reporttypspezifisches
ViewModel und die Reportdarstellung.

ARCH-2026-002 führt keinen parallelen Frontend-State, keinen künstlichen UI-Trigger und keine zusätzliche globale Analysis-Quelle ein.

Geltungsbereich

ARCH-2026-002 umfasst:

AnalysisResult- und PropertyRecord-Source-Adapter
normalisierte gemeinsame ReportSource
kanonisches Basis-ReportData
reporttypspezifische ViewModels
vollständige Reportmetadaten
kanonische KPI- und Projektionsfelder
Annahmenherkünfte
Szenario-Policies und Szenario-Controls
ScenarioAssessment und ScenarioRating
Investment Rating als getrennten Analysewert
Datenqualität und Mietschätzung
Warnungen und offene Prüfungen
Modellgrenzen
Reporttexte, Tabellen und Charts
DOM-unabhängige Tests
Snapshotparität zwischen AnalysisResult und PropertyRecord

Nicht Teil dieses Proposals:

State- und Aktualisierungsorchestrierung aus ARCH-2026-001
Änderung von Formeln, KPIs, Schwellen oder Ratings
neue fachliche Reportinhalte ohne Spezifikationsentscheidung
persistiertes oder externes ReportData-Schema
serverseitige PDF-Erzeugung
Backend oder Datenbank
vollständiges visuelles Redesign
Objektvergleich und Batch-Report

Vorgeschlagenes Zielprinzip

AnalysisResult
-> AnalysisResultReportSourceAdapter

PropertyRecord
-> PropertyRecordReportSourceAdapter

beide
-> normalisierte ReportSource
-> BaseReportDataBuilder
-> kanonisches BaseReportData
-> reporttypspezifisches ViewModel
-> ReportRenderer einschließlich Charts
-> HTML / Browser-Druck

Source-Adapter

Sie dürfen kanonische Snapshotfelder lesen, zulässige Legacy-Aliase normalisieren und fehlende optionale Felder ausdrücklich kennzeichnen.

Sie dürfen keine Formularwerte oder aktuellen Defaults lesen, keine alten Snapshots neu berechnen und keine fehlenden Ratings oder KPIs ableiten.

Normalisierte ReportSource

Die konkrete Struktur ist noch zu entscheiden. Sie soll mindestens enthalten oder referenzieren:

source_kind
source_id
analysis_result_id
object_id optional
property_input
scenario_results
base_summary_kpis
investment_rating
data_quality_assessment
warnings
calculation_status
Modell-, Engine-, Schema-, Konfigurations- und Methodenversionen
PropertyRecord-Metadaten optional
Legacy- und Kompatibilitätshinweise optional

BaseReportData und ViewModels

BaseReportData bildet die spezifizierten ReportData-Bereiche ab. Darauf aufbauend werden empfohlen:

buildOnePagerViewModel(baseReportData)
buildInvestmentReportViewModel(baseReportData)
buildBankReportViewModel(baseReportData)

ViewModels wählen vorhandene Werte aus und ordnen sie. Sie rechnen keine Finanzwerte, Assessments oder Ratings neu.

Determinismus und Build-Kontext

Zielregel:

identischer Snapshot
+ identischer Reporttyp
+ identischer expliziter Build-Kontext
= identisches ReportData und identisches ViewModel

reportId und createdAt werden explizit übergeben. Der Builder liest Zeit und Zufallswerte nicht implizit aus globalen APIs.

Regeln für Texte und Charts

Der Renderer darf statische Überschriften, Erläuterungen, Modellgrenzen und spezifizierte Checklisten ergänzen.

Dynamische Aussagen zum konkreten Objekt müssen aus ReportData stammen. Nicht zulässig sind neu abgeleitete Ratings, KPI-Schwellen, Kaufempfehlungen, vermutete Herkünfte oder DOM-basierte Zusammenfassungen.

Reportcharts erhalten ausschließlich strukturierte Datenreihen aus dem ViewModel. Sie lesen weder globalen State noch Report-DOM und werden nicht nachträglich durch einen zweiten Renderer ersetzt.

Weitere offene Einzelentscheidungen

2. ReportSource-Vertrag
   Gemeinsame Quelle und Behandlung von PropertyRecord-Metadaten.

3. BaseReportData-Struktur
   Konkrete Felder sowie required, optional und missing.

4. Reporttypspezifische ViewModels
   Gemeinsames Superset oder klare Projektionen je Reporttyp.

5. Rating- und Szenariodarstellung
   Trennung von ScenarioAssessment, ScenarioRating und Investment Rating.

6. Herkunft, Policies und Controls
   Struktur für Annahmenherkunft, fixed/scenario_adjustable und Sliderwerte.

7. Warnungen, offene Prüfungen und Decision Summary
   Snapshotquellen und Grenze zu statischen Renderertexten.

8. Chart-ViewModels
   Datenreihen und zulässige gemeinsame Chart-Hilfsfunktionen.

9. Interne Versionierung
   Versionskonstante oder formaler Vertrag erst bei Persistenz/API.

10. Migrationsfolge und Abhängigkeit zu ARCH-2026-001

Entscheidungsmehrwert

vollständige Übereinstimmung mit dem Reporting-Vertrag
stabile Reports trotz UI-Änderungen
klare Trennung von Normalisierung, Datenaufbereitung und Darstellung
DOM-unabhängige Tests
kanonische Feldnamen und nachvollziehbare Versionen
echte statt vermutete Annahmenherkunft
strukturierte Ratings, Warnungen und offene Prüfungen
identische Datenbasis für HTML, Druck und spätere PDF-Ausgabe
keine parallele Fachberechnung im Reporting

Auswirkungen

Architektur:

Snapshot -> SourceAdapter -> ReportSource -> BaseReportData -> ViewModel -> Renderer
DOM bleibt ausschließlich Ausgabeziel.

Roadmap:

Voraussetzung für belastbare Reports aus Meine Objekte
Grundlage für spätere serverseitige PDF-Erzeugung
Integration nach den relevanten State- und Owner-Entscheidungen aus ARCH-2026-001

Formeln und KPIs:

keine Änderung
keine Neuberechnung
keine neue Rating- oder Assessmentlogik

Datenverträge und Versionen:

keine Änderung bestehender persistierter Schemas erwartet
keine Modellversionserhöhung erwartet
ReportSource und ReportData zunächst interne Verträge
Engine-Version bei aktiver Frontendänderung prüfen

Tests und Referenzfälle

Erforderlich:

Builder und ViewModels funktionieren ohne document und window
keine DOM-Lookups in Source-Adaptern, Buildern oder ViewModels
identischer Snapshot und Build-Kontext erzeugen identisches ReportData
UI-Labeländerungen verändern ReportData nicht
AnalysisResult und PropertyRecord ergeben identische fachliche Reportbereiche
PropertyRecord-Metadaten bleiben erhalten
kanonische Feldnamen werden verwendet
Legacy-Aliase werden nur im Source-Adapter normalisiert
ScenarioAssessment, ScenarioRating und Investment Rating bleiben getrennt
Herkunft und Sliderwerte stammen aus PropertyInput
fehlende Werte werden gekennzeichnet und nicht erfunden
Reportcharts verwenden nur ViewModel-Daten
alle drei Reporttypen erfüllen ihre Pflichtinhalte
Browser-Druck bleibt funktionsfähig
bestehende Modell-, KPI-, Rating- und Snapshot-Regressionen bleiben grün

Legacy- und Migrationsfolgen

keine Datenmigration erwartet
bestehende PropertyRecords bleiben unverändert
Legacy-Felder werden nur beim Lesen normalisiert
alte PropertyRecords erhalten sichtbare Kompatibilitäts- und Versionshinweise
Reporttypen können einzeln auf ViewModels umgestellt werden
DOM-Lookups und nachgelagerte Chartkorrekturen entfallen erst nach nachgewiesener Parität

Risikoanalyse

Proposal-Aktualisierung:

niedrig

Spätere technische Umsetzung:

mittel

Die Änderung ist gut umsetzbar und weniger tief in die Engine eingebunden als ARCH-2026-001. Das Hauptrisiko sind stille Auslassungen oder abweichende Reportinhalte.

Besonders gefährdet:

KPI-Zuordnung
ScenarioRating und Investment Rating
Annahmenherkunft
Warnungen und offene Prüfungen
Reportmetadaten
PropertyRecord-Berichte
Mietschätzung und Datenqualität
Charts
Drucklayout

Sicherungs- und Rückfallstrategie vor Umsetzung

Vor dem ersten Code-Commit:

aktuellen main-Commit und erfolgreichen Contract Check festhalten
separaten Integrationsbranch verwenden
bei gemeinsamer Umsetzung den Baseline-Tag aus ARCH-2026-001 referenzieren

Für einen anonymisierten vollständigen Beispielsnapshot sichern:

AnalysisResult-Fixture
entsprechender PropertyRecord-Fixture
HTML-Ausgabe aller drei Reporttypen
Screenshots aller drei Vorschauen
Browser-Druck- oder PDF-Referenz
sichtbare KPIs, Ratings, Warnungen und Versionen

Jeder Reporttyp wird separat umgestellt und getestet. Regressionen werden zurückgerollt und nicht durch neue DOM-Lookups oder Korrekturrenderer verdeckt.

Empfohlene Umsetzungsstruktur nach vollständiger Annahme

Phase 0
  Fixtures, Screenshots und Druckreferenzen sichern

Phase 1
  Source-Adapter und normalisierte ReportSource

Phase 2
  BaseReportData, Metadaten, Herkunft, Ratings und Warnungen

Phase 3
  One Pager, Investment Report und Bank Report als eigene ViewModels

Phase 4
  Renderer und Charts umstellen
  DOM-Lookups und nachgelagerte Chartkorrekturen entfernen

Phase 5
  Integration in den Renderauftrag aus ARCH-2026-001
  Browser-, Druck- und PropertyRecord-Abnahme

Diese Struktur wird erst nach den offenen Einzelentscheidungen verbindlich.

Prüfergebnis

Die ursprüngliche Problemfeststellung ist weiterhin korrekt. Nachgewiesen sind zusätzlich:

unvollständiger und nicht dokumentierter ReportData-Vertrag
fehlende Reportmetadaten
nicht snapshotgetreue Herkunftsangaben
unstrukturierte Szenario- und Plausibilitätsdaten
nachgelagerte Chart-Ersetzung aus globalem State
fehlender gemeinsamer Reportquellenvertrag
unvollständige reporttypspezifische Pflichtinhalte
unzureichende Reporttests

Die Erweiterung auf die vollständige Snapshot-basierte Pipeline mit normalisierter ReportSource, kanonischem BaseReportData und reporttypspezifischen ViewModels ist sachlich erforderlich.

Die technische Korrektur ist möglich und mittel riskant. Sie soll nach den relevanten Entscheidungen aus ARCH-2026-001 integriert und durch feste Snapshot-, Browser- und Druckreferenzen abgesichert werden.

Entscheidung

Teilentscheidung 1 am 2026-07-07 bestätigt:

Variante B – ARCH-2026-002 umfasst die vollständige Snapshot-basierte
Reportdatenpipeline, normalisierte Reportquellen, kanonisches Basis-ReportData,
reporttypspezifische ViewModels sowie Reporttexte, Tabellen und Charts.

Die Zuständigkeitsgrenze zu ARCH-2026-001 ist ausdrücklich festgelegt.

Gesamtentscheidung: offen
Proposal-Status: under_review

Zieldokumente bei späterer Annahme

docs/specification/user-interface-and-reporting/reporting.md
docs/specification/user-interface-and-reporting/report-types.md
docs/specification/architecture/project-structure.md
docs/specification/model-and-calculations/calculation-interfaces.md
docs/specification/data-quality-and-validation/validation.md
docs/specification/product-domains-and-workflows/saved-objects.md
docs/roadmap/roadmap.md
docs/roadmap/current-status.md

Integrationscommit

offen