mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-08-03 05:18:22 +00:00
Merge pull request #1711 from Hestia-Homes/fix/sap-full-community-dhw
Bill full-SAP water-only community hot water on the heat-pump network (re-opens #1692)
This commit is contained in:
commit
141c783e40
13 changed files with 1047 additions and 0 deletions
|
|
@ -0,0 +1,127 @@
|
|||
# Elmhurst RdSAP inputs — UPRN 10094112770 (cert 9556-3047-3304-5355-1200, SAP-Schema-18.0.0)
|
||||
|
||||
**Lodged SAP:** 81 (B) **Our engine:** 67 (D) ← compare Elmhurst against this
|
||||
**Property:** Apartment 4, Dovestone Gardens, Briercliffe Road, BURNLEY, BB10 1BB (Calico portfolio 824, property 748351)
|
||||
|
||||
**Known divergence (the whole point of this cert):** the dwelling has **direct-electric
|
||||
room heaters for space heat** + a **WATER-ONLY communal heat network for hot water**
|
||||
(`water_heating_code 950`, `community_heating_use 2`; network = 90 % heat pump COP 3.24
|
||||
+ 10 % boiler). Our engine drops the community DHW system and prices hot water as **raw
|
||||
direct electric immersion** — 2,675 kWh ≈ £660 vs **lodged DHW cost £147**. That ~£500
|
||||
DHW error is what drags lodged B/81 → effective D/67. Build the **Community Hot Water**
|
||||
page below faithfully so Elmhurst prices DHW on the heat-pump network; that is the number
|
||||
we are reconciling to. PR #1688 does not fix this case (its community mapping is gated on
|
||||
a category-6 *main*; here the main is category-10 electric).
|
||||
|
||||
---
|
||||
|
||||
## Property Description
|
||||
| Elmhurst field | Value | Notes (SAP code / EES path) |
|
||||
|---|---|---|
|
||||
| Property type | Flat | `property_type` 2 |
|
||||
| Built form | End-terrace | `built_form` 3 |
|
||||
| Flat position / which floor | Ground floor | `dwelling_type` = Ground-floor flat |
|
||||
| Storeys in dwelling | 1 | single-storey flat |
|
||||
| Above another dwelling? | No (ground floor) | floor is exposed/over unheated |
|
||||
| Below another dwelling? | **Yes** | roof element = "(other premises above)" → no roof heat loss |
|
||||
| Age band | **M — 2023 onwards** | 2025 inspection, genuine new build (band M is correct here) |
|
||||
| Region | North West | BB (Burnley) |
|
||||
| Country | England | `country_code` ENG |
|
||||
|
||||
## Dimensions
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Total floor area | **58 m²** | `total_floor_area` 58; single building part "Main Dwelling" |
|
||||
| Living area | 22.57 m² | `living_area` (→ living-area fraction 0.39; habitable rooms ≈ 3) |
|
||||
| Room height | ≈ 2.4 m | not lodged in full-SAP payload; use standard new-build flat height |
|
||||
| Exposed (external) wall area | **37.01 m² gross** | External Wall 1, `total_wall_area` 37.01, U 0.19 (net of ~14.7 m² openings) |
|
||||
| Heat-loss perimeter | derive from 37.01 m² gross wall ÷ room height | full SAP lodges wall *area*, not perimeter |
|
||||
|
||||
## Walls
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Wall construction | As built / measured U | `walls` = "Average thermal transmittance 0.19 W/m²K" |
|
||||
| Wall U-value | **0.19 W/m²K** | External Wall 1, `wall_type` 2 |
|
||||
| Party wall | **Present — 2 party walls, U = 0** | `wall_type` 4, areas 21.02 + 15.98 m² (Elmhurst "Party wall" = adiabatic, no heat loss) |
|
||||
|
||||
## Roofs
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Roof | **None / other premises above** | `roofs` = "(other premises above)" → 0 heat loss (flat below another dwelling) |
|
||||
|
||||
## Floors
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Floor | As built / measured U | `floors` = "Average thermal transmittance 0.17 W/m²K" |
|
||||
| Floor U-value | **0.17 W/m²K** | ground floor of the flat |
|
||||
|
||||
## Openings — Windows
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Glazing type | High performance / triple or advanced double | `windows` = "High performance glazing", glazing_type 6, 100 % multiple glazed |
|
||||
| Window U-value | **1.4 W/m²K** | joined opening-type U |
|
||||
| Glazed area | as measured | 4 openings totalling ≈ 14.7 m² (W1 0.91×2.24, W2 1.58×2.24, W3+W4 7.08×1.0, W5 0.91×2.24); orientations NE/NW |
|
||||
| Doors | **none** | `door_count` 0 (flat entrance internal / no external door lodged) |
|
||||
|
||||
## Ventilation & Lighting
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Ventilation type | **MEV (mechanical extract)** | `ventilation_type` 8; PCDB index **500167**, duct type 2 (rigid), insulated |
|
||||
| Air permeability | **3.2 m³/h·m² (as tested)** | pressure test = yes |
|
||||
| Wet rooms | 2 | |
|
||||
| Sheltered sides | 2 | |
|
||||
| Lighting | **100 % low-energy** | 10 of 10 fixed outlets low-energy |
|
||||
|
||||
## Space Heating — Main Heating 1
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Main heat source | **Room heaters, electric** | `main_heating` desc; SAP code **691**, category 10, fuel 39 (electricity) |
|
||||
| Emitter | n/a (direct-acting electric) | emitter_temperature "NA" |
|
||||
| Main heating fraction | 1.0 | single main |
|
||||
| Controls | **Programmer + appliance thermostats** | `main_heating_controls`; control code 2603 |
|
||||
| Secondary heating | **None** | `secondary_heating` = None |
|
||||
|
||||
## Space Heating — Meters
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Electricity tariff / meter | **Standard (single rate)** | `electricity_tariff` 1 — **NOT** Economy 7, so the off-peak over-rating bug does not apply here |
|
||||
|
||||
## Water Heating — **Community Hot Water** (the reconciliation target)
|
||||
| Elmhurst field | Value | Notes |
|
||||
|---|---|---|
|
||||
| Water heating type | **Community / communal heat network** | `water_heating_code` **950** = water-only heat network; `hot_water` desc "Community scheme" |
|
||||
| Community use | **Water heating only** | `community_heating_use` 2 (space heat is NOT on the network) |
|
||||
| Heat source 1 | **Heat pump**, **90 %** heat fraction, **efficiency 324 %** (COP 3.24) | `heat_source_type` 3, `fuel_type` 41, `heat_efficiency` 324, `heat_fraction` 0.9 |
|
||||
| Heat source 2 | **Boiler**, **10 %** heat fraction, efficiency **100 %** | `heat_source_type` 2, `fuel_type` 41, `heat_fraction` 0.1 |
|
||||
| Distribution loss / type | **Type 3** | `community_heating_distribution_type` 3 |
|
||||
| Charging linked to use | **Yes** | `charging_linked_to_heat_use` true |
|
||||
| Cylinder in dwelling | **No** | `is_community_heating_cylinder_in_dwelling` false — no in-dwelling store |
|
||||
| (cross-check) lodged DHW cost | **£147/yr** | this is the figure the correct build should land near |
|
||||
|
||||
## Anchors to check against Elmhurst output
|
||||
| Quantity | Lodged (cert) | Our engine (buggy) |
|
||||
|---|---|---|
|
||||
| SAP | **81 B** | 67 D |
|
||||
| Heating cost | £374 | ~£? (space-heat electric) |
|
||||
| **Hot-water cost** | **£147** | **~£660 (raw electric — the bug)** |
|
||||
| Lighting cost | £64 | — |
|
||||
| RHI space / water demand | 1,186 / 1,909 kWh | space 1,039 / DHW 2,675 kWh |
|
||||
|
||||
---
|
||||
|
||||
## Fields to clear in Elmhurst (do NOT map)
|
||||
| Elmhurst page · field | Set to | Why absent |
|
||||
|---|---|---|
|
||||
| Property Description · 1st–4th Extension age band | (blank) | single building part "Main Dwelling", no extensions |
|
||||
| Property Description · Room-in-Roof | (blank) | ground-floor flat, no room-in-roof |
|
||||
| Dimensions · Room(s)-in-Roof area | (blank, not 0) | ditto |
|
||||
| Dimensions · 1st–4th Ext. sub-tabs | 0 / blank | one building part |
|
||||
| Roofs · roof area / U | none | "(other premises above)" — flat below another dwelling |
|
||||
| Openings · Doors | none | `door_count` 0 |
|
||||
| Openings · surplus window rows | delete beyond the 4 lodged | only 4 openings lodged |
|
||||
| Space Heating · Main Heating 2 | none | single main |
|
||||
| Space Heating · Secondary heating | none | `secondary_heating` None |
|
||||
| **Water Heating · in-dwelling cylinder / immersion** | **none** | `has_hot_water_cylinder` false; DHW is the community network, no local store |
|
||||
| Water Heating · Solar water heating / WWHRS / FGHRS | none | not lodged (`solar_water_heating` false; `instantaneous_wwhrs` is room-count metadata, not a device) |
|
||||
| New Technologies · PV / Wind / Hydro | none | none lodged |
|
||||
</content>
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,370 @@
|
|||
{
|
||||
"uprn": 10094112770,
|
||||
"roofs": [
|
||||
{
|
||||
"description": "(other premises above)",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"description": "Average thermal transmittance 0.19 W/m\u00b2K",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"floors": [
|
||||
{
|
||||
"description": "Average thermal transmittance 0.17 W/m\u00b2K",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"status": "entered",
|
||||
"tenure": 1,
|
||||
"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": "BB10 1BB",
|
||||
"data_type": 2,
|
||||
"hot_water": {
|
||||
"description": "Community scheme",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 5
|
||||
},
|
||||
"post_town": "BURNLEY",
|
||||
"built_form": 3,
|
||||
"created_at": "2025-04-15 09:28:31",
|
||||
"living_area": 22.57,
|
||||
"orientation": 6,
|
||||
"region_code": 19,
|
||||
"report_type": 3,
|
||||
"sap_heating": {
|
||||
"water_heating_code": 950,
|
||||
"main_heating_details": [
|
||||
{
|
||||
"main_fuel_type": 39,
|
||||
"main_heating_code": 691,
|
||||
"emitter_temperature": "NA",
|
||||
"main_heating_number": 1,
|
||||
"main_heating_control": 2603,
|
||||
"main_heating_category": 10,
|
||||
"main_heating_fraction": 1,
|
||||
"main_heating_data_source": 3
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "false",
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"secondary_heating_category": 1,
|
||||
"sap_community_heating_systems": [
|
||||
{
|
||||
"community_heating_use": 2,
|
||||
"community_heat_sources": [
|
||||
{
|
||||
"fuel_type": 41,
|
||||
"heat_fraction": 0.9,
|
||||
"heat_efficiency": 324,
|
||||
"heat_source_type": 3
|
||||
},
|
||||
{
|
||||
"fuel_type": 41,
|
||||
"heat_fraction": 0.1,
|
||||
"heat_efficiency": 100,
|
||||
"heat_source_type": 2
|
||||
}
|
||||
],
|
||||
"charging_linked_to_heat_use": "true",
|
||||
"community_heating_distribution_type": 3,
|
||||
"is_community_heating_cylinder_in_dwelling": "false"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sap_version": 9.92,
|
||||
"schema_type": "SAP-Schema-18.0.0",
|
||||
"uprn_source": "Energy Assessor",
|
||||
"country_code": "ENG",
|
||||
"main_heating": [
|
||||
{
|
||||
"description": "Room heaters, electric",
|
||||
"energy_efficiency_rating": 1,
|
||||
"environmental_efficiency_rating": 2
|
||||
}
|
||||
],
|
||||
"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": "Apartment 4",
|
||||
"address_line_2": "Dovestone Gardens",
|
||||
"address_line_3": "Briercliffe Road",
|
||||
"assessment_date": "2025-04-15",
|
||||
"assessment_type": "SAP",
|
||||
"completion_date": "2025-04-15",
|
||||
"inspection_date": "2025-04-15",
|
||||
"sap_ventilation": {
|
||||
"psv_count": 0,
|
||||
"pressure_test": 1,
|
||||
"wet_rooms_count": 2,
|
||||
"air_permeability": 3.2,
|
||||
"open_flues_count": 0,
|
||||
"ventilation_type": 8,
|
||||
"extract_fans_count": 0,
|
||||
"open_fireplaces_count": 0,
|
||||
"sheltered_sides_count": 2,
|
||||
"flueless_gas_fires_count": 0,
|
||||
"mechanical_vent_duct_type": 2,
|
||||
"mechanical_vent_duct_insulation": 2,
|
||||
"mechanical_ventilation_data_source": 1,
|
||||
"mechanical_vent_system_index_number": 500167,
|
||||
"is_mechanical_vent_approved_installer_scheme": "false"
|
||||
},
|
||||
"design_water_use": 1,
|
||||
"sap_data_version": 9.92,
|
||||
"sap_flat_details": {
|
||||
"level": 1
|
||||
},
|
||||
"total_floor_area": 58,
|
||||
"transaction_type": 6,
|
||||
"conservatory_type": 1,
|
||||
"registration_date": "2025-04-15",
|
||||
"sap_energy_source": {
|
||||
"electricity_tariff": 1,
|
||||
"wind_turbines_count": 0,
|
||||
"wind_turbine_terrain_type": 2,
|
||||
"fixed_lighting_outlets_count": 10,
|
||||
"low_energy_fixed_lighting_outlets_count": 10,
|
||||
"low_energy_fixed_lighting_outlets_percentage": 100
|
||||
},
|
||||
"sap_opening_types": [
|
||||
{
|
||||
"name": "Windows SE SW",
|
||||
"type": 4,
|
||||
"u_value": 1.4,
|
||||
"data_source": 2,
|
||||
"frame_factor": 0.69,
|
||||
"glazing_type": 6,
|
||||
"solar_transmittance": 0.66
|
||||
},
|
||||
{
|
||||
"name": "Windows NE NW",
|
||||
"type": 4,
|
||||
"u_value": 1.4,
|
||||
"data_source": 2,
|
||||
"frame_factor": 0.69,
|
||||
"glazing_type": 6,
|
||||
"solar_transmittance": 0.66
|
||||
}
|
||||
],
|
||||
"secondary_heating": {
|
||||
"description": "None",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"lzc_energy_sources": [
|
||||
13
|
||||
],
|
||||
"sap_building_parts": [
|
||||
{
|
||||
"sap_walls": [
|
||||
{
|
||||
"name": "External Wall 1",
|
||||
"u_value": 0.19,
|
||||
"wall_type": 2,
|
||||
"description": "External Wall 1",
|
||||
"total_wall_area": 37.01,
|
||||
"is_curtain_walling": "false"
|
||||
},
|
||||
{
|
||||
"name": "Party Wall 0",
|
||||
"u_value": 0,
|
||||
"wall_type": 4,
|
||||
"total_wall_area": 21.02
|
||||
},
|
||||
{
|
||||
"name": "Party Wall 0",
|
||||
"u_value": 0,
|
||||
"wall_type": 4,
|
||||
"total_wall_area": 15.98
|
||||
}
|
||||
],
|
||||
"identifier": "Main Dwelling",
|
||||
"overshading": 2,
|
||||
"sap_openings": [
|
||||
{
|
||||
"name": "W1",
|
||||
"type": "Windows NE NW",
|
||||
"width": 0.91,
|
||||
"height": 2.24,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 8
|
||||
},
|
||||
{
|
||||
"name": "W2",
|
||||
"type": "Windows NE NW",
|
||||
"width": 1.58,
|
||||
"height": 2.24,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 8
|
||||
},
|
||||
{
|
||||
"name": "W3+W4",
|
||||
"type": "Windows NE NW",
|
||||
"width": 7.08,
|
||||
"height": 1,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 2
|
||||
},
|
||||
{
|
||||
"name": "W5",
|
||||
"type": "Windows NE NW",
|
||||
"width": 0.91,
|
||||
"height": 2.24,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 2
|
||||
}
|
||||
],
|
||||
"construction_year": 2022,
|
||||
"sap_thermal_bridges": {
|
||||
"thermal_bridges": [
|
||||
{
|
||||
"length": 6.56,
|
||||
"psi_value": 0.3,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E2"
|
||||
},
|
||||
{
|
||||
"length": 6.56,
|
||||
"psi_value": 0.04,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E3"
|
||||
},
|
||||
{
|
||||
"length": 22.4,
|
||||
"psi_value": 0.05,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E4"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0.114,
|
||||
"psi_value_source": 3,
|
||||
"thermal_bridge_type": "E5"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0.07,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E7"
|
||||
},
|
||||
{
|
||||
"length": 2.4,
|
||||
"psi_value": 0.09,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E16"
|
||||
},
|
||||
{
|
||||
"length": 4.8,
|
||||
"psi_value": 0.06,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E18"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0.16,
|
||||
"psi_value_source": 4,
|
||||
"thermal_bridge_type": "P1"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0,
|
||||
"psi_value_source": 4,
|
||||
"thermal_bridge_type": "P3"
|
||||
}
|
||||
],
|
||||
"thermal_bridge_code": 5
|
||||
},
|
||||
"building_part_number": 1,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"storey": 0,
|
||||
"u_value": 0.17,
|
||||
"floor_type": 2,
|
||||
"description": "Heat Loss Floor 1",
|
||||
"storey_height": 2.4,
|
||||
"heat_loss_area": 58.11,
|
||||
"total_floor_area": 58.11
|
||||
}
|
||||
],
|
||||
"thermal_mass_parameter": 250
|
||||
}
|
||||
],
|
||||
"heating_cost_current": {
|
||||
"value": 374,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_current": 1.2,
|
||||
"energy_rating_average": 60,
|
||||
"energy_rating_current": 81,
|
||||
"lighting_cost_current": {
|
||||
"value": 64,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"main_heating_controls": [
|
||||
{
|
||||
"description": "Programmer and appliance thermostats",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "false",
|
||||
"heating_cost_potential": {
|
||||
"value": 374,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"hot_water_cost_current": {
|
||||
"value": 147,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_potential": 1.2,
|
||||
"energy_rating_potential": 81,
|
||||
"lighting_cost_potential": {
|
||||
"value": 64,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"schema_version_original": "18.0.0",
|
||||
"hot_water_cost_potential": {
|
||||
"value": 147,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"is_in_smoke_control_area": "unknown",
|
||||
"renewable_heat_incentive": {
|
||||
"rhi_new_dwelling": {
|
||||
"space_heating": 1186,
|
||||
"water_heating": 1909
|
||||
}
|
||||
},
|
||||
"seller_commission_report": "Y",
|
||||
"energy_consumption_current": 126,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"multiple_glazed_percentage": 100,
|
||||
"calculation_software_version": "4.14r19",
|
||||
"energy_consumption_potential": 126,
|
||||
"environmental_impact_current": 85,
|
||||
"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": 21
|
||||
}
|
||||
|
|
@ -168,6 +168,18 @@ class SapHeating:
|
|||
cylinder_volume_measured_l: Optional[int] = None
|
||||
water_heating_code: Optional[int] = None # TODO: make enum?
|
||||
water_heating_fuel: Optional[int] = None # TODO: make enum?
|
||||
# Water-only community heat network (SAP 10.2 §4.3 / Appendix C). Populated
|
||||
# for full-SAP certs whose DHW is on a communal scheme served by its OWN heat
|
||||
# source (heat pump / boilers / CHP), independent of the space main — i.e.
|
||||
# `water_heating_code` in {950,951,952} with a lodged
|
||||
# `sap_community_heating_systems` entry of `community_heating_use` = water.
|
||||
# None for individually-heated DHW and for space+water community schemes
|
||||
# (those ride the category-6 main's `community_heating_*` fields). The
|
||||
# calculator prices DHW on the network fuel scaled by this heat-source
|
||||
# efficiency (COP×100 for a heat pump) rather than as a direct-electric
|
||||
# immersion cylinder.
|
||||
community_water_heating_fuel: Optional[int] = None
|
||||
community_water_heating_efficiency: Optional[float] = None
|
||||
immersion_heating_type: Optional[Union[int, str]] = None # TODO: make enum?
|
||||
shower_outlets: Optional[ShowerOutlets] = None
|
||||
cylinder_insulation_type: Optional[Union[int, str]] = None
|
||||
|
|
|
|||
|
|
@ -3433,6 +3433,15 @@ def _sap_17_1_heating(schema: SapSchema17_1) -> SapHeating:
|
|||
has_fixed_air_conditioning=sh.has_fixed_air_conditioning == "true",
|
||||
water_heating_code=sh.water_heating_code,
|
||||
water_heating_fuel=sh.water_fuel_type,
|
||||
# D6c: a communal DHW network (`water_heating_code` 950/951/952) carries
|
||||
# its own heat source in `sap_community_heating_systems`, independent of
|
||||
# the space main. Expose its blended heat-source efficiency + fuel so the
|
||||
# calculator prices DHW on the network (heat-pump COP) instead of the
|
||||
# dropped-to-electric-immersion default.
|
||||
community_water_heating_efficiency=_sap_17_1_community_water_efficiency(
|
||||
schema
|
||||
),
|
||||
community_water_heating_fuel=_sap_17_1_community_water_fuel(schema),
|
||||
main_heating_details=[
|
||||
MainHeatingDetail(
|
||||
has_fghrs=False,
|
||||
|
|
@ -3515,6 +3524,53 @@ def _sap_17_1_community_sources(
|
|||
]
|
||||
|
||||
|
||||
# gov-API `community_heating_use`: 1 = space only, 2 = water only, 3 = space +
|
||||
# water. Water DHW is served by any network whose use includes water.
|
||||
_COMMUNITY_USE_SERVES_WATER: Final[frozenset[int]] = frozenset({2, 3})
|
||||
|
||||
|
||||
def _sap_17_1_community_water_sources(
|
||||
schema: SapSchema17_1,
|
||||
) -> List[SapCommunityHeatSource_SAP_17_1]:
|
||||
"""Heat sources of the community networks that serve hot water (use 2 water-
|
||||
only or 3 space+water)."""
|
||||
return [
|
||||
src
|
||||
for system in schema.sap_heating.sap_community_heating_systems or []
|
||||
if system.community_heating_use in _COMMUNITY_USE_SERVES_WATER
|
||||
for src in system.community_heat_sources
|
||||
]
|
||||
|
||||
|
||||
def _sap_17_1_community_water_efficiency(schema: SapSchema17_1) -> Optional[float]:
|
||||
"""Heat-fraction-weighted efficiency (%) of the community DHW network's heat
|
||||
sources, or None when no lodged network serves water. A heat pump's
|
||||
efficiency is its COP×100 (e.g. 324); the network blends its sources by heat
|
||||
fraction — 90% heat pump @ 324% + 10% boiler @ 100% = 301.6%. The calculator
|
||||
divides the DHW heat demand by this to get the network's fuel input, so a
|
||||
heat-pump network costs a fraction of a direct-electric immersion cylinder."""
|
||||
sources = _sap_17_1_community_water_sources(schema)
|
||||
total_fraction = sum(src.heat_fraction or 0.0 for src in sources)
|
||||
if total_fraction <= 0.0:
|
||||
return None
|
||||
weighted = sum(
|
||||
(src.heat_efficiency or 0.0) * (src.heat_fraction or 0.0) for src in sources
|
||||
)
|
||||
return weighted / total_fraction
|
||||
|
||||
|
||||
def _sap_17_1_community_water_fuel(schema: SapSchema17_1) -> Optional[int]:
|
||||
"""SAP Table 12 community fuel of the DHW network — the dominant heat source
|
||||
by heat fraction, mirroring `_sap_17_1_community_fuel` for the space main.
|
||||
None when no lodged network serves water."""
|
||||
sources = [
|
||||
src for src in _sap_17_1_community_water_sources(schema) if src.fuel_type
|
||||
]
|
||||
if not sources:
|
||||
return None
|
||||
return max(sources, key=lambda s: s.heat_fraction or 0.0).fuel_type
|
||||
|
||||
|
||||
def _sap_17_1_community_code(schema: SapSchema17_1) -> Optional[int]:
|
||||
"""SAP 10.2 Table 4a community main-heating code from the lodged heat-source
|
||||
mix, or None when no community system / no recognised source is present.
|
||||
|
|
|
|||
|
|
@ -1048,3 +1048,49 @@ class TestFullSapSchema16xNoFloorDimensions:
|
|||
ValueError, match="Wardalls Grove.*SE14 5FB.*sap_floor_dimensions"
|
||||
):
|
||||
EpcPropertyDataMapper.from_api_response(data)
|
||||
|
||||
|
||||
class TestSapWaterOnlyCommunityDhw:
|
||||
"""Full-SAP water-only community DHW (`water_heating_code` 950/951/952,
|
||||
`community_heating_use` = water): the DHW is served by a communal heat
|
||||
network with its OWN heat source, independent of the space main. The mapper
|
||||
must expose the network's heat-source efficiency + fuel so the calculator
|
||||
prices DHW on the network (heat-pump COP) instead of dropping it and pricing
|
||||
a direct-electric immersion cylinder.
|
||||
|
||||
Fixture `sap_18_0_water_community_hp.json` is the real Dovestone Gardens
|
||||
Apt 4 cert (9556-3047-3304-5355-1200): electric room heaters for space heat
|
||||
+ a communal heat-pump DHW network (90% heat pump @ 324% + 10% boiler @
|
||||
100%, fuel 41). Accredited Elmhurst prices DHW at £78 (1839 kWh @ 4.24p);
|
||||
the engine was pricing it as direct electric (~£353).
|
||||
"""
|
||||
|
||||
def test_maps_community_water_heat_source_efficiency(self) -> None:
|
||||
# Arrange — communal DHW network: 90% heat pump @ 324% + 10% boiler @ 100%.
|
||||
raw = load("sap_18_0_water_community_hp.json")
|
||||
|
||||
# Act
|
||||
epc = EpcPropertyDataMapper.from_api_response(raw)
|
||||
|
||||
# Assert — heat-fraction-weighted network efficiency (0.9×324 + 0.1×100
|
||||
# = 301.6%), NOT dropped to None (which the calculator reads as a
|
||||
# direct-electric immersion cylinder).
|
||||
assert epc is not None
|
||||
assert epc.sap_heating.community_water_heating_efficiency == pytest.approx(
|
||||
301.6
|
||||
)
|
||||
|
||||
def test_prices_community_dhw_on_the_heat_pump_network(self) -> None:
|
||||
# Arrange — communal heat-pump DHW; the space main is direct electric.
|
||||
from domain.sap10_calculator.calculator import Sap10Calculator
|
||||
|
||||
raw = load("sap_18_0_water_community_hp.json")
|
||||
epc = EpcPropertyDataMapper.from_api_response(raw)
|
||||
|
||||
# Act
|
||||
result = Sap10Calculator().calculate(epc)
|
||||
|
||||
# Assert — DHW bills on the community heat-pump fuel (SAP Table 32 code
|
||||
# 41 @ 4.24 p/kWh, COP baked in), NOT the direct-electric main (code 39
|
||||
# @ 13.19 p/kWh) it was defaulting to.
|
||||
assert result.hot_water_fuel_code == 41
|
||||
|
|
|
|||
370
datatypes/epc/schema/tests/fixtures/sap_18_0_water_community_hp.json
vendored
Normal file
370
datatypes/epc/schema/tests/fixtures/sap_18_0_water_community_hp.json
vendored
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
{
|
||||
"uprn": 10094112770,
|
||||
"roofs": [
|
||||
{
|
||||
"description": "(other premises above)",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"description": "Average thermal transmittance 0.19 W/m\u00b2K",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"floors": [
|
||||
{
|
||||
"description": "Average thermal transmittance 0.17 W/m\u00b2K",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
}
|
||||
],
|
||||
"status": "entered",
|
||||
"tenure": 1,
|
||||
"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": "BB10 1BB",
|
||||
"data_type": 2,
|
||||
"hot_water": {
|
||||
"description": "Community scheme",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 5
|
||||
},
|
||||
"post_town": "BURNLEY",
|
||||
"built_form": 3,
|
||||
"created_at": "2025-04-15 09:28:31",
|
||||
"living_area": 22.57,
|
||||
"orientation": 6,
|
||||
"region_code": 19,
|
||||
"report_type": 3,
|
||||
"sap_heating": {
|
||||
"water_heating_code": 950,
|
||||
"main_heating_details": [
|
||||
{
|
||||
"main_fuel_type": 39,
|
||||
"main_heating_code": 691,
|
||||
"emitter_temperature": "NA",
|
||||
"main_heating_number": 1,
|
||||
"main_heating_control": 2603,
|
||||
"main_heating_category": 10,
|
||||
"main_heating_fraction": 1,
|
||||
"main_heating_data_source": 3
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "false",
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"secondary_heating_category": 1,
|
||||
"sap_community_heating_systems": [
|
||||
{
|
||||
"community_heating_use": 2,
|
||||
"community_heat_sources": [
|
||||
{
|
||||
"fuel_type": 41,
|
||||
"heat_fraction": 0.9,
|
||||
"heat_efficiency": 324,
|
||||
"heat_source_type": 3
|
||||
},
|
||||
{
|
||||
"fuel_type": 41,
|
||||
"heat_fraction": 0.1,
|
||||
"heat_efficiency": 100,
|
||||
"heat_source_type": 2
|
||||
}
|
||||
],
|
||||
"charging_linked_to_heat_use": "true",
|
||||
"community_heating_distribution_type": 3,
|
||||
"is_community_heating_cylinder_in_dwelling": "false"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sap_version": 9.92,
|
||||
"schema_type": "SAP-Schema-18.0.0",
|
||||
"uprn_source": "Energy Assessor",
|
||||
"country_code": "ENG",
|
||||
"main_heating": [
|
||||
{
|
||||
"description": "Room heaters, electric",
|
||||
"energy_efficiency_rating": 1,
|
||||
"environmental_efficiency_rating": 2
|
||||
}
|
||||
],
|
||||
"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": "Apartment 4",
|
||||
"address_line_2": "Dovestone Gardens",
|
||||
"address_line_3": "Briercliffe Road",
|
||||
"assessment_date": "2025-04-15",
|
||||
"assessment_type": "SAP",
|
||||
"completion_date": "2025-04-15",
|
||||
"inspection_date": "2025-04-15",
|
||||
"sap_ventilation": {
|
||||
"psv_count": 0,
|
||||
"pressure_test": 1,
|
||||
"wet_rooms_count": 2,
|
||||
"air_permeability": 3.2,
|
||||
"open_flues_count": 0,
|
||||
"ventilation_type": 8,
|
||||
"extract_fans_count": 0,
|
||||
"open_fireplaces_count": 0,
|
||||
"sheltered_sides_count": 2,
|
||||
"flueless_gas_fires_count": 0,
|
||||
"mechanical_vent_duct_type": 2,
|
||||
"mechanical_vent_duct_insulation": 2,
|
||||
"mechanical_ventilation_data_source": 1,
|
||||
"mechanical_vent_system_index_number": 500167,
|
||||
"is_mechanical_vent_approved_installer_scheme": "false"
|
||||
},
|
||||
"design_water_use": 1,
|
||||
"sap_data_version": 9.92,
|
||||
"sap_flat_details": {
|
||||
"level": 1
|
||||
},
|
||||
"total_floor_area": 58,
|
||||
"transaction_type": 6,
|
||||
"conservatory_type": 1,
|
||||
"registration_date": "2025-04-15",
|
||||
"sap_energy_source": {
|
||||
"electricity_tariff": 1,
|
||||
"wind_turbines_count": 0,
|
||||
"wind_turbine_terrain_type": 2,
|
||||
"fixed_lighting_outlets_count": 10,
|
||||
"low_energy_fixed_lighting_outlets_count": 10,
|
||||
"low_energy_fixed_lighting_outlets_percentage": 100
|
||||
},
|
||||
"sap_opening_types": [
|
||||
{
|
||||
"name": "Windows SE SW",
|
||||
"type": 4,
|
||||
"u_value": 1.4,
|
||||
"data_source": 2,
|
||||
"frame_factor": 0.69,
|
||||
"glazing_type": 6,
|
||||
"solar_transmittance": 0.66
|
||||
},
|
||||
{
|
||||
"name": "Windows NE NW",
|
||||
"type": 4,
|
||||
"u_value": 1.4,
|
||||
"data_source": 2,
|
||||
"frame_factor": 0.69,
|
||||
"glazing_type": 6,
|
||||
"solar_transmittance": 0.66
|
||||
}
|
||||
],
|
||||
"secondary_heating": {
|
||||
"description": "None",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"lzc_energy_sources": [
|
||||
13
|
||||
],
|
||||
"sap_building_parts": [
|
||||
{
|
||||
"sap_walls": [
|
||||
{
|
||||
"name": "External Wall 1",
|
||||
"u_value": 0.19,
|
||||
"wall_type": 2,
|
||||
"description": "External Wall 1",
|
||||
"total_wall_area": 37.01,
|
||||
"is_curtain_walling": "false"
|
||||
},
|
||||
{
|
||||
"name": "Party Wall 0",
|
||||
"u_value": 0,
|
||||
"wall_type": 4,
|
||||
"total_wall_area": 21.02
|
||||
},
|
||||
{
|
||||
"name": "Party Wall 0",
|
||||
"u_value": 0,
|
||||
"wall_type": 4,
|
||||
"total_wall_area": 15.98
|
||||
}
|
||||
],
|
||||
"identifier": "Main Dwelling",
|
||||
"overshading": 2,
|
||||
"sap_openings": [
|
||||
{
|
||||
"name": "W1",
|
||||
"type": "Windows NE NW",
|
||||
"width": 0.91,
|
||||
"height": 2.24,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 8
|
||||
},
|
||||
{
|
||||
"name": "W2",
|
||||
"type": "Windows NE NW",
|
||||
"width": 1.58,
|
||||
"height": 2.24,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 8
|
||||
},
|
||||
{
|
||||
"name": "W3+W4",
|
||||
"type": "Windows NE NW",
|
||||
"width": 7.08,
|
||||
"height": 1,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 2
|
||||
},
|
||||
{
|
||||
"name": "W5",
|
||||
"type": "Windows NE NW",
|
||||
"width": 0.91,
|
||||
"height": 2.24,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 2
|
||||
}
|
||||
],
|
||||
"construction_year": 2022,
|
||||
"sap_thermal_bridges": {
|
||||
"thermal_bridges": [
|
||||
{
|
||||
"length": 6.56,
|
||||
"psi_value": 0.3,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E2"
|
||||
},
|
||||
{
|
||||
"length": 6.56,
|
||||
"psi_value": 0.04,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E3"
|
||||
},
|
||||
{
|
||||
"length": 22.4,
|
||||
"psi_value": 0.05,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E4"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0.114,
|
||||
"psi_value_source": 3,
|
||||
"thermal_bridge_type": "E5"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0.07,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E7"
|
||||
},
|
||||
{
|
||||
"length": 2.4,
|
||||
"psi_value": 0.09,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E16"
|
||||
},
|
||||
{
|
||||
"length": 4.8,
|
||||
"psi_value": 0.06,
|
||||
"psi_value_source": 2,
|
||||
"thermal_bridge_type": "E18"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0.16,
|
||||
"psi_value_source": 4,
|
||||
"thermal_bridge_type": "P1"
|
||||
},
|
||||
{
|
||||
"length": 15.42,
|
||||
"psi_value": 0,
|
||||
"psi_value_source": 4,
|
||||
"thermal_bridge_type": "P3"
|
||||
}
|
||||
],
|
||||
"thermal_bridge_code": 5
|
||||
},
|
||||
"building_part_number": 1,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"storey": 0,
|
||||
"u_value": 0.17,
|
||||
"floor_type": 2,
|
||||
"description": "Heat Loss Floor 1",
|
||||
"storey_height": 2.4,
|
||||
"heat_loss_area": 58.11,
|
||||
"total_floor_area": 58.11
|
||||
}
|
||||
],
|
||||
"thermal_mass_parameter": 250
|
||||
}
|
||||
],
|
||||
"heating_cost_current": {
|
||||
"value": 374,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_current": 1.2,
|
||||
"energy_rating_average": 60,
|
||||
"energy_rating_current": 81,
|
||||
"lighting_cost_current": {
|
||||
"value": 64,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"main_heating_controls": [
|
||||
{
|
||||
"description": "Programmer and appliance thermostats",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "false",
|
||||
"heating_cost_potential": {
|
||||
"value": 374,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"hot_water_cost_current": {
|
||||
"value": 147,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_potential": 1.2,
|
||||
"energy_rating_potential": 81,
|
||||
"lighting_cost_potential": {
|
||||
"value": 64,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"schema_version_original": "18.0.0",
|
||||
"hot_water_cost_potential": {
|
||||
"value": 147,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"is_in_smoke_control_area": "unknown",
|
||||
"renewable_heat_incentive": {
|
||||
"rhi_new_dwelling": {
|
||||
"space_heating": 1186,
|
||||
"water_heating": 1909
|
||||
}
|
||||
},
|
||||
"seller_commission_report": "Y",
|
||||
"energy_consumption_current": 126,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"multiple_glazed_percentage": 100,
|
||||
"calculation_software_version": "4.14r19",
|
||||
"energy_consumption_potential": 126,
|
||||
"environmental_impact_current": 85,
|
||||
"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": 21
|
||||
}
|
||||
|
|
@ -1943,6 +1943,18 @@ def _water_heating_fuel_code(epc: EpcPropertyData) -> Optional[int]:
|
|||
no fuel_type lodged, so the old fallback resolved to None and CO2/
|
||||
PE/cost lookups returned defaults instead of the gas-combi values.
|
||||
"""
|
||||
# A water-ONLY community scheme (WHC 950/951/952) is served by its own heat
|
||||
# network, independent of the space main. Bill DHW on the network's SAP
|
||||
# Table 12 community fuel (e.g. 41 = heat from electric heat pump @ 4.24
|
||||
# p/kWh — the COP is already priced into the community row) rather than
|
||||
# defaulting to the space main's fuel, which for a direct-electric main
|
||||
# mis-billed communal heat-pump DHW at the 13.19p standard-electric rate.
|
||||
community_water_fuel = epc.sap_heating.community_water_heating_fuel
|
||||
if (
|
||||
epc.sap_heating.water_heating_code in _WATER_HEAT_NETWORK_ONLY_CODES
|
||||
and community_water_fuel is not None
|
||||
):
|
||||
return community_water_fuel
|
||||
if epc.sap_heating.water_heating_fuel:
|
||||
fuel = epc.sap_heating.water_heating_fuel
|
||||
# When DHW is on a heat network, the colliding community fuels
|
||||
|
|
|
|||
|
|
@ -163,6 +163,12 @@ class EpcPropertyModel(SQLModel, table=True):
|
|||
)
|
||||
heating_water_heating_code: Optional[int] = Field(default=None)
|
||||
heating_water_heating_fuel: Optional[int] = Field(default=None)
|
||||
# #1711: the water-only community heat network serving DHW (WHC 950/951/952).
|
||||
# Read by cert_to_inputs (`_water_heating_fuel_code`) to bill hot water on the
|
||||
# network fuel; dropping them re-prices heat-pump DHW as direct electric
|
||||
# (Dovestone: 80 → 67 SAP). Efficiency is the heat-fraction-weighted COP × 100.
|
||||
heating_community_water_heating_fuel: Optional[int] = Field(default=None)
|
||||
heating_community_water_heating_efficiency: Optional[float] = Field(default=None)
|
||||
heating_immersion_heating_type: Optional[Union[int, str]] = Field(
|
||||
default=None, sa_column=Column(JSONB, nullable=True)
|
||||
)
|
||||
|
|
@ -363,6 +369,10 @@ class EpcPropertyModel(SQLModel, table=True):
|
|||
heating_cylinder_size=h.cylinder_size,
|
||||
heating_water_heating_code=h.water_heating_code,
|
||||
heating_water_heating_fuel=h.water_heating_fuel,
|
||||
heating_community_water_heating_fuel=h.community_water_heating_fuel,
|
||||
heating_community_water_heating_efficiency=(
|
||||
h.community_water_heating_efficiency
|
||||
),
|
||||
heating_immersion_heating_type=h.immersion_heating_type,
|
||||
heating_cylinder_insulation_type=h.cylinder_insulation_type,
|
||||
heating_cylinder_thermostat=h.cylinder_thermostat,
|
||||
|
|
|
|||
|
|
@ -1121,6 +1121,10 @@ class EpcPostgresRepository(EpcRepository):
|
|||
cylinder_size=p.heating_cylinder_size,
|
||||
water_heating_code=p.heating_water_heating_code,
|
||||
water_heating_fuel=p.heating_water_heating_fuel,
|
||||
community_water_heating_fuel=p.heating_community_water_heating_fuel,
|
||||
community_water_heating_efficiency=(
|
||||
p.heating_community_water_heating_efficiency
|
||||
),
|
||||
immersion_heating_type=p.heating_immersion_heating_type,
|
||||
shower_outlets=shower_outlets,
|
||||
cylinder_insulation_type=p.heating_cylinder_insulation_type,
|
||||
|
|
|
|||
|
|
@ -1392,6 +1392,44 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = (
|
|||
cert_num="8059-6020-9429-4133-0996",
|
||||
sap_score=72,
|
||||
),
|
||||
# UPRN 10094112770 → cert 9556-3047-3304-5355-1200. SAP-Schema-18.0.0 — a
|
||||
# FULL-SAP cert (2025 new-build GROUND-FLOOR FLAT, Dovestone Gardens,
|
||||
# Burnley, TFA 58 m²). Direct-electric room heaters for space heat + a
|
||||
# WATER-ONLY communal heat network for DHW (water_heating_code 950,
|
||||
# community_heating_use 2; network = 90% heat pump @ COP 3.24 + 10% boiler,
|
||||
# fuel 41). Lodged 81 (B); engine now produces 80.
|
||||
#
|
||||
# This cert IS the water-only community-DHW fix. The gov-API mapper dropped
|
||||
# `sap_community_heating_systems` for a non-community (category-10) main, so
|
||||
# the calculator priced communal heat-pump DHW as a DIRECT-ELECTRIC immersion
|
||||
# cylinder (2675 kWh @ 13.19p ≈ £353) and pinned SAP at 67 (D). Mapping the
|
||||
# network's fuel onto the DHW cascade (SAP Table 32 code 41 = heat from
|
||||
# electric heat pump @ 4.24 p/kWh, COP priced into the row) bills DHW at £113
|
||||
# and lifts SAP 67 → 80.
|
||||
#
|
||||
# Built in Elmhurst RdSAP10 on the lodged inputs (evidence saved:
|
||||
# elmhurst_summary.pdf / elmhurst_worksheet.pdf). A FAITHFULLY-built Elmhurst
|
||||
# reproduces the engine EXACTLY: worksheet SAP **80 = engine 80**. The
|
||||
# calculator is validated line-for-line — fabric heat loss 41.2 vs 41.6 W/K,
|
||||
# community DHW on fuel 41 @ 4.24p, ventilation matched once the cert's inputs
|
||||
# are keyed in.
|
||||
#
|
||||
# Reaching that faithful build meant correcting four data-entry artefacts that
|
||||
# the shared reusable assessment carried, each of which had suppressed the
|
||||
# accredited score below the engine (67→80 over the campaign): a phantom
|
||||
# secondary gas fire (SAP 603) → +5; the MVHR unit 500167 initially unset → +4;
|
||||
# air permeability AP50 keyed at 4.88 vs the cert's tested 3.2 → +1; and a
|
||||
# phantom "open flue attached to other heater" (1 vs the cert's 0) inflating
|
||||
# infiltration (8) → +5. With all four aligned to the certificate the two
|
||||
# engines converge on 80 — so the earlier apparent gaps were Elmhurst build
|
||||
# fidelity, NOT calculator error. PINNED TO THE OBSERVED 80 (lodged 81 B),
|
||||
# mapping deliberately untuned.
|
||||
RealCertExpectation(
|
||||
schema="SAP-Schema-18.0.0",
|
||||
sample="uprn_10094112770",
|
||||
cert_num="9556-3047-3304-5355-1200",
|
||||
sap_score=80,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ def test_calculator_read_fields_round_trip(db_engine: Engine) -> None:
|
|||
heating,
|
||||
main_heating_details=[mh0, *heating.main_heating_details[1:]],
|
||||
cylinder_volume_measured_l=180,
|
||||
community_water_heating_fuel=41,
|
||||
community_water_heating_efficiency=324.0,
|
||||
)
|
||||
original = replace(
|
||||
original,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue