Skip to content

feat: show grid_cost (net supplier balance) as headline, break out battery_cycle_cost separately #249

Description

@johanzander

Summary

Per @Frank-Leysen's comment on #126 (point 1, "grid_cost vs Today's Costs" — with point 4, "Meter tracking", as the supporting rationale), change how the dashboard presents daily cost so the headline figure matches what users see on their supplier meter.

Background

grid_cost and battery_cycle_cost are already computed and stored separately in the backend (core/bess/models.py:175-176):

grid_cost = import_eur - export_eur          # matches the supplier meter
battery_cycle_cost = ...                     # battery wear/degradation cost
# hourly_cost = grid_cost + battery_cycle_cost   (today's "Today's Costs")

Today the frontend only surfaces the combined hourly_cost as "Today's Costs" (SystemStatusCard.tsx:428, SavingsOverview.tsx), with Grid-Only Cost shown alongside it as the no-battery baseline. There's no separate display of grid_cost or battery_cycle_cost on their own.

Frank's point: on days with high solar throughput, bundling battery wear into "Today's Costs" makes a day that's clearly profitable on the meter (net import EUR − export EUR) look only marginally worthwhile — because wear is an investment/TCO cost, not a line on the electricity bill. He tracks a manual daily log of net supplier result (import EUR − export EUR) as the number he actually trusts (point 4), and wants the dashboard to surface that same number natively as grid_cost.

Requested change

  1. Show grid_cost as the headline figure, clearly labelled as net supplier balance / net grid cost (import EUR − export EUR — matches the physical meter).
  2. Keep "Grid-Only Cost" as-is — it remains the no-battery savings baseline.
  3. Break battery_cycle_cost out as its own, separate figure — not folded into the headline cost:
    • Continue using it in the optimizer at a realistic rate (~EUR 0.04/kWh) to discourage pointless cycling.
    • Optionally display it as something like "estimated wear today".
    • Add an on/off display toggle for it, decoupled from whether the optimizer uses it.
  4. Setting the cycle cost rate to 0 in settings should make the headline figure equal grid_cost exactly — useful for debugging/verification.

Non-goals / explicitly not requested

  • Not replacing "Today's Costs" with something that still silently bundles wear cost.
  • Not changing the Grid-Only Cost baseline or savings-% calculation.

Where this likely touches

  • core/bess/models.pygrid_cost / battery_cycle_cost already exist per-hour; check daily aggregation exposes both distinctly via the API.
  • backend/api_dataclasses.py, backend/api.py — confirm both fields are exposed on the daily summary endpoint(s).
  • frontend/src/components/SystemStatusCard.tsx, frontend/src/components/SavingsOverview.tsx, frontend/src/components/DetailedSavingsAnalysis.tsx — relabel headline metric, add cycle-cost display + toggle.
  • frontend/src/types.ts — type updates if new fields are threaded through.

cc @Frank-Leysen

Metadata

Metadata

Assignees

No one assigned

    Labels

    bot-analyzedTriage bot has processed this issueenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions