mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
227 lines
7.9 KiB
Python
227 lines
7.9 KiB
Python
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">
|
|
<Report-Header>
|
|
<Property>
|
|
<Address>
|
|
<Address-Line-1>1</Address-Line-1>
|
|
<Address-Line-2>Fake Avenue</Address-Line-2>
|
|
<Post-Town>Random</Post-Town>
|
|
<Postcode>AB24 5CD</Postcode>
|
|
</Address>
|
|
</Property>
|
|
</Report-Header>
|
|
|
|
<SAP-Data>
|
|
<SAP-Property-Details>
|
|
<Property-Type>0</Property-Type>
|
|
|
|
<SAP-Building-Parts>
|
|
|
|
<SAP-Building-Part>
|
|
<Building-Part-Number>1</Building-Part-Number>
|
|
<Identifier>Main Dwelling</Identifier>
|
|
<Construction-Age-Band>C</Construction-Age-Band>
|
|
<Floor-Heat-Loss>7</Floor-Heat-Loss>
|
|
|
|
<Roof-Construction>4</Roof-Construction>
|
|
<Roof-Insulation-Location>2</Roof-Insulation-Location>
|
|
<Roof-Insulation-Thickness>100mm</Roof-Insulation-Thickness>
|
|
|
|
<Wall-Construction>4</Wall-Construction>
|
|
<Wall-Insulation-Type>4</Wall-Insulation-Type>
|
|
|
|
<SAP-Floor-Dimensions>
|
|
<SAP-Floor-Dimension>
|
|
<Heat-Loss-Perimeter quantity="metres">25.31</Heat-Loss-Perimeter>
|
|
<Room-Height quantity="metres">2.46</Room-Height>
|
|
<Total-Floor-Area quantity="square metres">43.61</Total-Floor-Area>
|
|
<Floor>0</Floor>
|
|
<Party-Wall-Length>0</Party-Wall-Length>
|
|
</SAP-Floor-Dimension>
|
|
|
|
<SAP-Floor-Dimension>
|
|
<Heat-Loss-Perimeter quantity="metres">26.16</Heat-Loss-Perimeter>
|
|
<Room-Height quantity="metres">2.44</Room-Height>
|
|
<Total-Floor-Area quantity="square metres">42.33</Total-Floor-Area>
|
|
<Floor>1</Floor>
|
|
<Party-Wall-Length>0</Party-Wall-Length>
|
|
</SAP-Floor-Dimension>
|
|
</SAP-Floor-Dimensions>
|
|
|
|
</SAP-Building-Part>
|
|
|
|
<SAP-Building-Part>
|
|
<Building-Part-Number>2</Building-Part-Number>
|
|
<Identifier>Extension</Identifier>
|
|
<Construction-Age-Band>C</Construction-Age-Band>
|
|
|
|
<Roof-Construction>8</Roof-Construction>
|
|
<Roof-Insulation-Location>7</Roof-Insulation-Location>
|
|
<Sloping-Ceiling-Insulation-Thickness>AB</Sloping-Ceiling-Insulation-Thickness>
|
|
|
|
<Wall-Construction>3</Wall-Construction>
|
|
<Wall-Insulation-Type>4</Wall-Insulation-Type>
|
|
|
|
<SAP-Floor-Dimensions>
|
|
<SAP-Floor-Dimension>
|
|
<Heat-Loss-Perimeter quantity="metres">6.85</Heat-Loss-Perimeter>
|
|
<Room-Height quantity="metres">2.24</Room-Height>
|
|
<Total-Floor-Area quantity="square metres">4.46</Total-Floor-Area>
|
|
<Floor>0</Floor>
|
|
<Party-Wall-Length>0</Party-Wall-Length>
|
|
</SAP-Floor-Dimension>
|
|
</SAP-Floor-Dimensions>
|
|
|
|
</SAP-Building-Part>
|
|
|
|
</SAP-Building-Parts>
|
|
|
|
</SAP-Property-Details>
|
|
</SAP-Data>
|
|
</RdSAP-Report>
|
|
"""
|
|
|
|
|
|
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)
|
|
|
|
# assert
|
|
assert result == {
|
|
"address": "1, Fake Avenue, Random, AB24 5CD",
|
|
"property_type": "House",
|
|
"building_parts": [
|
|
{
|
|
"identifier": "Main Dwelling",
|
|
"floors": [
|
|
{
|
|
"area_m2": 43.61,
|
|
"height_m": 2.46,
|
|
"heat_loss_perimeter_m": 25.31,
|
|
"party_wall_length_m": 0.0,
|
|
},
|
|
{
|
|
"area_m2": 42.33,
|
|
"height_m": 2.44,
|
|
"heat_loss_perimeter_m": 26.16,
|
|
"party_wall_length_m": 0.0,
|
|
},
|
|
],
|
|
"roof": {
|
|
"construction": 4,
|
|
"insulation_location": 2,
|
|
"insulation_thickness_mm": 100.0,
|
|
},
|
|
},
|
|
{
|
|
"identifier": "Extension",
|
|
"floors": [
|
|
{
|
|
"area_m2": 4.46,
|
|
"height_m": 2.24,
|
|
"heat_loss_perimeter_m": 6.85,
|
|
"party_wall_length_m": 0.0,
|
|
}
|
|
],
|
|
"roof": {
|
|
"construction": 8,
|
|
"insulation_location": 7,
|
|
},
|
|
},
|
|
],
|
|
}
|
|
|
|
|
|
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 == {
|
|
"reference": "1AB245CD",
|
|
"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 == {
|
|
"reference": "5XY12AB",
|
|
"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,
|
|
}
|