From 4bc042f56a4c36c2e7970c0e28c80bc4b7ef8211 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Tue, 14 Jul 2026 16:25:02 +0000 Subject: [PATCH] Correct overclaim: rating 0 means N/A, not confirmed party wall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer pushback: the gov EPC code table (epc_codes.csv) defines energy_efficiency_rating 0 generically as "N/A", not specifically "party wall". The payload carries no other identifying field, so the actual cause can't be determined from the data alone. The fix itself is unaffected (still calc-neutral regardless of cause) — just correcting comments/test naming to not assert an unconfirmed fact. Co-Authored-By: Claude Sonnet 5 --- datatypes/epc/domain/mapper.py | 24 +++++++++++-------- .../domain/tests/test_from_sap_schema_15_0.py | 18 +++++++------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index a39776640..a5511a62e 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -3916,16 +3916,20 @@ def _normalize_sap_schema_16_x(data: Dict[str, Any]) -> Dict[str, Any]: # Every "Top-floor flat" SAP-Schema-15.0 cert we've seen (confirmed on 21 # real certs from task 9d271e98-96e6-4be6-bb50-e9be6f954003, portfolio # 796 — e.g. cert 8204-4998-7729-4026-5693, UPRN 100061740136) lodges a - # second `walls[]` entry that is a bare zero-rated party-wall boundary - # element — `{"energy_efficiency_rating": 0, - # "environmental_efficiency_rating": 0}`, no `description` key at all — - # unlike the sibling `floors`/`roofs` "(other premises above/below)" - # sentinel convention, which DOES carry text. RdSapSchema17_1 requires - # `description`. Default it to "" rather than fabricate construction - # text: `_joined_descriptions` (heat_transmission.py) already filters out - # falsy descriptions, so a rating-0/no-description element contributes - # nothing to the wall U-value derivation either way — this default is - # calc-neutral, purely unblocking the parse. + # second `walls[]` entry with both ratings 0 and no `description` key at + # all — `{"energy_efficiency_rating": 0, + # "environmental_efficiency_rating": 0}`. Per the gov EPC code table + # (epc_codes.csv: energy_efficiency_rating 0 == "N/A"), rating 0 just + # means "not applicable" generically — the payload carries no other + # field (no wall type/construction code), so we cannot tell from the + # data alone *why* it's N/A (a party wall to a neighbour is a plausible + # cause on a top-floor flat, but unconfirmed). Whatever the cause, + # RdSapSchema17_1 requires `description`, so default it to "" rather + # than fabricate construction text: `_joined_descriptions` + # (heat_transmission.py) already filters out falsy descriptions, so an + # N/A-rated element with no description contributes nothing to the wall + # U-value derivation either way — this default is calc-neutral, purely + # unblocking the parse. for elements_key in ("roofs", "walls", "floors", "windows"): for element in _dicts(d.get(elements_key)): if ( diff --git a/datatypes/epc/domain/tests/test_from_sap_schema_15_0.py b/datatypes/epc/domain/tests/test_from_sap_schema_15_0.py index ef8658ea8..745157de5 100644 --- a/datatypes/epc/domain/tests/test_from_sap_schema_15_0.py +++ b/datatypes/epc/domain/tests/test_from_sap_schema_15_0.py @@ -141,17 +141,19 @@ class TestFromSapSchema15_0: assert epc.has_hot_water_cylinder is False assert epc.sap_heating.cylinder_size == 1 - def test_defaults_description_on_a_bare_zero_rated_party_wall(self) -> None: + def test_defaults_description_on_a_bare_n_a_rated_wall_element(self) -> None: # Task 9d271e98-96e6-4be6-bb50-e9be6f954003 (portfolio 796 / scenario # 1268) failed 21 "Top-floor flat" properties with "EnergyElement: # missing required field 'description'": every one lodges a second - # `walls[]` entry that is a bare zero-rated party-wall boundary - # element (`{"energy_efficiency_rating": 0, - # "environmental_efficiency_rating": 0}`, no description key at all) - # — property_id 735232 / UPRN 100061740136 / cert - # 8204-4998-7729-4026-5693 here. Must default to "" rather than fail - # loud (calc-neutral — `_joined_descriptions` already drops falsy - # descriptions). + # `walls[]` entry with both ratings 0 and no description key at all + # (`{"energy_efficiency_rating": 0, "environmental_efficiency_rating": + # 0}`) — property_id 735232 / UPRN 100061740136 / cert + # 8204-4998-7729-4026-5693 here. Rating 0 == "N/A" per the gov EPC + # code table (epc_codes.csv); the payload carries no other field, so + # the specific cause of the N/A (party wall? something else?) isn't + # determinable from the data. Must default to "" rather than fail + # loud regardless of cause (calc-neutral — `_joined_descriptions` + # already drops falsy descriptions). epc = EpcPropertyDataMapper.from_api_response( load("sap_15_0_uprn_100061740136.json") )