Lodge the heat-network SAP code and Table 12 community fuel for PasHub community heating 🟥

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-14 22:30:28 +00:00
parent 6f1ba4be25
commit f9d8d33147
2 changed files with 52 additions and 0 deletions

View file

@ -122,6 +122,54 @@ class TestPhotovoltaicArrayMapping:
assert result.sap_energy_source.photovoltaic_arrays is None
class TestCommunityHeatingMapping:
"""A "Community heating system" dwelling must lodge the Table 4a
heat-network SAP code and the Table 12 community fuel with
`sap_main_heating_code=None`, `is_heat_network_main()` is False and the
calculator's whole heat-network branch (DLF, £120 standing charge, 80%
heat-source efficiency, Table 4c(3) charging) never fires; the dwelling is
priced as an ordinary mains-gas boiler (issue #1590 follow-up; fixture
507644414148 over-rates +14.3, 8.6 of it from these two fields).
"""
def test_community_boilers_lodge_heat_network_code_and_fuel(self) -> None:
# Arrange — the cohort's community lodgement (verbatim survey labels).
data = load("pashub_rdsap_site_notes_example1.json")
mh = data["heating_and_hot_water"]["main_heating"]
mh["system_type"] = "Community heating system"
mh["community_heat_source"] = "Community heating - boilers only"
mh["fuel"] = "Mains Gas"
mh["controls"] = (
"Charging system linked to use of community heating, room thermostat only"
)
mh["product_id"] = 0 # heat networks lodge no PCDB boiler
survey = from_dict(PasHubRdSapSiteNotes, data)
# Act
main = EpcPropertyDataMapper.from_site_notes(
survey
).sap_heating.main_heating_details[0]
# Assert — Table 4a code 301 (community boilers) routes
# is_heat_network_main; Table 12 code 51 (community boilers,
# mains gas) prices/factors the heat correctly.
assert main.sap_main_heating_code == 301
assert main.main_fuel_type == 51
def test_unknown_heat_source_strict_raises(self) -> None:
# Arrange
data = load("pashub_rdsap_site_notes_example1.json")
mh = data["heating_and_hot_water"]["main_heating"]
mh["system_type"] = "Community heating system"
mh["community_heat_source"] = "Some novel scheme"
mh["controls"] = ""
survey = from_dict(PasHubRdSapSiteNotes, data)
# Act / Assert
with pytest.raises(UnmappedPasHubLabel, match="community heat source"):
EpcPropertyDataMapper.from_site_notes(survey)
class TestRoomInRoofMapping:
"""A surveyed room-in-roof block (RdSAP §3.10 detailed measurement) must
reach `sap_building_parts[*].sap_room_in_roof` left None, ~32 of

View file

@ -202,6 +202,10 @@ class MainHeating:
weather_compensator: bool
emitter: str
emitter_temperature: str
# §Heating "Heating System (Other)" — the community heat-source label
# (e.g. "Community heating - boilers only") lodged only by heat-network
# dwellings; blank elsewhere.
community_heat_source: str = ""
@dataclass