Merge pull request #1587 from Hestia-Homes/worktree-issue-1566-roof-construction-country

Set roof_construction_type and country_code on the PasHub site-notes path
This commit is contained in:
KhalimCK 2026-07-14 18:51:10 +01:00 committed by GitHub
commit 8eb2649b9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 69 additions and 0 deletions

View file

@ -343,6 +343,13 @@ class EpcPropertyDataMapper:
inspection_date=general.inspection_date,
tenure=general.tenure,
transaction_type=general.transaction_type,
# PAS Hub site notes don't lodge a country field, but the
# cascade reads `country_code` to pick the England (vs Welsh /
# Scottish / NI) U-value tables. Set 'ENG' explicitly, matching
# the Elmhurst path (`from_elmhurst_site_notes`) and this
# cohort's postcodes; a general fix should read the surveyed
# country once PAS Hub lodges one.
country_code="ENG",
roofs=[],
walls=[],
floors=[],
@ -5985,6 +5992,7 @@ def _map_main_building_part(
),
sap_floor_dimensions=_map_floor_dimensions(measurements.main_building.floors),
wall_thickness_mm=main.wall_thickness_mm,
roof_construction_type=roof.construction_type or None,
roof_insulation_location=roof_location,
roof_insulation_thickness=roof_thickness,
floor_type=floor.floor_type,
@ -6015,6 +6023,9 @@ def _map_extension_building_part(
),
sap_floor_dimensions=_map_floor_dimensions(ext_m.floors),
wall_thickness_mm=ext_c.wall_thickness_mm,
roof_construction_type=(
roof.construction_type or None if roof is not None else None
),
roof_insulation_location=roof_location,
roof_insulation_thickness=roof_thickness,
)

View file

@ -34,6 +34,62 @@ def load(filename: str) -> Dict[str, Any]:
return json.load(f) # type: ignore[no-any-return]
class TestRoofConstructionTypeCoding:
"""`from_site_notes` must set `roof_construction_type` from the surveyed
`roof_space.*.construction_type` label, not leave it `None`. The
calculator's `heat_transmission` reads this field for its "flat" /
"sloping ceiling" substring routing (flat-roof U path vs the pitched-
roof cos(30°) inclined-surface factor); leaving it `None` silently
routes every roof flat or pitched through the pitched default
(Guinness cohort, issue #1566).
"""
@pytest.mark.parametrize(
"label, expected",
[
("Pitched roof (Slates or tiles), Access to loft", "Pitched roof (Slates or tiles), Access to loft"),
("Flat", "Flat"), # routes to the flat-roof U path (heat_transmission "flat" substring)
("", None), # no lodging
],
)
def test_main_building_label_passes_through(
self, label: str, expected: Optional[str]
) -> None:
data = load("pashub_rdsap_site_notes_example1.json")
data["roof_space"]["main_building"]["construction_type"] = label
survey = from_dict(PasHubRdSapSiteNotes, data)
result = EpcPropertyDataMapper.from_site_notes(survey)
assert result.sap_building_parts[0].roof_construction_type == expected
def test_extension_label_passes_through(self) -> None:
data = load("pashub_rdsap_site_notes_example2.json")
data["roof_space"]["extensions"][0]["construction_type"] = "Flat"
survey = from_dict(PasHubRdSapSiteNotes, data)
result = EpcPropertyDataMapper.from_site_notes(survey)
extension_part = next(
bp
for bp in result.sap_building_parts
if bp.identifier != BuildingPartIdentifier.MAIN
)
assert extension_part.roof_construction_type == "Flat"
class TestCountryCode:
"""`from_site_notes` must set `country_code` so the cascade's England /
Wales / Scotland / NI U-value tables (`u_floor`, `u_basement_floor`,
`u_door`) resolve correctly. PAS Hub site notes don't lodge a country
field; default to 'ENG' for this all-English cohort (Guinness cohort,
issue #1566), matching the Elmhurst site-notes path.
"""
def test_country_code_is_england(self) -> None:
survey = from_dict(
PasHubRdSapSiteNotes, load("pashub_rdsap_site_notes_example1.json")
)
result = EpcPropertyDataMapper.from_site_notes(survey)
assert result.country_code == "ENG"
class TestPartyWallConstructionCoding:
"""`from_site_notes` must int-code the PAS Hub `party_wall_construction_type`
label to the SAP10 code `u_party_wall` consumes (RdSAP 10 Table 15), not copy
@ -672,6 +728,7 @@ class TestFromSiteNotesExample1:
status=None,
tenure="Rented Social",
transaction_type="None of the Above",
country_code="ENG",
# Elements (not available from site notes)
roofs=[],
walls=[],
@ -801,6 +858,7 @@ class TestFromSiteNotesExample1:
),
],
wall_thickness_mm=280,
roof_construction_type="Pitched roof (Slates or tiles), Access to loft",
roof_insulation_location="Joists",
roof_insulation_thickness=100,
floor_type="Ground Floor",