mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge pull request #1307 from Hestia-Homes/feature/unmapped-ventilation-type-10
Map SAP ventilation_type codes 7/8/9/10 correctly in full-SAP schema path 🟩
This commit is contained in:
commit
8244d3f116
2 changed files with 32 additions and 6 deletions
|
|
@ -72,10 +72,9 @@ _SAP_KNOWN_WALL_TYPES: Final[frozenset[int]] = frozenset({1, 2, 3, 4, 5})
|
|||
# RdSAP age band M. Used only for that fallback + secondary age-band logic.
|
||||
_SAP_DEFAULT_AGE_BAND: Final[str] = "M"
|
||||
# full-SAP standard `ventilation_type` code → MechanicalVentilationKind name
|
||||
# (None = natural). MVHR (7) is deferred to natural — like the RdSAP API path
|
||||
# (_API_MECHANICAL_VENTILATION_TO_KIND code 4), its (24a) formula needs the
|
||||
# PCDB heat-recovery efficiency, not yet plumbed; mapping to MVHR with a null
|
||||
# efficiency would mis-model it as MV. None of the corpus lodges 7.
|
||||
# (None = natural). MVHR (code 8) uses the same PCDB Table 4g fallback
|
||||
# (66% × 0.70 in-use factor) as the RdSAP-21 API path when no PCDF index is
|
||||
# lodged — the cascade handles a null index gracefully.
|
||||
_SAP_VENTILATION_TYPE_TO_MV_KIND: Final[Dict[int, Optional[str]]] = {
|
||||
1: None, # natural (with intermittent extract fans)
|
||||
2: None, # passive stack — treated as natural
|
||||
|
|
@ -83,8 +82,10 @@ _SAP_VENTILATION_TYPE_TO_MV_KIND: Final[Dict[int, Optional[str]]] = {
|
|||
4: "EXTRACT_OR_PIV_OUTSIDE", # positive input from outside
|
||||
5: "EXTRACT_OR_PIV_OUTSIDE", # mechanical extract, centralised (MEV c)
|
||||
6: "EXTRACT_OR_PIV_OUTSIDE", # mechanical extract, decentralised (MEV dc)
|
||||
7: None, # MVHR — deferred (efficiency not plumbed)
|
||||
8: "MV", # balanced mechanical, no heat recovery
|
||||
7: "MV", # balanced without heat recovery (MV)
|
||||
8: "MVHR", # balanced with heat recovery (MVHR)
|
||||
9: None, # natural with extract fans and/or passive vents (legacy)
|
||||
10: None, # natural with extract fans and passive vents
|
||||
}
|
||||
# rdsap_uvalues WALL_CAVITY = 4 (D7 fallback; U comes from the description).
|
||||
_SAP_DEFAULT_WALL_CONSTRUCTION: Final[int] = 4
|
||||
|
|
|
|||
|
|
@ -410,6 +410,31 @@ class TestFromSapSchema17_1Ventilation:
|
|||
with pytest.raises(UnmappedApiCode):
|
||||
EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
|
||||
@pytest.mark.parametrize("code", [9, 10])
|
||||
def test_natural_ventilation_codes_9_and_10_map_to_none(self, code: int) -> None:
|
||||
data = load("sap_17_1.json")
|
||||
data["sap_ventilation"]["ventilation_type"] = code
|
||||
schema = from_dict(SapSchema17_1, data)
|
||||
result = EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
assert result.sap_ventilation is not None
|
||||
assert result.sap_ventilation.mechanical_ventilation_kind is None
|
||||
|
||||
def test_ventilation_type_7_is_mv(self) -> None:
|
||||
data = load("sap_17_1.json")
|
||||
data["sap_ventilation"]["ventilation_type"] = 7
|
||||
schema = from_dict(SapSchema17_1, data)
|
||||
result = EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
assert result.sap_ventilation is not None
|
||||
assert result.sap_ventilation.mechanical_ventilation_kind == "MV"
|
||||
|
||||
def test_ventilation_type_8_is_mvhr(self) -> None:
|
||||
data = load("sap_17_1.json")
|
||||
data["sap_ventilation"]["ventilation_type"] = 8
|
||||
schema = from_dict(SapSchema17_1, data)
|
||||
result = EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
assert result.sap_ventilation is not None
|
||||
assert result.sap_ventilation.mechanical_ventilation_kind == "MVHR"
|
||||
|
||||
|
||||
class TestFromSapSchema17_1Heating:
|
||||
"""Slice D6: full-SAP sap_heating (differing field names) maps onto the
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue