diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index acf3c615d..4159bf658 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -9776,6 +9776,10 @@ _ELMHURST_MV_TYPE_TO_KIND: Dict[str, str] = { # picking which (25)m formula to apply. "Mechanical extract, decentralised (MEV dc)": "EXTRACT_OR_PIV_OUTSIDE", "Mechanical ventilation with heat recovery (MVHR)": "MVHR", + # PIV from the loft is treated as natural ventilation → (24d)m (per the + # MechanicalVentilationKind.NATURAL contract); only PIV from OUTSIDE is + # whole-house extract → EXTRACT_OR_PIV_OUTSIDE / (24c)m. + "Positive input from loft": "NATURAL", } diff --git a/tests/datatypes/epc/domain/test_mapper_ventilation_piv_loft.py b/tests/datatypes/epc/domain/test_mapper_ventilation_piv_loft.py new file mode 100644 index 000000000..60dc529e7 --- /dev/null +++ b/tests/datatypes/epc/domain/test_mapper_ventilation_piv_loft.py @@ -0,0 +1,24 @@ +"""Mapper boundary: the Elmhurst §12.1 "Positive input from loft" mechanical- +ventilation label. + +SAP 10.2 §2 (24d) treats positive input ventilation sourced from the LOFT as +natural ventilation — unlike PIV from OUTSIDE, which is whole-house extract and +resolves to EXTRACT_OR_PIV_OUTSIDE / (24c). The MechanicalVentilationKind.NATURAL +docstring states the loft case explicitly. Before this mapping existed the label +raised UnmappedElmhurstLabel, blocking the whole Summary (surfaced across 8 WCHG +Elmhurst certs). +""" + +from datatypes.epc.domain.mapper import ( + _elmhurst_mv_kind, # pyright: ignore[reportPrivateUsage] +) + + +def test_positive_input_from_loft_maps_to_natural() -> None: + # Arrange — the Elmhurst §12.1 PIV-from-loft ventilation label. + + # Act + kind = _elmhurst_mv_kind("Positive input from loft") + + # Assert — SAP 10.2 §2 (24d): loft-sourced PIV is treated as natural vent. + assert kind == "NATURAL"