flatten sap property to excel row object 🟥

This commit is contained in:
Daniel Roth 2026-04-15 08:21:14 +00:00
parent 3ae2ed1207
commit fcceeb2736
2 changed files with 97 additions and 2 deletions

View file

@ -1,4 +1,8 @@
from backend.ecmk_fetcher.xml_processor import SapPropertyDetails, parse_rdsap
from backend.ecmk_fetcher.xml_processor import (
SapPropertyDetails,
flatten_sap_property,
parse_rdsap,
)
SAMPLE_XML = """<RdSAP-Report xmlns="https://epbr.digital.communities.gov.uk/xsd/rdsap">
@ -84,6 +88,39 @@ SAMPLE_XML = """<RdSAP-Report xmlns="https://epbr.digital.communities.gov.uk/xsd
"""
NO_ROOF_XML = """<RdSAP-Report xmlns="https://epbr.digital.communities.gov.uk/xsd/rdsap">
<Report-Header>
<Property>
<Address>
<Address-Line-1>5</Address-Line-1>
<Post-Town>Somewhere</Post-Town>
<Postcode>XY1 2AB</Postcode>
</Address>
</Property>
</Report-Header>
<SAP-Data>
<SAP-Property-Details>
<Property-Type>0</Property-Type>
<SAP-Building-Parts>
<SAP-Building-Part>
<Identifier>Main Dwelling</Identifier>
<SAP-Floor-Dimensions>
<SAP-Floor-Dimension>
<Heat-Loss-Perimeter quantity="metres">10.0</Heat-Loss-Perimeter>
<Room-Height quantity="metres">2.5</Room-Height>
<Total-Floor-Area quantity="square metres">50.0</Total-Floor-Area>
<Floor>0</Floor>
<Party-Wall-Length>3.0</Party-Wall-Length>
</SAP-Floor-Dimension>
</SAP-Floor-Dimensions>
</SAP-Building-Part>
</SAP-Building-Parts>
</SAP-Property-Details>
</SAP-Data>
</RdSAP-Report>
"""
def test_parse_rdsap_contract():
# arrange + act
result: SapPropertyDetails = parse_rdsap(SAMPLE_XML)
@ -132,3 +169,57 @@ def test_parse_rdsap_contract():
},
],
}
def test_flatten_full():
# Two building parts; Main Dwelling has two floors + full roof,
# Extension has one floor + partial roof (no thickness)
# arrange
details: SapPropertyDetails = parse_rdsap(SAMPLE_XML)
# act
result = flatten_sap_property(details)
# assert
assert result == {
"address": "1, Fake Avenue, Random, AB24 5CD",
"property_type": "House",
"main_dwelling_floor_1_area_m2": 43.61,
"main_dwelling_floor_1_height_m": 2.46,
"main_dwelling_floor_1_heat_loss_perimeter_m": 25.31,
"main_dwelling_floor_1_party_wall_length_m": 0.0,
"main_dwelling_floor_2_area_m2": 42.33,
"main_dwelling_floor_2_height_m": 2.44,
"main_dwelling_floor_2_heat_loss_perimeter_m": 26.16,
"main_dwelling_floor_2_party_wall_length_m": 0.0,
"main_dwelling_roof_construction": 4,
"main_dwelling_roof_insulation_location": 2,
"main_dwelling_roof_insulation_thickness_mm": 100.0,
"extension_floor_1_area_m2": 4.46,
"extension_floor_1_height_m": 2.24,
"extension_floor_1_heat_loss_perimeter_m": 6.85,
"extension_floor_1_party_wall_length_m": 0.0,
"extension_roof_construction": 8,
"extension_roof_insulation_location": 7,
}
def test_flatten_no_roof():
# Single building part with no roof — roof keys must be absent entirely
# arrange
details: SapPropertyDetails = parse_rdsap(NO_ROOF_XML)
# act
result = flatten_sap_property(details)
# assert
assert result == {
"address": "5, Somewhere, XY1 2AB",
"property_type": "House",
"main_dwelling_floor_1_area_m2": 50.0,
"main_dwelling_floor_1_height_m": 2.5,
"main_dwelling_floor_1_heat_loss_perimeter_m": 10.0,
"main_dwelling_floor_1_party_wall_length_m": 3.0,
}

View file

@ -1,5 +1,5 @@
import xml.etree.ElementTree as ET
from typing import List, Optional, TypedDict
from typing import Any, List, Optional, TypedDict
from etl.xml_survey_extraction.XmlParser import PROPERTY_TYPE_LOOKUP
@ -170,3 +170,7 @@ def parse_rdsap(xml_string: str) -> SapPropertyDetails:
}
return result
def flatten_sap_property(details: SapPropertyDetails) -> dict[str, Any]:
raise NotImplementedError