From a63276387ef7653119620bf1533fa426e9e57471 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 26 Jun 2026 09:55:08 +0000 Subject: [PATCH] =?UTF-8?q?Construct=20sap=5Fventilation=20in=20from=5Frds?= =?UTF-8?q?ap=5Fschema=5F19=5F0=20/=2021=5F0=5F0=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both passed no sap_ventilation= → EpcPropertyData default None, dropping the whole §2 block so MEV/MVHR certs scored as natural. Mirror 21.0.1's block for the only fields each schema lodges: mechanical_ventilation_kind (§2 MV-kind dispatch) + sheltered_sides (§S5, from built_form). Neither schema lodges the fan/flue/vent counts (RdSAP Table-5 age defaults), so those stay unset. Co-Authored-By: Claude Opus 4.8 (1M context) --- datatypes/epc/domain/mapper.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index 8f55db80..efacc71b 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -1698,6 +1698,19 @@ class EpcPropertyDataMapper: if getattr(bp, "glazed_perimeter", None) is None ], sap_conservatory=_api_sap_conservatory(schema.sap_building_parts), + # ADR-0037 follow-up: 19.0 previously passed no `sap_ventilation=`, + # dropping the whole §2 block. The schema only lodges the top-level + # `mechanical_ventilation` enum + `built_form` (no fan/flue/vent + # counts — RdSAP uses Table-5 age defaults), so mirror just those + # two fields from 21.0.1. An MEV/MVHR cert that defaulted to NATURAL + # under-stated its ventilation heat loss; `sheltered_sides` (§S5) + # avoids the cascade's shelter default of 2. + sap_ventilation=SapVentilation( + sheltered_sides=_api_sheltered_sides(schema.built_form), + mechanical_ventilation_kind=_api_mechanical_ventilation_kind( + schema.mechanical_ventilation + ), + ), ) @staticmethod @@ -2274,6 +2287,19 @@ class EpcPropertyDataMapper: else None ), ), + # ADR-0037 follow-up: 21.0.0 previously passed no `sap_ventilation=`, + # dropping the whole §2 block. Unlike 21.0.1 it does not lodge the + # fan/flue/vent counts, so mirror only the two fields it does carry: + # the top-level `mechanical_ventilation` enum (→ §2 MV-kind dispatch; + # an MEV/MVHR cert otherwise defaulted to NATURAL and under-stated + # ventilation heat loss) and `sheltered_sides` from built_form (§S5, + # vs the cascade's shelter default of 2). + sap_ventilation=SapVentilation( + sheltered_sides=_api_sheltered_sides(schema.built_form), + mechanical_ventilation_kind=_api_mechanical_ventilation_kind( + schema.mechanical_ventilation + ), + ), ) @staticmethod