mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Carry full-SAP measured fabric U-value descriptions into the domain model 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c3fd9a6872
commit
0eaf87b106
3 changed files with 62 additions and 5 deletions
|
|
@ -43,7 +43,10 @@ from datatypes.epc.schema.rdsap_schema_17_1 import (
|
|||
RdSapSchema17_1,
|
||||
EnergyElement as EnergyElement_17_1,
|
||||
)
|
||||
from datatypes.epc.schema.sap_schema_17_1 import SapSchema17_1
|
||||
from datatypes.epc.schema.sap_schema_17_1 import (
|
||||
SapSchema17_1,
|
||||
EnergyElement as EnergyElement_SAP_17_1,
|
||||
)
|
||||
from datatypes.epc.schema.rdsap_schema_18_0 import (
|
||||
RdSapSchema18_0,
|
||||
EnergyElement as EnergyElement_18_0,
|
||||
|
|
@ -654,9 +657,14 @@ class EpcPropertyDataMapper:
|
|||
cfl_fixed_lighting_bulbs_count=0,
|
||||
led_fixed_lighting_bulbs_count=0,
|
||||
incandescent_fixed_lighting_bulbs_count=0,
|
||||
roofs=[],
|
||||
walls=[],
|
||||
floors=[],
|
||||
# D4: full SAP lodges the measured U as text in the element
|
||||
# description ("Average thermal transmittance X W/m²K"); carry it
|
||||
# through so u_wall/u_floor/u_roof parse it instead of re-deriving
|
||||
# from a fabricated age band. "(other premises above/below)"
|
||||
# sentinels survive untouched (bordering dwelling → no heat loss).
|
||||
roofs=EpcPropertyDataMapper._map_energy_elements(schema.roofs),
|
||||
walls=EpcPropertyDataMapper._map_energy_elements(schema.walls),
|
||||
floors=EpcPropertyDataMapper._map_energy_elements(schema.floors),
|
||||
main_heating=[],
|
||||
sap_windows=[],
|
||||
sap_building_parts=[],
|
||||
|
|
@ -2219,6 +2227,7 @@ class EpcPropertyDataMapper:
|
|||
EnergyElement_20_0,
|
||||
EnergyElement_21_0,
|
||||
EnergyElement_21_0_1,
|
||||
EnergyElement_SAP_17_1,
|
||||
],
|
||||
) -> EnergyElement:
|
||||
description = (
|
||||
|
|
@ -2243,6 +2252,7 @@ class EpcPropertyDataMapper:
|
|||
EnergyElement_20_0,
|
||||
EnergyElement_21_0,
|
||||
EnergyElement_21_0_1,
|
||||
EnergyElement_SAP_17_1,
|
||||
]
|
||||
],
|
||||
) -> List[EnergyElement]:
|
||||
|
|
|
|||
|
|
@ -75,3 +75,34 @@ class TestFromSapSchema17_1Tracer:
|
|||
# Assert
|
||||
assert result.uprn == 10092973954
|
||||
assert result.total_floor_area_m2 == 68.0
|
||||
|
||||
|
||||
class TestFromSapSchema17_1FabricDescriptions:
|
||||
"""Slice 3 (D4): the measured-U fabric descriptions flow through to
|
||||
epc.walls/floors/roofs so the engine's u_wall/u_floor/u_roof can parse
|
||||
'Average thermal transmittance X W/m²K' instead of re-deriving from a band."""
|
||||
|
||||
@pytest.fixture
|
||||
def sample(self) -> EpcPropertyData:
|
||||
schema = from_dict(SapSchema17_1, load("sap_17_1.json"))
|
||||
return EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
|
||||
def test_wall_description_carries_measured_u(self, sample: EpcPropertyData) -> None:
|
||||
assert sample.walls[0].description == "Average thermal transmittance 0.17 W/m²K"
|
||||
|
||||
def test_floor_description_carries_measured_u(self, sample: EpcPropertyData) -> None:
|
||||
assert sample.floors[0].description == "Average thermal transmittance 0.13 W/m²K"
|
||||
|
||||
def test_roof_description_carries_other_premises(
|
||||
self, sample: EpcPropertyData
|
||||
) -> None:
|
||||
# A ground-floor flat with premises above → no roof heat loss; the
|
||||
# "(other premises above)" sentinel must survive so the engine treats
|
||||
# it as internal rather than parsing a measured U.
|
||||
assert sample.roofs[0].description == "(other premises above)"
|
||||
|
||||
@pytest.mark.parametrize("fixture", _ALL_FIXTURES)
|
||||
def test_every_fixture_has_wall_descriptions(self, fixture: str) -> None:
|
||||
schema = from_dict(SapSchema17_1, load(fixture))
|
||||
result = EpcPropertyDataMapper.from_sap_schema_17_1(schema)
|
||||
assert result.walls and result.walls[0].description
|
||||
|
|
|
|||
|
|
@ -10,11 +10,24 @@ raises only on a missing *required* field.
|
|||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Union
|
||||
from typing import List, Union
|
||||
|
||||
from .common import DescriptionV1
|
||||
|
||||
|
||||
@dataclass
|
||||
class EnergyElement:
|
||||
"""A fabric/system element with its lodged description. On full SAP the
|
||||
`description` carries the measured U-value as text, e.g. "Average thermal
|
||||
transmittance 0.17 W/m²K" (parsed downstream by u_wall/u_floor/u_roof),
|
||||
or "(other premises above/below)" for an element bordering another
|
||||
dwelling (no heat loss)."""
|
||||
|
||||
description: Union[str, DescriptionV1]
|
||||
energy_efficiency_rating: int
|
||||
environmental_efficiency_rating: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class SapSchema17_1:
|
||||
uprn: int
|
||||
|
|
@ -30,3 +43,6 @@ class SapSchema17_1:
|
|||
inspection_date: str
|
||||
has_hot_water_cylinder: str
|
||||
has_fixed_air_conditioning: str
|
||||
roofs: List[EnergyElement]
|
||||
walls: List[EnergyElement]
|
||||
floors: List[EnergyElement]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue