From 7b04a9d5f4c185da9b9a7d7a1805376a90fc5f7c Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 15 Jul 2026 00:25:20 +0000 Subject: [PATCH] =?UTF-8?q?Int-code=20the=20surveyed=20secondary-heating?= =?UTF-8?q?=20label=20to=20its=20Table=204a=20room-heater=20code=20?= =?UTF-8?q?=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../epc/domain/tests/test_from_site_notes.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/datatypes/epc/domain/tests/test_from_site_notes.py b/datatypes/epc/domain/tests/test_from_site_notes.py index 2b89ab80d..de38e214a 100644 --- a/datatypes/epc/domain/tests/test_from_site_notes.py +++ b/datatypes/epc/domain/tests/test_from_site_notes.py @@ -726,6 +726,62 @@ class TestWallConstructionCoding: EpcPropertyDataMapper.from_site_notes(survey) +class TestSecondaryHeatingTypeCoding: + """`from_site_notes` must int-code the PAS Hub secondary-heating + `secondary_system` label to the SAP 10.2 Table 4a room-heater code, not + pass the raw string through. `_secondary_efficiency` does + `_int_or_none(secondary_heating_type)` — a string yields None and + silently falls back to code 693 (portable electric heater, eff 1.00), + so a gas open fire (code 605, eff 0.40) is billed as 100%-efficient + electric. 70/205 cohort properties lodge a secondary system; the 3 + gas/solid-fuel room heaters (e.g. deal 499607224524, +4.0 SAP) were + over-credited by the wrong fallback. + """ + + @pytest.mark.parametrize( + "label, expected_code", + [ + # Electric direct-acting (PCDB 691, eff 1.00) — the modal cohort + # heater; 691 == the old 693 fallback efficiency, so unchanged. + ("Panel, convector or radiant heaters", 691), + # Gas room heaters (PCDB Table 4a column A). + ( + "Flush fitting live fuel effect open front fire, " + "sealed to fireplace", + 605, + ), + ( + "1980 or later - Open front fire with open flue, " + "sealed to fireplace", + 603, + ), + # Solid fuel (PCDB 631, eff 0.32 col B). + ("Open fire in grate", 631), + ("No Secondary Heating", None), # no secondary heater lodged + ("", None), # no lodging + ], + ) + def test_label_maps_to_sap_code( + self, label: str, expected_code: Optional[int] + ) -> None: + data = load("pashub_rdsap_site_notes_example1.json") + data["heating_and_hot_water"]["secondary_heating"][ + "secondary_system" + ] = label + survey = from_dict(PasHubRdSapSiteNotes, data) + result = EpcPropertyDataMapper.from_site_notes(survey) + assert result.sap_heating.secondary_heating_type == expected_code + + def test_unknown_label_strict_raises(self) -> None: + data = load("pashub_rdsap_site_notes_example1.json") + data["heating_and_hot_water"]["secondary_heating"][ + "secondary_system" + ] = "Wood-burning stove with heat battery" + survey = from_dict(PasHubRdSapSiteNotes, data) + with pytest.raises(UnmappedPasHubLabel): + EpcPropertyDataMapper.from_site_notes(survey) + + class TestSecondaryFuelTypeCoding: """`from_site_notes` must int-code the PAS Hub secondary-heating `secondary_fuel` label to the SAP 10.2 Table 32 `secondary_fuel_type`