fix(energy): report real kWh in the cost Summary instead of mislabelled money
The Summary cards labelled `metered_import` / `metered_export` as "(kWh)", but both fields are monetary totals (Σ import_cost / Σ export_revenue). Today's page therefore showed "Import 1.339 kWh" when the meter had actually imported 4.188 kWh — the 1.339 was EUR. Cross-checked against the DSMR cumulative registers and Home Assistant: our energy figures were correct all along, only the label was wrong. summarize() now also aggregates the metered energy, reusing the already-fetched non-degraded rows so no extra query is issued: metered_import_kwh = Σ (d1_kwh + d2_kwh) metered_export_kwh = Σ (r1_kwh + r2_kwh) The Import/Export cards show kWh as the headline figure and keep the monetary equivalent as a sub-line, so the split between energy cost and standing charges/credits behind total_payable stays visible. The `_kwh` suffix is now the only thing separating energy from money in this payload, so the docstrings on both summarize() and SummaryResponse call that out explicitly. app/integrations/expose.py reads only the money keys, so the HA outbound sensors are unaffected by the additive fields.
This commit is contained in:
@@ -990,6 +990,38 @@ class TestSummarize:
|
||||
# Σnet ≈ 2 × 0.4051 = 0.8102
|
||||
assert abs(result["metered_net"] - 0.8102) < 1e-6
|
||||
|
||||
def test_metered_kwh_sums(self, energy_db: Session) -> None:
|
||||
"""The *_kwh totals sum both tariff registers and are distinct from the money totals."""
|
||||
self._setup_two_periods(energy_db)
|
||||
result = summarize(energy_db, _ts(10, 0), _ts(10, 30))
|
||||
|
||||
# Per period: d1=0.5, d2=1.2 → import 1.7 kWh; r1=0.0, r2=0.1 → export 0.1 kWh.
|
||||
assert abs(result["metered_import_kwh"] - 3.4) < 1e-6, (
|
||||
f"expected Σ(d1+d2) = 2 × 1.7 = 3.4 kWh, got {result['metered_import_kwh']}"
|
||||
)
|
||||
assert abs(result["metered_export_kwh"] - 0.2) < 1e-6, (
|
||||
f"expected Σ(r1+r2) = 2 × 0.1 = 0.2 kWh, got {result['metered_export_kwh']}"
|
||||
)
|
||||
# Regression guard for the mislabelled-unit bug: energy and money totals
|
||||
# must never be conflated (import 3.4 kWh vs 0.8202 EUR of import cost).
|
||||
assert result["metered_import_kwh"] != result["metered_import"]
|
||||
assert result["metered_export_kwh"] != result["metered_export"]
|
||||
|
||||
def test_metered_kwh_excludes_degraded_periods(self, energy_db: Session) -> None:
|
||||
"""Degraded periods contribute no kWh, mirroring the money totals."""
|
||||
self._setup_two_periods(energy_db)
|
||||
# Degrade the first period; its kWh must drop out of the totals.
|
||||
row = energy_db.execute(
|
||||
select(EnergyCostPeriod).where(EnergyCostPeriod.period_start == _T0)
|
||||
).scalar_one()
|
||||
row.degraded = True
|
||||
energy_db.commit()
|
||||
|
||||
result = summarize(energy_db, _ts(10, 0), _ts(10, 30))
|
||||
assert result["degraded_count"] == 1
|
||||
assert abs(result["metered_import_kwh"] - 1.7) < 1e-6
|
||||
assert abs(result["metered_export_kwh"] - 0.1) < 1e-6
|
||||
|
||||
def test_period_count(self, energy_db: Session) -> None:
|
||||
self._setup_two_periods(energy_db)
|
||||
result = summarize(energy_db, _ts(10, 0), _ts(10, 30))
|
||||
@@ -2708,6 +2740,7 @@ class TestSummarizeSettlementOffset:
|
||||
|
||||
expected_keys = {
|
||||
"currency", "metered_import", "metered_export", "metered_net",
|
||||
"metered_import_kwh", "metered_export_kwh",
|
||||
"fixed_costs", "credits", "total_payable", "period_count",
|
||||
"degraded_count", "days",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user