From 0b32d9fceedeb8ad5d3e36ba8e5813e2bd85dbda Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Tue, 16 Jun 2026 19:24:50 +0000 Subject: [PATCH] Add SAP-16.3 + SAP-17.0 schema coverage (completes the e2e UPRN set) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SAP-Schema-16.3: same reduced-field RdSAP shape as 16.2 — generalise the normaliser to _normalize_sap_schema_16_x and route both 16.2/16.3 through it. uprn_44012843 maps → SAP 79 (lodged 81). - SAP-Schema-17.0: structurally identical to the full-SAP 17.1 schema (measured sap_opening_types), so it parses with the 17.1 dataclass and reuses from_sap_schema_17_1 with no normalisation. uprn_10023444324 → 80, uprn_ 10023444320 → 81. - Regression tests (16.3 dispatch, 17.0 dispatch) + sap_16_3.json / sap_17_0.json fixtures; 0 new pyright errors. All 7 e2e UPRNs now map. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../expand-sap-accuracy-corpus/worklist.md | 14 +- .../SAP-Schema-17.0/uprn_10023444320/epc.json | 364 ++++++++++++++++ .../SAP-Schema-17.0/uprn_10023444324/epc.json | 387 ++++++++++++++++++ datatypes/epc/domain/mapper.py | 33 +- .../epc/domain/tests/test_from_sap_schema.py | 28 +- .../epc/schema/tests/fixtures/sap_16_3.json | 222 ++++++++++ .../epc/schema/tests/fixtures/sap_17_0.json | 387 ++++++++++++++++++ 7 files changed, 1413 insertions(+), 22 deletions(-) create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444320/epc.json create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444324/epc.json create mode 100644 datatypes/epc/schema/tests/fixtures/sap_16_3.json create mode 100644 datatypes/epc/schema/tests/fixtures/sap_17_0.json diff --git a/.claude/skills/expand-sap-accuracy-corpus/worklist.md b/.claude/skills/expand-sap-accuracy-corpus/worklist.md index 55134391..c8dfb679 100644 --- a/.claude/skills/expand-sap-accuracy-corpus/worklist.md +++ b/.claude/skills/expand-sap-accuracy-corpus/worklist.md @@ -20,9 +20,11 @@ UPRNs needed for end-to-end testing (also tracked in The 100 below). | 10093116543 | SAP-17.1 | ✅ pinned | 81 (elm 77) | 2017 gas-combi semi | | 10093116529 | SAP-17.1 | ✅ pinned | 81 (elm 78) | 2017 gas-combi g/f flat; party-wall fix | | 100020933699 | SAP-16.2 | 🔧 mapper + glazing fix | 71 (lodged 70) | RdSAP-shaped; single-glazing fix; Elmhurst validation pending | -| 44012843 | — | ☐ todo | — | not yet processed | -| 10023444324 | — | ☐ todo | — | not yet processed | -| 10023444320 | — | ☐ todo | — | not yet processed | +| 44012843 | SAP-16.3 | 🔧 mapper added | 79 (lodged 81) | same 16.x reduced-field path; Elmhurst pending | +| 10023444324 | SAP-17.0 | 🔧 mapper added | 80 (lodged 82) | full-SAP shape = 17.1; Elmhurst pending | +| 10023444320 | SAP-17.0 | 🔧 mapper added | 81 (lodged 81) | full-SAP shape = 17.1; Elmhurst pending | + +**All 7 e2e UPRNs now map and produce engine SAP scores.** Schema coverage added this session: SAP-16.2, SAP-16.3 (reduced-field → RdSAP-17.1 path), SAP-17.0 (full-SAP → 17.1 path). ## The 100 @@ -30,8 +32,8 @@ UPRNs needed for end-to-end testing (also tracked in The 100 below). - [x] 10093116543 — SAP-17.1 (2017 gas-combi semi) · eng 81 / elm 77 (lodged 82) · PINNED engine 81. +4 = documented full-SAP→RdSAP residual, NOT a mapper bug: ~1.5 floor-U (cert lodges measured 0.11 vs Elmhurst RdSAP solid default 0.23; U-known override disabled) + ~1 boiler-eff (cert PCDB 17644 88.5% vs Elmhurst generic BGW combi 84%; PCDB search disabled, 89% cascade option is a regular boiler needing a cylinder) + ~0.5 roof band-L/infil. Conservatory leftover from prior cert cleared (worksheet 73→77). No mapper change. - [x] 🔧 10093116529 — SAP-17.1 (2017 gas-combi ground-floor FLAT, TFA 49) · eng 81 / elm 78 (lodged 81) · PINNED engine 81. 🔧 FIXED a real calc bug: full-SAP flats took the 0.25 house party-wall default instead of the RdSAP Table-15 flat 0.0 (flatness is in dwelling_type, not property_type) — heat_transmission._is_flat_or_maisonette_dwelling; +regression test. Cert lodges party u_value 0; Elmhurst worksheet 0.0; fix 80→81. Residual +3 vs Elmhurst = documented full-SAP→RdSAP gap (measured wall 0.184/floor 0.12 + PCDB 88.5% vs generic 84%). Calculator faithful: fed Elmhurst's Us, HTC 93.4 vs ~94. House→Flat Elmhurst switch (storeys→1, roof→another-dwelling-above). No mapper change. - [ ] 🔧 100020933699 — SAP-16.2 SCHEMA COVERAGE ADDED (end-terrace house, band G). 16.2 is structurally RdSAP-17.1 (reduced fields, glazed_area band, construction-code building parts) under a different name; mapped via `_normalize_sap_schema_16_2` (renames windows→window, main_gas→mains_gas, boiler_index_number→main_heating_index_number, wwhrs→instantaneous_wwhrs + defaults) → reuses from_rdsap_schema_17_1. 🔧 Also fixed: "Single glazed" description honoured when multiple_glazing_type="ND" (was defaulting to double; RdSAP-21 code 5) → eng 72→71. +4 regression tests, sap_16_2.json fixture, 0 new pyright errors. eng 71 / lodged 70. ⚠ Known gap: 16.2 lodges no party_wall_length → end-terrace party wall unmodelled (likely the residual +1). ⏳ Elmhurst build (partial: PropDesc/Dims/Walls/Roofs done) + pin still pending. -- [ ] 44012843 -- [ ] 10023444324 +- [ ] 🔧 44012843 — SAP-16.3 schema coverage (same _normalize_sap_schema_16_x reduced-field path as 16.2) · eng 79 / lodged 81 · g/f flat band K · Elmhurst pin pending +- [ ] 🔧 10023444324 — SAP-17.0 schema coverage (full-SAP shape ≡ 17.1; dispatched to from_sap_schema_17_1, no normalization) · eng 80 / lodged 82 · Elmhurst pin pending - [ ] 10092970673 - [ ] 10094601287 - [ ] 10090844932 @@ -89,7 +91,7 @@ UPRNs needed for end-to-end testing (also tracked in The 100 below). - [ ] 10093305101 - [ ] 100020933894 - [ ] 100020937013 -- [ ] 10023444320 +- [ ] 🔧 10023444320 — SAP-17.0 schema coverage (full-SAP ≡ 17.1) · eng 81 / lodged 81 · Elmhurst pin pending - [ ] 100062188801 - [ ] 10008048040 - [ ] 10093101966 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444320/epc.json b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444320/epc.json new file mode 100644 index 00000000..23f50eb8 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444320/epc.json @@ -0,0 +1,364 @@ +{ + "uprn": 10023444320, + "roofs": [ + { + "description": "(other premises above)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "walls": [ + { + "description": "Average thermal transmittance 0.2 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "floors": [ + { + "description": "Average thermal transmittance 0.2 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "status": "entered", + "tenure": "ND", + "windows": { + "description": "High performance glazing", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "lighting": { + "description": "Low energy lighting in all fixed outlets", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "DA1 5UU", + "data_type": 2, + "hot_water": { + "description": "From main system", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "post_town": "DARTFORD", + "built_form": 1, + "created_at": "2016-09-06 16:02:50", + "living_area": 21.45, + "orientation": 0, + "region_code": 14, + "report_type": 3, + "sap_heating": { + "thermal_store": 1, + "water_fuel_type": 1, + "water_heating_code": 901, + "main_heating_details": [ + { + "main_fuel_type": 1, + "heat_emitter_type": 1, + "emitter_temperature": 1, + "is_flue_fan_present": "true", + "main_heating_number": 1, + "main_heating_control": 2106, + "is_interlocked_system": "true", + "main_heating_category": 2, + "main_heating_fraction": 1, + "main_heating_flue_type": 2, + "central_heating_pump_age": 2, + "main_heating_data_source": 1, + "main_heating_index_number": 16211, + "has_separate_delayed_start": "true", + "load_or_weather_compensation": 0, + "is_central_heating_pump_in_heated_space": "true" + } + ], + "has_hot_water_cylinder": "false", + "has_fixed_air_conditioning": "false", + "secondary_heating_category": 1 + }, + "sap_version": 9.92, + "schema_type": "SAP-Schema-17.0", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and radiators, mains gas", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "air_tightness": { + "description": "Air permeability 3.1 m\u00b3/h.m\u00b2 (as tested)", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "dwelling_type": "Mid-floor flat", + "language_code": 1, + "property_type": 2, + "address_line_1": "10, Ashmore Close", + "assessment_date": "2016-09-06", + "assessment_type": "SAP", + "completion_date": "2016-09-06", + "inspection_date": "2016-09-06", + "sap_ventilation": { + "psv_count": 0, + "pressure_test": 1, + "wet_rooms_count": 2, + "air_permeability": 3.09, + "open_flues_count": 0, + "ventilation_type": 6, + "extract_fans_count": 0, + "open_fireplaces_count": 0, + "sheltered_sides_count": 2, + "kitchen_duct_fans_count": 0, + "kitchen_room_fans_count": 1, + "kitchen_wall_fans_count": 0, + "flueless_gas_fires_count": 0, + "mechanical_vent_duct_type": 2, + "non_kitchen_duct_fans_count": 0, + "non_kitchen_room_fans_count": 1, + "non_kitchen_wall_fans_count": 0, + "mechanical_ventilation_data_source": 1, + "mechanical_vent_system_index_number": 500416, + "is_mechanical_vent_approved_installer_scheme": "true" + }, + "design_water_use": 1, + "sap_data_version": 9.92, + "sap_flat_details": { + "level": 2 + }, + "total_floor_area": 51, + "transaction_type": 6, + "conservatory_type": 1, + "registration_date": "2016-09-06", + "sap_energy_source": { + "pv_arrays": [ + { + "pitch": 2, + "peak_power": 0.48, + "orientation": 5, + "overshading": 1, + "pv_connection": 1 + } + ], + "electricity_tariff": 1, + "wind_turbines_count": 0, + "wind_turbine_terrain_type": 2, + "fixed_lighting_outlets_count": 6, + "low_energy_fixed_lighting_outlets_count": 6, + "low_energy_fixed_lighting_outlets_percentage": 100 + }, + "sap_opening_types": [ + { + "name": 1, + "type": 1, + "u_value": 0.97, + "data_source": 2, + "description": "Front", + "glazing_type": 1 + }, + { + "name": 2, + "type": 4, + "u_value": 1.2, + "data_source": 2, + "description": "Window", + "frame_factor": 0.7, + "glazing_type": 6, + "solar_transmittance": 0.63 + } + ], + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "lzc_energy_sources": [ + 11 + ], + "sap_building_parts": [ + { + "sap_walls": [ + { + "name": "Wall 1", + "u_value": 0.2, + "wall_type": 2, + "description": "150mm hi-cav 32 AAC", + "total_wall_area": 53.26, + "is_curtain_walling": "false" + }, + { + "name": "Wall 2", + "u_value": 0.18, + "wall_type": 3, + "description": "To corridor", + "total_wall_area": 15.18, + "is_curtain_walling": "false" + } + ], + "identifier": "Main Dwelling", + "overshading": 2, + "sap_openings": [ + { + "name": 1, + "type": 1, + "width": 1, + "height": 2.1, + "location": "Wall 2", + "orientation": 0 + }, + { + "name": 2, + "type": 2, + "width": 1.17, + "height": 2.29, + "location": "Wall 1", + "orientation": 5 + }, + { + "name": 3, + "type": 2, + "width": 1.17, + "height": 2.29, + "location": "Wall 1", + "orientation": 5 + }, + { + "name": 4, + "type": 2, + "width": 2.29, + "height": 2.29, + "location": "Wall 1", + "orientation": 5 + }, + { + "name": 5, + "type": 2, + "width": 1.18, + "height": 1.38, + "location": "Wall 1", + "orientation": 1 + }, + { + "name": 6, + "type": 2, + "width": 1.18, + "height": 1.38, + "location": "Wall 1", + "orientation": 1 + } + ], + "construction_year": 2015, + "sap_thermal_bridges": { + "thermal_bridges": [ + { + "length": 7.99, + "psi_value": 0.3, + "psi_value_source": 2, + "thermal_bridge_type": "E2" + }, + { + "length": 6.99, + "psi_value": 0.04, + "psi_value_source": 2, + "thermal_bridge_type": "E3" + }, + { + "length": 23.46, + "psi_value": 0.05, + "psi_value_source": 2, + "thermal_bridge_type": "E4" + }, + { + "length": 28.39, + "psi_value": 0.32, + "psi_value_source": 4, + "thermal_bridge_type": "E20" + }, + { + "length": 2.41, + "psi_value": 1, + "psi_value_source": 3, + "thermal_bridge_type": "E9" + }, + { + "length": 9.64, + "psi_value": 0.09, + "psi_value_source": 2, + "thermal_bridge_type": "E16" + } + ], + "thermal_bridge_code": 5 + }, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "storey": 1, + "u_value": 0.18, + "floor_type": 4, + "description": "Floor abv Bike Store", + "storey_height": 2.41, + "heat_loss_area": 50.68, + "total_floor_area": 50.68 + } + ], + "thermal_mass_parameter": 250 + } + ], + "heating_cost_current": { + "value": 182, + "currency": "GBP" + }, + "co2_emissions_current": 0.7, + "energy_rating_average": 60, + "energy_rating_current": 81, + "lighting_cost_current": { + "value": 36, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Programmer, room thermostat and TRVs", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "has_hot_water_cylinder": "false", + "heating_cost_potential": { + "value": 182, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 80, + "currency": "GBP" + }, + "co2_emissions_potential": 0.7, + "energy_rating_potential": 81, + "lighting_cost_potential": { + "value": 36, + "currency": "GBP" + }, + "schema_version_original": "LIG-17.0", + "hot_water_cost_potential": { + "value": 80, + "currency": "GBP" + }, + "is_in_smoke_control_area": "unknown", + "renewable_heat_incentive": { + "rhi_new_dwelling": { + "space_heating": 1525, + "water_heating": 1657 + } + }, + "seller_commission_report": "Y", + "energy_consumption_current": 80, + "has_fixed_air_conditioning": "false", + "multiple_glazed_percentage": 100, + "calculation_software_version": 6.2, + "energy_consumption_potential": 80, + "environmental_impact_current": 89, + "current_energy_efficiency_band": "B", + "environmental_impact_potential": 89, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "B", + "co2_emissions_current_per_floor_area": 14 +} \ No newline at end of file diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444324/epc.json b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444324/epc.json new file mode 100644 index 00000000..57b43b62 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444324/epc.json @@ -0,0 +1,387 @@ +{ + "uprn": 10023444324, + "roofs": [ + { + "description": "(other premises above)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "walls": [ + { + "description": "Average thermal transmittance 0.2 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "floors": [ + { + "description": "Average thermal transmittance 0.1 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "status": "entered", + "tenure": "ND", + "windows": { + "description": "High performance glazing", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "lighting": { + "description": "Low energy lighting in all fixed outlets", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "DA1 5UU", + "data_type": 2, + "hot_water": { + "description": "From main system", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "post_town": "DARTFORD", + "built_form": 3, + "created_at": "2016-09-06 16:02:00", + "living_area": 25.23, + "orientation": 0, + "region_code": 14, + "report_type": 3, + "sap_heating": { + "thermal_store": 1, + "water_fuel_type": 1, + "water_heating_code": 901, + "main_heating_details": [ + { + "main_fuel_type": 1, + "heat_emitter_type": 1, + "emitter_temperature": 1, + "is_flue_fan_present": "true", + "main_heating_number": 1, + "main_heating_control": 2106, + "is_interlocked_system": "true", + "main_heating_category": 2, + "main_heating_fraction": 1, + "main_heating_flue_type": 2, + "central_heating_pump_age": 2, + "main_heating_data_source": 1, + "main_heating_index_number": 16211, + "has_separate_delayed_start": "true", + "load_or_weather_compensation": 0, + "is_central_heating_pump_in_heated_space": "true" + } + ], + "has_hot_water_cylinder": "false", + "has_fixed_air_conditioning": "false", + "secondary_heating_category": 1 + }, + "sap_version": 9.92, + "schema_type": "SAP-Schema-17.0", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and radiators, mains gas", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "air_tightness": { + "description": "Air permeability 3.2 m\u00b3/h.m\u00b2 (as tested)", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "dwelling_type": "Ground-floor flat", + "language_code": 1, + "property_type": 2, + "address_line_1": "1, Ashmore Close", + "assessment_date": "2016-09-06", + "assessment_type": "SAP", + "completion_date": "2016-09-06", + "inspection_date": "2016-09-06", + "sap_ventilation": { + "psv_count": 0, + "pressure_test": 1, + "wet_rooms_count": 2, + "air_permeability": 3.24, + "open_flues_count": 0, + "ventilation_type": 6, + "extract_fans_count": 0, + "open_fireplaces_count": 0, + "sheltered_sides_count": 2, + "kitchen_duct_fans_count": 0, + "kitchen_room_fans_count": 1, + "kitchen_wall_fans_count": 0, + "flueless_gas_fires_count": 0, + "mechanical_vent_duct_type": 2, + "non_kitchen_duct_fans_count": 0, + "non_kitchen_room_fans_count": 1, + "non_kitchen_wall_fans_count": 0, + "mechanical_ventilation_data_source": 1, + "mechanical_vent_system_index_number": 500416, + "is_mechanical_vent_approved_installer_scheme": "true" + }, + "design_water_use": 1, + "sap_data_version": 9.92, + "sap_flat_details": { + "level": 1 + }, + "total_floor_area": 50, + "transaction_type": 6, + "conservatory_type": 1, + "registration_date": "2016-09-06", + "sap_energy_source": { + "pv_arrays": [ + { + "pitch": 2, + "peak_power": 0.48, + "orientation": 5, + "overshading": 1, + "pv_connection": 1 + } + ], + "electricity_tariff": 1, + "wind_turbines_count": 0, + "wind_turbine_terrain_type": 2, + "fixed_lighting_outlets_count": 6, + "low_energy_fixed_lighting_outlets_count": 6, + "low_energy_fixed_lighting_outlets_percentage": 100 + }, + "sap_opening_types": [ + { + "name": 1, + "type": 1, + "u_value": 0.97, + "data_source": 2, + "description": "Front", + "glazing_type": 1 + }, + { + "name": 2, + "type": 4, + "u_value": 1.2, + "data_source": 2, + "description": "Window", + "frame_factor": 0.7, + "glazing_type": 6, + "solar_transmittance": 0.63 + } + ], + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "lzc_energy_sources": [ + 11 + ], + "sap_building_parts": [ + { + "sap_walls": [ + { + "name": "Wall 1", + "u_value": 0.2, + "wall_type": 2, + "description": "150mm hi-cav 32 AAC", + "total_wall_area": 37.93, + "is_curtain_walling": "false" + }, + { + "name": "Wall 2", + "u_value": 0.18, + "wall_type": 3, + "description": "To corridor", + "total_wall_area": 19.28, + "is_curtain_walling": "false" + }, + { + "name": "Wall 3", + "u_value": 0, + "wall_type": 4, + "description": "party", + "total_wall_area": 15.5 + } + ], + "identifier": "Main Dwelling", + "overshading": 2, + "sap_openings": [ + { + "name": 1, + "type": 1, + "width": 1, + "height": 2.1, + "location": "Wall 2", + "orientation": 0 + }, + { + "name": 2, + "type": 2, + "width": 1.16, + "height": 2.28, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 3, + "type": 2, + "width": 1.16, + "height": 1.08, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 4, + "type": 2, + "width": 2.29, + "height": 2.28, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 5, + "type": 2, + "width": 1.17, + "height": 2.23, + "location": "Wall 1", + "orientation": 3 + } + ], + "construction_year": 2015, + "sap_thermal_bridges": { + "thermal_bridges": [ + { + "length": 6.78, + "psi_value": 0.3, + "psi_value_source": 2, + "thermal_bridge_type": "E2" + }, + { + "length": 5.78, + "psi_value": 0.04, + "psi_value_source": 2, + "thermal_bridge_type": "E3" + }, + { + "length": 19.94, + "psi_value": 0.05, + "psi_value_source": 2, + "thermal_bridge_type": "E4" + }, + { + "length": 22.17, + "psi_value": 0.16, + "psi_value_source": 2, + "thermal_bridge_type": "E5" + }, + { + "length": 22.17, + "psi_value": 0.07, + "psi_value_source": 2, + "thermal_bridge_type": "E7" + }, + { + "length": 2.26, + "psi_value": 1, + "psi_value_source": 3, + "thermal_bridge_type": "E9" + }, + { + "length": 4.82, + "psi_value": 0.09, + "psi_value_source": 2, + "thermal_bridge_type": "E16" + }, + { + "length": 4.82, + "psi_value": 0.12, + "psi_value_source": 4, + "thermal_bridge_type": "E18" + }, + { + "length": 8, + "psi_value": 0.16, + "psi_value_source": 4, + "thermal_bridge_type": "P1" + }, + { + "length": 8, + "psi_value": 0, + "psi_value_source": 3, + "thermal_bridge_type": "P3" + } + ], + "thermal_bridge_code": 5 + }, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "storey": 0, + "u_value": 0.1, + "floor_type": 2, + "description": "Floor 1", + "storey_height": 2.41, + "heat_loss_area": 50.17, + "total_floor_area": 50.17 + } + ], + "thermal_mass_parameter": 250 + } + ], + "heating_cost_current": { + "value": 171, + "currency": "GBP" + }, + "co2_emissions_current": 0.7, + "energy_rating_average": 60, + "energy_rating_current": 82, + "lighting_cost_current": { + "value": 36, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Programmer, room thermostat and TRVs", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "has_hot_water_cylinder": "false", + "heating_cost_potential": { + "value": 171, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 80, + "currency": "GBP" + }, + "co2_emissions_potential": 0.7, + "energy_rating_potential": 82, + "lighting_cost_potential": { + "value": 36, + "currency": "GBP" + }, + "schema_version_original": "LIG-17.0", + "hot_water_cost_potential": { + "value": 80, + "currency": "GBP" + }, + "is_in_smoke_control_area": "unknown", + "renewable_heat_incentive": { + "rhi_new_dwelling": { + "space_heating": 1299, + "water_heating": 1651 + } + }, + "seller_commission_report": "Y", + "energy_consumption_current": 75, + "has_fixed_air_conditioning": "false", + "multiple_glazed_percentage": 100, + "calculation_software_version": 6.2, + "energy_consumption_potential": 75, + "environmental_impact_current": 89, + "current_energy_efficiency_band": "B", + "environmental_impact_potential": 89, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "B", + "co2_emissions_current_per_floor_area": 13 +} \ No newline at end of file diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index 7028274c..8e217c9f 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -2546,24 +2546,27 @@ class EpcPropertyDataMapper: from_dict(RdSapSchema17_0, data) ) ) - if schema == "SAP-Schema-17.1": - # Full SAP (not RdSAP). D8: _clear_basement_flag_when_system_built is - # an RdSAP code-6 disambiguation; full SAP lodges explicit wall types - # (no code-6 basement ambiguity), so it's a no-op and is skipped. + if schema in ("SAP-Schema-17.1", "SAP-Schema-17.0"): + # Full SAP (not RdSAP). SAP-Schema-17.0 is structurally identical to + # 17.1 (same measured sap_opening_types / building parts), so it + # parses with the 17.1 dataclass and reuses the same mapper. D8: + # _clear_basement_flag_when_system_built is an RdSAP code-6 + # disambiguation; full SAP lodges explicit wall types (no code-6 + # basement ambiguity), so it's a no-op and is skipped. return EpcPropertyDataMapper.from_sap_schema_17_1( from_dict(SapSchema17_1, data) ) - if schema == "SAP-Schema-16.2": - # SAP-Schema-16.2 is structurally an RdSAP-17.1 cert (reduced fields, - # glazed_area band, construction-code building parts) under a different - # name + a handful of renamed/omitted fields — normalise it onto the - # RdSAP-17.1 shape and reuse that tested mapper. See - # `_normalize_sap_schema_16_2`. + if schema in ("SAP-Schema-16.2", "SAP-Schema-16.3"): + # The SAP-Schema-16.x family is structurally RdSAP-17.1 (reduced + # fields, glazed_area band, construction-code building parts) under a + # different name + a handful of renamed/omitted fields — normalise + # onto the RdSAP-17.1 shape and reuse that tested mapper. See + # `_normalize_sap_schema_16_x`. from datatypes.epc.schema.rdsap_schema_17_1 import RdSapSchema17_1 return _clear_basement_flag_when_system_built( EpcPropertyDataMapper.from_rdsap_schema_17_1( - from_dict(RdSapSchema17_1, _normalize_sap_schema_16_2(data)) + from_dict(RdSapSchema17_1, _normalize_sap_schema_16_x(data)) ) ) @@ -3022,11 +3025,11 @@ def _default_missing_post_town(data: Dict[str, Any]) -> Dict[str, Any]: return {**data, "post_town": ""} -def _normalize_sap_schema_16_2(data: Dict[str, Any]) -> Dict[str, Any]: - """Rewrite a `SAP-Schema-16.2` API doc onto the `RdSAP-Schema-17.1` shape so - it can reuse the tested `from_rdsap_schema_17_1` mapper. +def _normalize_sap_schema_16_x(data: Dict[str, Any]) -> Dict[str, Any]: + """Rewrite a `SAP-Schema-16.2`/`16.3` API doc onto the `RdSAP-Schema-17.1` + shape so it can reuse the tested `from_rdsap_schema_17_1` mapper. - Despite the "SAP-Schema" name, 16.2 is structurally an RdSAP cert (reduced + Despite the "SAP-Schema" name, 16.x is structurally an RdSAP cert (reduced fields: a `glazed_area` *band* not measured openings, construction-code building parts, `main_gas`/`meter_type` energy source, a PCDB boiler index). It differs from RdSAP-17.1 only by a handful of field names plus three diff --git a/datatypes/epc/domain/tests/test_from_sap_schema.py b/datatypes/epc/domain/tests/test_from_sap_schema.py index 8f5d3ab1..ad088bac 100644 --- a/datatypes/epc/domain/tests/test_from_sap_schema.py +++ b/datatypes/epc/domain/tests/test_from_sap_schema.py @@ -381,7 +381,7 @@ class TestFromSapSchema17_1Perimeter: class TestFromSapSchema16_2: """SAP-Schema-16.2 — structurally an RdSAP-17.1 cert under a different name + a few renamed/omitted fields. `from_api_response` normalises it onto the - RdSAP-17.1 shape (`_normalize_sap_schema_16_2`) and reuses that mapper. + RdSAP-17.1 shape (`_normalize_sap_schema_16_x`) and reuses that mapper. Regression for uprn_100020933699 (cert 9548-…-0950, End-terrace house).""" def test_16_2_dispatches_and_maps_via_rdsap_17_1(self) -> None: @@ -419,6 +419,32 @@ class TestFromSapSchema16_2: assert epc.sap_windows, "expected synthesised windows" assert epc.sap_windows[0].glazing_type == 1 # cascade single-glazing slot + def test_16_3_dispatches_via_same_16_x_path(self) -> None: + # SAP-Schema-16.3 is the same reduced-field RdSAP shape as 16.2 and + # routes through the same _normalize_sap_schema_16_x path. Regression + # for uprn_44012843 (ground-floor flat, age band K). + from domain.sap10_calculator.calculator import Sap10Calculator + + epc = EpcPropertyDataMapper.from_api_response(load("sap_16_3.json")) + assert isinstance(epc, EpcPropertyData) + assert epc.uprn == 44012843 + assert epc.dwelling_type == "Ground-floor flat" + # lodged 81; engine produces 79. + assert Sap10Calculator().calculate(epc).sap_score == 79 + + def test_17_0_dispatches_via_full_sap_path(self) -> None: + # SAP-Schema-17.0 is structurally identical to the full-SAP 17.1 schema + # (measured sap_opening_types) — it parses with the 17.1 dataclass and + # reuses from_sap_schema_17_1 with no normalisation. Regression for + # uprn_10023444324 (ground-floor flat). + from domain.sap10_calculator.calculator import Sap10Calculator + + epc = EpcPropertyDataMapper.from_api_response(load("sap_17_0.json")) + assert isinstance(epc, EpcPropertyData) + assert epc.uprn == 10023444324 + # lodged 82; engine produces 80. + assert Sap10Calculator().calculate(epc).sap_score == 80 + def test_16_2_normalizer_does_not_mutate_caller_dict(self) -> None: # Mirror _normalize_shower_outlets' contract: the caller's dict is # untouched (deep copy), so a re-dispatch sees the original shape. diff --git a/datatypes/epc/schema/tests/fixtures/sap_16_3.json b/datatypes/epc/schema/tests/fixtures/sap_16_3.json new file mode 100644 index 00000000..eaa277d5 --- /dev/null +++ b/datatypes/epc/schema/tests/fixtures/sap_16_3.json @@ -0,0 +1,222 @@ +{ + "uprn": 44012843, + "roofs": [ + { + "description": "(another dwelling above)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "walls": [ + { + "description": "Cavity wall, as built, insulated (assumed)", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "floors": [ + { + "description": "Solid, insulated (assumed)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "status": "entered", + "tenure": 2, + "windows": [ + { + "description": "Fully double glazed", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "lighting": { + "description": "Low energy lighting in 80% of fixed outlets", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "ME2 2BN", + "hot_water": { + "description": "From main system, plus solar", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "post_town": "ROCHESTER", + "built_form": 3, + "created_at": "2014-02-18 23:08:35", + "door_count": 1, + "glazed_area": 1, + "region_code": 14, + "report_type": 2, + "sap_heating": { + "wwhrs": { + "rooms_with_bath_and_or_shower": 1, + "rooms_with_mixer_shower_no_bath": 0, + "rooms_with_bath_and_mixer_shower": 1 + }, + "cylinder_size": 4, + "water_heating_code": 901, + "water_heating_fuel": 26, + "cylinder_thermostat": "Y", + "main_heating_details": [ + { + "has_fghrs": "N", + "main_fuel_type": 26, + "boiler_flue_type": 2, + "fan_flue_present": "Y", + "heat_emitter_type": 1, + "boiler_index_number": 9895, + "main_heating_number": 1, + "main_heating_control": 2106, + "main_heating_category": 2, + "main_heating_fraction": 1, + "main_heating_data_source": 1 + } + ], + "cylinder_insulation_type": 1, + "has_fixed_air_conditioning": "false", + "cylinder_insulation_thickness": 50 + }, + "sap_version": 9.91, + "schema_type": "SAP-Schema-16.3", + "uprn_source": "Energy Assessor", + "country_code": "EAW", + "main_heating": [ + { + "description": "Boiler and radiators, mains gas", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "dwelling_type": "Ground-floor flat", + "language_code": 1, + "property_type": 2, + "address_line_1": "1 Alexandra House", + "address_line_2": "Sealand Drive", + "schema_version": "LIG-16.1", + "assessment_type": "RdSAP", + "completion_date": "2014-02-18", + "inspection_date": "2014-02-18", + "extensions_count": 0, + "measurement_type": 1, + "sap_flat_details": { + "level": 1, + "top_storey": "N", + "flat_location": 0, + "heat_loss_corridor": 2, + "unheated_corridor_length": 10.8 + }, + "total_floor_area": 55, + "transaction_type": 8, + "conservatory_type": 1, + "heated_room_count": 2, + "registration_date": "2014-02-18", + "restricted_access": 0, + "sap_energy_source": { + "main_gas": "Y", + "meter_type": 2, + "photovoltaic_supply": { + "percent_roof_area": 0 + }, + "wind_turbines_count": 0, + "wind_turbines_terrain_type": 2 + }, + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "lzc_energy_sources": [ + 10 + ], + "sap_building_parts": [ + { + "identifier": "Main Dwelling", + "wall_dry_lined": "N", + "wall_thickness": 340, + "floor_heat_loss": 7, + "roof_construction": 3, + "wall_construction": 4, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "floor": 0, + "room_height": 2.35, + "floor_insulation": 1, + "total_floor_area": 55.26, + "floor_construction": 1, + "heat_loss_perimeter": 29.2 + } + ], + "wall_insulation_type": 4, + "construction_age_band": "K", + "wall_thickness_measured": "Y", + "roof_insulation_location": "ND", + "roof_insulation_thickness": "ND" + } + ], + "low_energy_lighting": 80, + "solar_water_heating": "Y", + "bedf_revision_number": 353, + "habitable_room_count": 2, + "heating_cost_current": { + "value": 231, + "currency": "GBP" + }, + "insulated_door_count": 0, + "co2_emissions_current": 1.0, + "energy_rating_average": 60, + "energy_rating_current": 81, + "lighting_cost_current": { + "value": 47, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Programmer, room thermostat and TRVs", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "multiple_glazing_type": 2, + "open_fireplaces_count": 0, + "has_hot_water_cylinder": "true", + "heating_cost_potential": { + "value": 231, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 61, + "currency": "GBP" + }, + "mechanical_ventilation": 0, + "percent_draughtproofed": 100, + "co2_emissions_potential": 1.0, + "energy_rating_potential": 81, + "lighting_cost_potential": { + "value": 47, + "currency": "GBP" + }, + "hot_water_cost_potential": { + "value": 61, + "currency": "GBP" + }, + "renewable_heat_incentive": { + "water_heating": 2177, + "space_heating_existing_dwelling": 2074 + }, + "seller_commission_report": "Y", + "energy_consumption_current": 99, + "has_fixed_air_conditioning": "false", + "multiple_glazed_proportion": 100, + "calculation_software_version": 8.3, + "energy_consumption_potential": 99, + "environmental_impact_current": 85, + "fixed_lighting_outlets_count": 5, + "current_energy_efficiency_band": "B", + "environmental_impact_potential": 85, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "B", + "co2_emissions_current_per_floor_area": 19, + "low_energy_fixed_lighting_outlets_count": 4 +} \ No newline at end of file diff --git a/datatypes/epc/schema/tests/fixtures/sap_17_0.json b/datatypes/epc/schema/tests/fixtures/sap_17_0.json new file mode 100644 index 00000000..57b43b62 --- /dev/null +++ b/datatypes/epc/schema/tests/fixtures/sap_17_0.json @@ -0,0 +1,387 @@ +{ + "uprn": 10023444324, + "roofs": [ + { + "description": "(other premises above)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "walls": [ + { + "description": "Average thermal transmittance 0.2 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "floors": [ + { + "description": "Average thermal transmittance 0.1 W/m\u00b2K", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "status": "entered", + "tenure": "ND", + "windows": { + "description": "High performance glazing", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "lighting": { + "description": "Low energy lighting in all fixed outlets", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "DA1 5UU", + "data_type": 2, + "hot_water": { + "description": "From main system", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "post_town": "DARTFORD", + "built_form": 3, + "created_at": "2016-09-06 16:02:00", + "living_area": 25.23, + "orientation": 0, + "region_code": 14, + "report_type": 3, + "sap_heating": { + "thermal_store": 1, + "water_fuel_type": 1, + "water_heating_code": 901, + "main_heating_details": [ + { + "main_fuel_type": 1, + "heat_emitter_type": 1, + "emitter_temperature": 1, + "is_flue_fan_present": "true", + "main_heating_number": 1, + "main_heating_control": 2106, + "is_interlocked_system": "true", + "main_heating_category": 2, + "main_heating_fraction": 1, + "main_heating_flue_type": 2, + "central_heating_pump_age": 2, + "main_heating_data_source": 1, + "main_heating_index_number": 16211, + "has_separate_delayed_start": "true", + "load_or_weather_compensation": 0, + "is_central_heating_pump_in_heated_space": "true" + } + ], + "has_hot_water_cylinder": "false", + "has_fixed_air_conditioning": "false", + "secondary_heating_category": 1 + }, + "sap_version": 9.92, + "schema_type": "SAP-Schema-17.0", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and radiators, mains gas", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "air_tightness": { + "description": "Air permeability 3.2 m\u00b3/h.m\u00b2 (as tested)", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "dwelling_type": "Ground-floor flat", + "language_code": 1, + "property_type": 2, + "address_line_1": "1, Ashmore Close", + "assessment_date": "2016-09-06", + "assessment_type": "SAP", + "completion_date": "2016-09-06", + "inspection_date": "2016-09-06", + "sap_ventilation": { + "psv_count": 0, + "pressure_test": 1, + "wet_rooms_count": 2, + "air_permeability": 3.24, + "open_flues_count": 0, + "ventilation_type": 6, + "extract_fans_count": 0, + "open_fireplaces_count": 0, + "sheltered_sides_count": 2, + "kitchen_duct_fans_count": 0, + "kitchen_room_fans_count": 1, + "kitchen_wall_fans_count": 0, + "flueless_gas_fires_count": 0, + "mechanical_vent_duct_type": 2, + "non_kitchen_duct_fans_count": 0, + "non_kitchen_room_fans_count": 1, + "non_kitchen_wall_fans_count": 0, + "mechanical_ventilation_data_source": 1, + "mechanical_vent_system_index_number": 500416, + "is_mechanical_vent_approved_installer_scheme": "true" + }, + "design_water_use": 1, + "sap_data_version": 9.92, + "sap_flat_details": { + "level": 1 + }, + "total_floor_area": 50, + "transaction_type": 6, + "conservatory_type": 1, + "registration_date": "2016-09-06", + "sap_energy_source": { + "pv_arrays": [ + { + "pitch": 2, + "peak_power": 0.48, + "orientation": 5, + "overshading": 1, + "pv_connection": 1 + } + ], + "electricity_tariff": 1, + "wind_turbines_count": 0, + "wind_turbine_terrain_type": 2, + "fixed_lighting_outlets_count": 6, + "low_energy_fixed_lighting_outlets_count": 6, + "low_energy_fixed_lighting_outlets_percentage": 100 + }, + "sap_opening_types": [ + { + "name": 1, + "type": 1, + "u_value": 0.97, + "data_source": 2, + "description": "Front", + "glazing_type": 1 + }, + { + "name": 2, + "type": 4, + "u_value": 1.2, + "data_source": 2, + "description": "Window", + "frame_factor": 0.7, + "glazing_type": 6, + "solar_transmittance": 0.63 + } + ], + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "lzc_energy_sources": [ + 11 + ], + "sap_building_parts": [ + { + "sap_walls": [ + { + "name": "Wall 1", + "u_value": 0.2, + "wall_type": 2, + "description": "150mm hi-cav 32 AAC", + "total_wall_area": 37.93, + "is_curtain_walling": "false" + }, + { + "name": "Wall 2", + "u_value": 0.18, + "wall_type": 3, + "description": "To corridor", + "total_wall_area": 19.28, + "is_curtain_walling": "false" + }, + { + "name": "Wall 3", + "u_value": 0, + "wall_type": 4, + "description": "party", + "total_wall_area": 15.5 + } + ], + "identifier": "Main Dwelling", + "overshading": 2, + "sap_openings": [ + { + "name": 1, + "type": 1, + "width": 1, + "height": 2.1, + "location": "Wall 2", + "orientation": 0 + }, + { + "name": 2, + "type": 2, + "width": 1.16, + "height": 2.28, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 3, + "type": 2, + "width": 1.16, + "height": 1.08, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 4, + "type": 2, + "width": 2.29, + "height": 2.28, + "location": "Wall 1", + "orientation": 7 + }, + { + "name": 5, + "type": 2, + "width": 1.17, + "height": 2.23, + "location": "Wall 1", + "orientation": 3 + } + ], + "construction_year": 2015, + "sap_thermal_bridges": { + "thermal_bridges": [ + { + "length": 6.78, + "psi_value": 0.3, + "psi_value_source": 2, + "thermal_bridge_type": "E2" + }, + { + "length": 5.78, + "psi_value": 0.04, + "psi_value_source": 2, + "thermal_bridge_type": "E3" + }, + { + "length": 19.94, + "psi_value": 0.05, + "psi_value_source": 2, + "thermal_bridge_type": "E4" + }, + { + "length": 22.17, + "psi_value": 0.16, + "psi_value_source": 2, + "thermal_bridge_type": "E5" + }, + { + "length": 22.17, + "psi_value": 0.07, + "psi_value_source": 2, + "thermal_bridge_type": "E7" + }, + { + "length": 2.26, + "psi_value": 1, + "psi_value_source": 3, + "thermal_bridge_type": "E9" + }, + { + "length": 4.82, + "psi_value": 0.09, + "psi_value_source": 2, + "thermal_bridge_type": "E16" + }, + { + "length": 4.82, + "psi_value": 0.12, + "psi_value_source": 4, + "thermal_bridge_type": "E18" + }, + { + "length": 8, + "psi_value": 0.16, + "psi_value_source": 4, + "thermal_bridge_type": "P1" + }, + { + "length": 8, + "psi_value": 0, + "psi_value_source": 3, + "thermal_bridge_type": "P3" + } + ], + "thermal_bridge_code": 5 + }, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "storey": 0, + "u_value": 0.1, + "floor_type": 2, + "description": "Floor 1", + "storey_height": 2.41, + "heat_loss_area": 50.17, + "total_floor_area": 50.17 + } + ], + "thermal_mass_parameter": 250 + } + ], + "heating_cost_current": { + "value": 171, + "currency": "GBP" + }, + "co2_emissions_current": 0.7, + "energy_rating_average": 60, + "energy_rating_current": 82, + "lighting_cost_current": { + "value": 36, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Programmer, room thermostat and TRVs", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "has_hot_water_cylinder": "false", + "heating_cost_potential": { + "value": 171, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 80, + "currency": "GBP" + }, + "co2_emissions_potential": 0.7, + "energy_rating_potential": 82, + "lighting_cost_potential": { + "value": 36, + "currency": "GBP" + }, + "schema_version_original": "LIG-17.0", + "hot_water_cost_potential": { + "value": 80, + "currency": "GBP" + }, + "is_in_smoke_control_area": "unknown", + "renewable_heat_incentive": { + "rhi_new_dwelling": { + "space_heating": 1299, + "water_heating": 1651 + } + }, + "seller_commission_report": "Y", + "energy_consumption_current": 75, + "has_fixed_air_conditioning": "false", + "multiple_glazed_percentage": 100, + "calculation_software_version": 6.2, + "energy_consumption_potential": 75, + "environmental_impact_current": 89, + "current_energy_efficiency_band": "B", + "environmental_impact_potential": 89, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "B", + "co2_emissions_current_per_floor_area": 13 +} \ No newline at end of file