mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
140 lines
4.5 KiB
Python
140 lines
4.5 KiB
Python
"""The Landlord-Override main-heating-system → heating Simulation Overlay mapping.
|
|
|
|
A main-heating-system value resolves to the SAP `sap_main_heating_code` the
|
|
calculator reads from the primary system; the overlay is whole-dwelling.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType
|
|
from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for
|
|
from domain.epc.property_overlays.main_heating_system_overlay import (
|
|
main_heating_overlay_for,
|
|
)
|
|
from domain.epc.property_overlays.water_heating_overlay import (
|
|
water_heating_overlay_for,
|
|
)
|
|
from domain.modelling.scoring.overlay_applicator import apply_simulations
|
|
from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import (
|
|
build_epc,
|
|
)
|
|
|
|
|
|
def test_gas_combi_overlays_the_primary_heating_code() -> None:
|
|
# Act
|
|
simulation = main_heating_overlay_for("Gas boiler, combi", 0)
|
|
|
|
# Assert — condensing combi is SAP Table 4b code 104.
|
|
assert simulation is not None
|
|
assert simulation.heating is not None
|
|
assert simulation.heating.sap_main_heating_code == 104
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("main_heating_value", "code"),
|
|
[
|
|
("Gas boiler, regular", 102),
|
|
("Gas CPSU", 120),
|
|
("Electric storage heaters, fan", 404),
|
|
("Direct-acting electric", 191),
|
|
],
|
|
)
|
|
def test_heating_archetypes_decode_to_their_sap_codes(
|
|
main_heating_value: str, code: int
|
|
) -> None:
|
|
# Act
|
|
simulation = main_heating_overlay_for(main_heating_value, 0)
|
|
|
|
# Assert
|
|
assert simulation is not None
|
|
assert simulation.heating is not None
|
|
assert simulation.heating.sap_main_heating_code == code
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("main_heating_value", "code"),
|
|
[
|
|
("Electric storage heaters, old", 401),
|
|
("Electric storage heaters, slimline", 402),
|
|
("Electric storage heaters, convector", 403),
|
|
],
|
|
)
|
|
def test_storage_heater_subtypes_decode_to_their_codes(
|
|
main_heating_value: str, code: int
|
|
) -> None:
|
|
# Act
|
|
simulation = main_heating_overlay_for(main_heating_value, 0)
|
|
|
|
# Assert
|
|
assert simulation is not None
|
|
assert simulation.heating is not None
|
|
assert simulation.heating.sap_main_heating_code == code
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"main_heating_value",
|
|
["Unknown", "", "Air source heat pump", "Community heating"],
|
|
)
|
|
def test_unresolvable_or_unmodelled_heating_produces_no_overlay(
|
|
main_heating_value: str,
|
|
) -> None:
|
|
# Heat pumps (main_heating_index_number) and community heating (community
|
|
# codes) don't map to a Table 4b sap_main_heating_code yet — no overlay.
|
|
|
|
# Act
|
|
simulation = main_heating_overlay_for(main_heating_value, 0)
|
|
|
|
# Assert
|
|
assert simulation is None
|
|
|
|
|
|
def test_main_heating_override_remaps_the_primary_system_code() -> None:
|
|
# Arrange
|
|
baseline = build_epc()
|
|
overlay = main_heating_overlay_for("Gas boiler, regular", 0)
|
|
assert overlay is not None
|
|
|
|
# Act
|
|
result = apply_simulations(baseline, [overlay])
|
|
|
|
# Assert — the calculator reads the code off main_heating_details[0].
|
|
assert result.sap_heating.main_heating_details[0].sap_main_heating_code == 102
|
|
|
|
|
|
def test_the_three_heating_overrides_compose_without_conflict() -> None:
|
|
# Arrange — main_fuel, water_heating and main_heating_system all fold onto one
|
|
# HeatingOverlay surface but set DISJOINT fields, so they compose (the
|
|
# field-disjoint design that makes precedence moot for these three).
|
|
baseline = build_epc()
|
|
overlays = [
|
|
fuel_overlay_for("electricity", 0),
|
|
water_heating_overlay_for("Electric immersion, electricity", 0),
|
|
main_heating_overlay_for("Electric storage heaters, fan", 0),
|
|
]
|
|
assert all(o is not None for o in overlays)
|
|
|
|
# Act
|
|
result = apply_simulations(baseline, [o for o in overlays if o is not None])
|
|
|
|
# Assert — each override landed on its own field.
|
|
main = result.sap_heating.main_heating_details[0]
|
|
assert main.main_fuel_type == 29
|
|
assert main.sap_main_heating_code == 404
|
|
assert result.sap_heating.water_heating_code == 903
|
|
assert result.sap_heating.water_heating_fuel == 29
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"member",
|
|
[m for m in MainHeatingSystemType if m is not MainHeatingSystemType.UNKNOWN],
|
|
)
|
|
def test_every_resolvable_main_heating_value_decodes(
|
|
member: MainHeatingSystemType,
|
|
) -> None:
|
|
# Act
|
|
simulation = main_heating_overlay_for(member.value, 0)
|
|
|
|
# Assert
|
|
assert simulation is not None
|