Files
MeterVault/tests
schmidt.florian 7e34aeccc8
ci / build-test (push) Successful in 1m24s
Meter chain topology + per-energy-type flow (Sankey) pages
Adds a meter hierarchy and a flow view: a downstream meter is a *subsection*
of an upstream one (not an addition), so you can see where a main meter's flow
divides — e.g. official water → garden, pool, other; grid/battery → all → car.

- MeterLink (schema + migration AddMeterLinks): a directed from→to flow edge.
  Multi-parent allowed (a merge, e.g. grid + solar → house); multi-child is a
  split. Cascade-deletes with either endpoint; unique + distinct-endpoint checks.
- FlowService: per energy type + period, builds a Sankey graph — nodes = meters
  sized by consumption; link value = downstream meter's consumption, split
  proportionally across multiple upstreams; unaccounted remainder under a meter
  becomes a synthetic "Other" node; depth via topological longest-path.
- SankeyChart.razor: hand-rolled inline-SVG Sankey (ApexCharts has no Sankey
  type) — columns by depth, nodes stacked by value, bezier ribbons sized by flow,
  left→right, theme-aware, HTML-encoded labels, tooltips. Built as a MarkupString
  to sidestep Razor's <text> element clash.
- /energy/{id} page (one per energy type): KPIs (consumption + cost), the flow
  Sankey, and the meter list. NavMenu now lists a link per energy type
  (Electricity, Water, Gas, …) loaded from the DB.
- Meters admin: cycle-safe "Sub-meter of (upstream meters)" multi-select
  (descendants excluded to prevent cycles); reconciles meter_link rows on save.
- Reference data seeds a demo chain (Haus → Auto) so electricity flow shows
  Haus dividing into Auto + Other.

Tests: FlowServiceTests (single-parent remainder; two-parent proportional
split); render test now asserts the flow chain + covers /energy/{id}. 69 Core +
47 Integration = 116 green. Live-verified: Haus 95,450 kWh → Auto 51,909 +
Other 43,541 (flow conserved), all 5 energy-type pages render.

Claude-Session: https://claude.ai/code/session_01Lz2RqAsnQhetqWNoCDfexK
2026-07-14 14:02:16 +02:00
..