mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Slice 8 of ADR-0025 costing. _existing_system keys on the heating fuel code, not the mains_gas flag -- the 001431 electric fixtures all lodge mains_gas=True (gas available at the property) while heating electrically (fuel 30), which the flag-based check misread as gas (and would have wrongly reused a non-existent wet system). Electric/gas/oil/LPG map to their categories; empty details -> NONE; unrecognised -> OTHER (gas-line fallback). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
84 lines
3.6 KiB
Python
84 lines
3.6 KiB
Python
"""The dwelling interpretation that feeds `Products.ashp_bundle_cost` — reading
|
|
an `EpcPropertyData` into a typed `AshpCostInputs` (ADR-0025). This is the
|
|
modelling-layer half of the split: it derives the existing system, property
|
|
size band, design heat loss (floor-area proxy), radiator count, and whether a
|
|
wet system can be reused — the catalogue math (Products) stays EPC-free.
|
|
"""
|
|
|
|
import copy
|
|
|
|
from datatypes.epc.domain.epc_property_data import EpcPropertyData
|
|
from domain.modelling.generators.heating_recommendation import ashp_cost_inputs
|
|
from domain.modelling.products import AshpCostInputs, AshpExistingSystem
|
|
from tests.domain.modelling._elmhurst_recommendation import (
|
|
parse_recommendation_summary,
|
|
)
|
|
|
|
|
|
def test_mains_gas_dwelling_maps_to_a_reusable_wet_gas_system() -> None:
|
|
# Arrange — a mains-gas regular boiler with radiators (90 m2, 7 habitable
|
|
# rooms): an existing wet system the ASHP can reuse.
|
|
epc = parse_recommendation_summary(
|
|
"ashp_from_system_boiler_with_cylinder_001431_before.pdf"
|
|
)
|
|
|
|
# Act
|
|
inputs: AshpCostInputs = ashp_cost_inputs(epc)
|
|
|
|
# Assert — gas, large (90 > 75 m2), 4.5 kW (90 x 0.05), 10 radiators
|
|
# (7 habitable + 3), reusable wet system.
|
|
assert inputs.existing_system is AshpExistingSystem.GAS
|
|
assert inputs.is_small_property is False
|
|
assert abs(inputs.design_heat_loss_kw - 4.5) <= 1e-9
|
|
assert inputs.radiator_count == 10
|
|
assert inputs.has_reusable_wet_system is True
|
|
|
|
|
|
def test_electric_dwelling_has_no_reusable_wet_system() -> None:
|
|
# Arrange — an electric storage-heater dwelling (no wet system).
|
|
epc = parse_recommendation_summary(
|
|
"hhr_storage_from_electric_storage_001431_before.pdf"
|
|
)
|
|
|
|
# Act
|
|
inputs: AshpCostInputs = ashp_cost_inputs(epc)
|
|
|
|
# Assert — electric, so a full new wet distribution is needed.
|
|
assert inputs.existing_system is AshpExistingSystem.ELECTRIC_STORAGE
|
|
assert inputs.has_reusable_wet_system is False
|
|
|
|
|
|
def test_classification_keys_on_fuel_not_the_mains_gas_flag() -> None:
|
|
# Arrange — the 001431 electric fixtures all lodge mains_gas=True (gas is
|
|
# available at the property) while heating electrically (fuel 30). The
|
|
# classifier must key on the fuel, not the flag, or it would misread these
|
|
# as gas and wrongly reuse a non-existent wet system.
|
|
epc = parse_recommendation_summary(
|
|
"hhr_storage_from_electric_storage_001431_before.pdf"
|
|
)
|
|
|
|
# Act / Assert
|
|
assert epc.sap_energy_source.mains_gas is True
|
|
inputs: AshpCostInputs = ashp_cost_inputs(epc)
|
|
assert inputs.existing_system is AshpExistingSystem.ELECTRIC_STORAGE
|
|
assert inputs.has_reusable_wet_system is False
|
|
|
|
|
|
def test_oil_and_lpg_dwellings_are_reusable_wet_systems() -> None:
|
|
# Arrange — no oil/LPG fixture exists, so mutate an off-gas dwelling's main
|
|
# fuel to oil (28) and LPG (27); both are wet boiler systems.
|
|
base: EpcPropertyData = parse_recommendation_summary(
|
|
"hhr_storage_from_electric_storage_001431_before.pdf"
|
|
)
|
|
|
|
def _with_fuel(code: int) -> EpcPropertyData:
|
|
clone: EpcPropertyData = copy.deepcopy(base)
|
|
clone.sap_energy_source.mains_gas = False
|
|
clone.sap_heating.main_heating_details[0].main_fuel_type = code
|
|
clone.sap_heating.main_heating_details[0].sap_main_heating_code = 199
|
|
return clone
|
|
|
|
# Act / Assert
|
|
assert ashp_cost_inputs(_with_fuel(28)).existing_system is AshpExistingSystem.OIL
|
|
assert ashp_cost_inputs(_with_fuel(27)).existing_system is AshpExistingSystem.LPG
|
|
assert ashp_cost_inputs(_with_fuel(28)).has_reusable_wet_system is True
|