From 21afbefa9dbe3c597a8ec5559705f795c049092e Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:05:00 +0000 Subject: [PATCH] =?UTF-8?q?Resolve=20a=20landlord=20gas-combi=20heating=20?= =?UTF-8?q?override=20to=20its=20SAP=20code=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../main_heating_system_overlay.py | 28 +++++++++++++++++++ .../epc/test_main_heating_system_overlay.py | 21 ++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 domain/epc/property_overlays/main_heating_system_overlay.py create mode 100644 tests/domain/epc/test_main_heating_system_overlay.py diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py new file mode 100644 index 000000000..6b7aca804 --- /dev/null +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -0,0 +1,28 @@ +"""Map a Landlord-Override main-heating-system value to a heating Simulation Overlay. + +A main-heating-system value is one canonical system archetype ("Gas boiler, +combi", "Electric storage heaters, fan"). The calculator reads the primary +system's `sap_main_heating_code` (SAP Table 4a/4b), so the overlay maps the +archetype to a representative code and emits a whole-dwelling `HeatingOverlay` +targeting `main_heating_details[0]` (`building_part` is ignored). It composes +field-wise with the main_fuel / water_heating overlays. + +The SEDBUK A-G efficiency band the Hyde "Heating" column carries is NOT honoured +yet (no efficiency slot on the overlay/MainHeatingDetail) -- archetypes map to +their modern/condensing Table 4b code, so an old low-rated boiler is currently +modelled at the condensing efficiency. Heat pumps and community heating (which +resolve via main_heating_index_number / community codes, not a Table 4b code) +are left UNKNOWN until modelled. Unresolvable values produce no overlay. +""" + +from __future__ import annotations + +from typing import Optional + +from domain.modelling.simulation import EpcSimulation + + +def main_heating_overlay_for( + main_heating_value: str, building_part: int +) -> Optional[EpcSimulation]: + raise NotImplementedError diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py new file mode 100644 index 000000000..e1b7a90d6 --- /dev/null +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -0,0 +1,21 @@ +"""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 + +from domain.epc.property_overlays.main_heating_system_overlay import ( + main_heating_overlay_for, +) + + +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