mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice 2 of Bill Derivation. BillDerivation(fuel_rates).derive(breakdown) takes a delivered-energy breakdown (per-section EnergyLine(section, fuel, kwh) + exported_kwh) and produces a Bill: per-section kWh + cost, standing charges, SEG credit, and total. - Each end-use line billed at its fuel's unit rate. - Standing charge added ONCE per distinct fuel used (a meter, not an end use); off-gas fuels carry 0 so contribute nothing — no metered/unmetered special case. - SEG export credit subtracted. - Deterministic (ADR-0006); raises UnpricedFuel (via FuelRates) on an unpriced fuel (e.g. heat network) rather than billing at a wrong default. Pure domain — no calculator dependency; the SapResult->EnergyBreakdown adapter is slice 3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
1.5 KiB
Python
58 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Mapping, Sequence
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
|
|
from domain.fuel_rates.fuel import Fuel
|
|
|
|
|
|
class BillSection(Enum):
|
|
"""A user-meaningful slice of the annual energy bill — the calculator's raw
|
|
end uses folded into the sections the UI shows (ADR-0014)."""
|
|
|
|
HEATING = "HEATING"
|
|
HOT_WATER = "HOT_WATER"
|
|
LIGHTING = "LIGHTING"
|
|
APPLIANCES = "APPLIANCES"
|
|
COOKING = "COOKING"
|
|
PUMPS_FANS = "PUMPS_FANS"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class EnergyLine:
|
|
"""One section's delivered energy on one fuel. A section may have more than
|
|
one line (e.g. gas main heating + electric secondary heating)."""
|
|
|
|
section: BillSection
|
|
fuel: Fuel
|
|
kwh: float
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class EnergyBreakdown:
|
|
"""A Property's delivered energy per end use, the input to Bill Derivation —
|
|
produced from SAP10 Calculation in a later slice. ``exported_kwh`` is PV
|
|
generation exported to the grid, credited at the SEG rate."""
|
|
|
|
lines: Sequence[EnergyLine]
|
|
exported_kwh: float = 0.0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class BillSectionCost:
|
|
"""One section's rolled-up delivered kWh and annual cost (£)."""
|
|
|
|
kwh: float
|
|
cost_gbp: float
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Bill:
|
|
"""A Property's annual energy bill, composed per section plus the per-meter
|
|
standing charges and the SEG export credit, and the total (ADR-0014)."""
|
|
|
|
sections: Mapping[BillSection, BillSectionCost]
|
|
standing_charges_gbp: float
|
|
seg_credit_gbp: float
|
|
total_gbp: float
|