mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Pin end-to-end off-peak day/night bill regression 🟩
An Economy-7 storage dwelling now prices heating at the 0.20-day/0.80- night blend through cert -> calculator -> bill, instead of raising UnpricedFuel and aborting the modelling_e2e batch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
81d5429b60
commit
1da86a6366
1 changed files with 77 additions and 0 deletions
77
tests/domain/billing/test_off_peak_bill_integration.py
Normal file
77
tests/domain/billing/test_off_peak_bill_integration.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
"""End-to-end regression for the Off-Peak Meter day/night bill split (ADR-0014
|
||||
2026-06-24 amendment).
|
||||
|
||||
Drives a real off-peak (Economy-7) storage-heating cert through the whole chain
|
||||
— `cert_to_inputs` → `calculate_sap_from_inputs` → `EnergyBreakdown.from_sap_result`
|
||||
→ `BillDerivation.derive` against the committed Fuel Rates snapshot. Before the
|
||||
amendment this raised `UnpricedFuel` ("no rate for fuel ELECTRICITY_OFF_PEAK"),
|
||||
which aborted the `modelling_e2e` batch (e.g. property 717572). It must now price
|
||||
the dwelling day/night instead of crashing.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import replace
|
||||
|
||||
from domain.sap10_ml.tests._fixtures import (
|
||||
make_building_part,
|
||||
make_minimal_sap10_epc,
|
||||
make_sap_heating,
|
||||
)
|
||||
from datatypes.epc.domain.epc_property_data import EpcPropertyData, MainHeatingDetail
|
||||
from domain.sap10_calculator.calculator import calculate_sap_from_inputs
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import cert_to_inputs
|
||||
from domain.fuel_rates.fuel import Fuel
|
||||
from domain.billing.bill import BillSection, EnergyBreakdown
|
||||
from domain.billing.bill_derivation import BillDerivation
|
||||
from repositories.fuel_rates.fuel_rates_static_file_repository import (
|
||||
FuelRatesStaticFileRepository,
|
||||
)
|
||||
|
||||
_TYPICAL_TFA_M2 = 60.0
|
||||
|
||||
|
||||
def _off_peak_storage_epc() -> EpcPropertyData:
|
||||
# Integrated storage heaters (SAP code 408, Table 12a Grid 1 high-rate
|
||||
# fraction 0.20) on a Dual / Economy-7 (7-hour) meter.
|
||||
main = MainHeatingDetail(
|
||||
has_fghrs=False,
|
||||
main_fuel_type=29, # electricity
|
||||
heat_emitter_type=1,
|
||||
emitter_temperature=1,
|
||||
main_heating_control=2401,
|
||||
main_heating_category=7, # electric storage heaters
|
||||
sap_main_heating_code=408,
|
||||
)
|
||||
base = make_minimal_sap10_epc(
|
||||
total_floor_area_m2=_TYPICAL_TFA_M2,
|
||||
habitable_rooms_count=4,
|
||||
country_code="ENG",
|
||||
sap_building_parts=[make_building_part(construction_age_band="E")],
|
||||
sap_heating=make_sap_heating(main_heating_details=[main]),
|
||||
)
|
||||
return replace(
|
||||
base,
|
||||
sap_energy_source=replace(base.sap_energy_source, meter_type="1"),
|
||||
)
|
||||
|
||||
|
||||
def test_off_peak_storage_dwelling_bills_heating_day_night_not_crashes() -> None:
|
||||
# Arrange — score the off-peak cert and price it at the committed snapshot.
|
||||
result = calculate_sap_from_inputs(cert_to_inputs(_off_peak_storage_epc()))
|
||||
rates = FuelRatesStaticFileRepository().get_current()
|
||||
|
||||
# Act — the previously-crashing path: off-peak electricity reaches the bill.
|
||||
breakdown = EnergyBreakdown.from_sap_result(result)
|
||||
bill = BillDerivation(rates).derive(breakdown)
|
||||
|
||||
# Assert — heating bills on the off-peak carrier at the 0.20-day/0.80-night
|
||||
# blend (0.20×29.73 + 0.80×13.89 = 17.058 p/kWh), not a crash and not the
|
||||
# flat standard rate (24.67 p) or pure night rate (13.89 p).
|
||||
heating = bill.sections[BillSection.HEATING]
|
||||
assert heating.kwh > 0.0
|
||||
implied_rate_p = heating.cost_gbp / heating.kwh * 100.0
|
||||
assert abs(implied_rate_p - 17.058) <= 1e-6
|
||||
# The off-peak meter contributes one standing charge (56.99 p/day).
|
||||
assert any(line.fuel is Fuel.ELECTRICITY_OFF_PEAK for line in breakdown.lines)
|
||||
assert bill.total_gbp > 0.0
|
||||
Loading…
Add table
Reference in a new issue