Files
MeterVault/src/Infrastructure/Dashboard/ConsumableModels.cs
T
schmidt.florian 1282acf82c SDD §8 panels (PV/oil/meter-detail) + fix reference-data-in-Docker
Complete the SDD §8 dashboard views that were deferred at the M5 boundary,
and fix a shipping bug that left the Docker demo empty.

Bug: "Load reference data" created meters/tank/tariffs but imported zero
readings in Docker. Root cause: sampledata/ was excluded by .dockerignore and
never copied into the build stage, so the App csproj's linked Content glob
resolved to nothing at publish time; ReferenceDataImporter then silently
skipped the missing CSVs after already writing its marker meter, leaving the
DB permanently "loaded" but empty.
  - .dockerignore: stop excluding sampledata/
  - Dockerfile: COPY sampledata/ into the build stage
  - ReferenceDataImporter: fail-fast (validate CSVs exist before the marker
    meter) and throw instead of silently skipping a missing file
  - Program.cs + MeterVaultOptions: opt-in MeterVault__SeedReferenceData
    (compose METERVAULT_SEED=true) for a one-command populated demo

New SDD §8 panels (read models in Infrastructure/Dashboard, Blazor pages):
  - §8.4 Solar/PV (/solar): generation from GenerationCounter meters;
    self-consumption / autarky % / self-consumption % / savings derived from
    meters tagged total_load & grid_import via Meter.Meta role config
    (MeterRoles/MeterMeta) — nothing hardcoded by name.
  - §8.5 Oil/consumable (/consumables): tank level (cm→L calibrated), fill
    gauge, deliveries log, burner runtime, effective L/h (fixed/empirical),
    forecast-to-empty, tariff cost, monthly series.
  - §8.6 Meter detail (/meters/{id}): raw readings, normalized consumption,
    source status, tariff timeline, events, measured-vs-estimated markers.
  - Reusable SeriesChart component; nav links; Meters list rows link to detail.

Tests: MeterMetaTests (Core, +10); DashboardRenderTests extended to assert the
three panel services compute real figures and the new routes render (108 total,
all green). Live-verified in Docker: seed imports 302 readings / 347 consumption
rows; panels render (generation 16,481 kWh, oil 3,967 L) cross-checking the DB.

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

36 lines
1.2 KiB
C#

using MeterVault.Core.Domain;
namespace MeterVault.Infrastructure.Dashboard;
/// <summary>One recorded delivery into a consumable store.</summary>
public sealed record DeliveryRow(DateTimeOffset Time, double Amount, string? Unit);
/// <summary>One month of consumable draw.</summary>
public sealed record ConsumableMonth(DateOnly Period, double Consumption);
/// <summary>
/// The oil / consumable panel read model (SDD §8.5) for one <see cref="MeterMode.ConsumableBalance"/>
/// meter: current tank level (physical + volume), fill vs capacity, deliveries, associated burner
/// runtime, effective L/h (fixed or empirical), forecast-to-empty, tariff cost and a monthly series.
/// </summary>
public sealed record ConsumableSummary(
int MeterId,
string Name,
string Unit,
double Capacity,
double? CurrentLevel,
double? PhysicalLevel,
string? PhysicalUnit,
DateTimeOffset? LevelAsOf,
double FillFraction,
double ConsumptionInRange,
double? BurnerHours,
double? EffectiveRate,
double? FixedRate,
TankRateMode RateMode,
double? AveragePerDay,
DateOnly? ForecastEmpty,
double CostInRange,
IReadOnlyList<DeliveryRow> Deliveries,
IReadOnlyList<ConsumableMonth> Months);