mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice 1 of Bill Derivation — the reference-data foundation that later slices price the calculator's per-end-use kWh against: - Fuel enum (canonical billing fuels; the join key between the calculator's SAP-code fuels and the rates snapshot). COAL + HEAT_NETWORK are members with no national rate. - FuelRates value object: unit_rate_p_per_kwh / standing_charge_p_per_day / seg_export_p_per_kwh; raises UnpricedFuel on a fuel it has no rate for rather than billing at a wrong default. - FuelRatesRepository port (ADR-0011 Repo-reads-stored-reference-data) + StaticFileFuelRatesRepository reading a committed JSON snapshot. - Snapshot fuel_rates_2026_q2.json: GB national, Apr-Jun 2026 Ofgem cap (gas/electricity) + DESNZ/NEP May 2026 (off-gas). Carries the full researched data; the value object exposes single-rate fuels this slice. Off-peak (day/night), house coal and heat network raise UnpricedFuel until later slices. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from enum import Enum
|
|
|
|
|
|
class Fuel(Enum):
|
|
"""A canonical billing fuel — the join key between the calculator's
|
|
per-end-use fuel (mapped from SAP fuel codes) and the Fuel Rates snapshot
|
|
(ADR-0014). Member names match the snapshot's keys.
|
|
|
|
``COAL`` (traditional house coal) and ``HEAT_NETWORK`` are carried as
|
|
members so a cert lodging them maps to a Fuel, but they have no national
|
|
rate — pricing them raises ``UnpricedFuel`` (house coal's domestic sale is
|
|
illegal in England; heat networks are scheme-specific).
|
|
"""
|
|
|
|
MAINS_GAS = "MAINS_GAS"
|
|
ELECTRICITY = "ELECTRICITY"
|
|
ELECTRICITY_OFF_PEAK = "ELECTRICITY_OFF_PEAK"
|
|
OIL = "OIL"
|
|
LPG = "LPG"
|
|
COAL = "COAL"
|
|
SMOKELESS = "SMOKELESS"
|
|
WOOD_LOGS = "WOOD_LOGS"
|
|
WOOD_PELLETS = "WOOD_PELLETS"
|
|
HEAT_NETWORK = "HEAT_NETWORK"
|
|
|
|
|
|
class UnpricedFuel(ValueError):
|
|
"""Bill Derivation was asked for a rate on a fuel the current Fuel Rates
|
|
snapshot does not price (ADR-0014).
|
|
|
|
Raised rather than billing at a wrong default so the gap surfaces
|
|
immediately — house coal and heat networks have no national rate, and
|
|
off-peak electricity needs the day/night split that a later slice adds.
|
|
"""
|
|
|
|
def __init__(self, fuel: Fuel) -> None:
|
|
super().__init__(
|
|
f"no rate for fuel {fuel.name} in the current Fuel Rates snapshot; "
|
|
f"add it to the snapshot or map this end use to a priced fuel"
|
|
)
|
|
self.fuel = fuel
|