Map to domain from 20.0.0 schema 🟩

This commit is contained in:
Daniel Roth 2026-04-14 13:30:42 +00:00
parent d56090eaad
commit 95607bd5e8

View file

@ -1,5 +1,5 @@
from datetime import date
from typing import List, Union
from typing import List, Sequence, Union
from regex import T
@ -166,8 +166,164 @@ class EpcPropertyDataMapper:
raise NotImplementedError
@staticmethod
def from_rdsap_schema_20_0_0(_schema: RdSapSchema20_0_0) -> EpcPropertyData:
raise NotImplementedError
def from_rdsap_schema_20_0_0(schema: RdSapSchema20_0_0) -> EpcPropertyData:
es = schema.sap_energy_source
return EpcPropertyData(
uprn=schema.uprn,
assessment_type=schema.assessment_type,
sap_version=schema.sap_version,
dwelling_type=schema.dwelling_type,
property_type=str(schema.property_type),
built_form=str(schema.built_form),
address_line_1=schema.address_line_1,
address_line_2=schema.address_line_2,
postcode=schema.postcode,
post_town=schema.post_town,
status=schema.status,
tenure=str(schema.tenure),
transaction_type=str(schema.transaction_type),
inspection_date=date.fromisoformat(schema.inspection_date),
completion_date=date.fromisoformat(schema.completion_date),
registration_date=date.fromisoformat(schema.registration_date),
total_floor_area_m2=float(schema.total_floor_area),
solar_water_heating=schema.solar_water_heating == "Y",
has_hot_water_cylinder=schema.has_hot_water_cylinder == "true",
has_fixed_air_conditioning=schema.has_fixed_air_conditioning == "true",
conservatory_type=schema.conservatory_type,
has_conservatory=schema.conservatory_type != 1,
door_count=schema.door_count,
habitable_rooms_count=schema.habitable_room_count,
heated_rooms_count=schema.heated_room_count,
wet_rooms_count=0,
extensions_count=schema.extensions_count,
open_chimneys_count=0,
insulated_door_count=schema.insulated_door_count,
draughtproofed_door_count=None,
led_fixed_lighting_bulbs_count=0,
cfl_fixed_lighting_bulbs_count=0,
incandescent_fixed_lighting_bulbs_count=0,
roofs=EpcPropertyDataMapper._map_energy_elements(schema.roofs),
walls=EpcPropertyDataMapper._map_energy_elements(schema.walls),
floors=EpcPropertyDataMapper._map_energy_elements(schema.floors),
main_heating=EpcPropertyDataMapper._map_energy_elements(schema.main_heating),
window=EpcPropertyDataMapper._map_energy_element(schema.window),
lighting=EpcPropertyDataMapper._map_energy_element(schema.lighting),
hot_water=EpcPropertyDataMapper._map_energy_element(schema.hot_water),
secondary_heating=EpcPropertyDataMapper._map_energy_element(schema.secondary_heating),
sap_heating=SapHeating(
# 20.0.0 uses room counts not product index numbers; domain fields default to None
instantaneous_wwhrs=InstantaneousWwhrs(),
main_heating_details=[
MainHeatingDetail(
has_fghrs=d.has_fghrs == "Y",
main_fuel_type=d.main_fuel_type,
boiler_flue_type=d.boiler_flue_type,
fan_flue_present=d.fan_flue_present == "Y",
heat_emitter_type=d.heat_emitter_type,
emitter_temperature=d.emitter_temperature,
main_heating_number=d.main_heating_number,
main_heating_control=d.main_heating_control,
main_heating_category=d.main_heating_category,
main_heating_fraction=d.main_heating_fraction,
sap_main_heating_code=d.sap_main_heating_code,
central_heating_pump_age=d.central_heating_pump_age,
main_heating_data_source=d.main_heating_data_source,
main_heating_index_number=d.main_heating_index_number,
)
for d in schema.sap_heating.main_heating_details
],
has_fixed_air_conditioning=schema.sap_heating.has_fixed_air_conditioning == "true",
cylinder_size=schema.sap_heating.cylinder_size,
water_heating_code=schema.sap_heating.water_heating_code,
water_heating_fuel=schema.sap_heating.water_heating_fuel,
immersion_heating_type=schema.sap_heating.immersion_heating_type,
cylinder_insulation_type=schema.sap_heating.cylinder_insulation_type,
cylinder_thermostat=schema.sap_heating.cylinder_thermostat,
secondary_fuel_type=schema.sap_heating.secondary_fuel_type,
secondary_heating_type=schema.sap_heating.secondary_heating_type,
cylinder_insulation_thickness=schema.sap_heating.cylinder_insulation_thickness,
),
# 20.0.0 SapWindow lacks frame/gap/draught fields present in later schemas
sap_windows=[
SapWindow(
pvc_frame="",
glazing_gap=0,
orientation=w.orientation,
window_type=w.window_type,
glazing_type=w.glazing_type,
window_width=0.0,
window_height=0.0,
draught_proofed=False,
window_location=w.window_location,
window_wall_type=0,
permanent_shutters_present=False,
)
for w in schema.sap_windows
],
sap_energy_source=SapEnergySource(
mains_gas=es.mains_gas == "Y",
meter_type=str(es.meter_type),
pv_battery_count=0,
wind_turbines_count=es.wind_turbines_count,
gas_smart_meter_present=False,
is_dwelling_export_capable=False,
wind_turbines_terrain_type=str(es.wind_turbines_terrain_type),
electricity_smart_meter_present=False,
photovoltaic_supply=(
PhotovoltaicSupply(
none_or_no_details=PhotovoltaicSupplyNoneOrNoDetails(
percent_roof_area=es.photovoltaic_supply.none_or_no_details.percent_roof_area,
)
)
if es.photovoltaic_supply
else None
),
),
sap_building_parts=[
SapBuildingPart(
identifier=bp.identifier,
construction_age_band=bp.construction_age_band,
wall_construction=bp.wall_construction,
wall_insulation_type=bp.wall_insulation_type,
wall_thickness_measured=bp.wall_thickness_measured == "Y",
party_wall_construction=bp.party_wall_construction,
sap_floor_dimensions=[
SapFloorDimension(
room_height_m=fd.room_height.value,
total_floor_area_m2=fd.total_floor_area.value,
party_wall_length_m=(
float(fd.party_wall_length)
if isinstance(fd.party_wall_length, int)
else fd.party_wall_length.value
),
heat_loss_perimeter_m=fd.heat_loss_perimeter.value,
floor=fd.floor,
floor_insulation=fd.floor_insulation,
floor_construction=fd.floor_construction,
)
for fd in bp.sap_floor_dimensions
],
building_part_number=bp.building_part_number,
wall_dry_lined=bp.wall_dry_lined == "Y",
wall_thickness_mm=bp.wall_thickness,
wall_insulation_thickness=bp.wall_insulation_thickness,
floor_heat_loss=bp.floor_heat_loss,
floor_insulation_thickness=bp.floor_insulation_thickness,
roof_construction=bp.roof_construction,
roof_insulation_location=bp.roof_insulation_location,
roof_insulation_thickness=bp.roof_insulation_thickness,
sap_room_in_roof=(
SapRoomInRoof(
floor_area=bp.sap_room_in_roof.floor_area,
construction_age_band=bp.sap_room_in_roof.construction_age_band,
)
if bp.sap_room_in_roof
else None
),
)
for bp in schema.sap_building_parts
],
)
@staticmethod
def from_rdsap_schema_21_0_0(schema: RdSapSchema21_0_0) -> EpcPropertyData:
@ -206,14 +362,20 @@ class EpcPropertyDataMapper:
led_fixed_lighting_bulbs_count=schema.led_fixed_lighting_bulbs_count,
cfl_fixed_lighting_bulbs_count=schema.cfl_fixed_lighting_bulbs_count,
incandescent_fixed_lighting_bulbs_count=schema.incandescent_fixed_lighting_bulbs_count,
roofs=EpcPropertyDataMapper._map_21_0_0_energy_elements(schema.roofs),
walls=EpcPropertyDataMapper._map_21_0_0_energy_elements(schema.walls),
floors=EpcPropertyDataMapper._map_21_0_0_energy_elements(schema.floors),
main_heating=EpcPropertyDataMapper._map_21_0_0_energy_elements(schema.main_heating),
window=EpcPropertyDataMapper._map_21_0_0_energy_element(schema.window),
lighting=EpcPropertyDataMapper._map_21_0_0_energy_element(schema.lighting),
hot_water=EpcPropertyDataMapper._map_21_0_0_energy_element(schema.hot_water),
secondary_heating=EpcPropertyDataMapper._map_21_0_0_energy_element(schema.secondary_heating),
roofs=EpcPropertyDataMapper._map_energy_elements(schema.roofs),
walls=EpcPropertyDataMapper._map_energy_elements(schema.walls),
floors=EpcPropertyDataMapper._map_energy_elements(schema.floors),
main_heating=EpcPropertyDataMapper._map_energy_elements(
schema.main_heating
),
window=EpcPropertyDataMapper._map_energy_element(schema.window),
lighting=EpcPropertyDataMapper._map_energy_element(schema.lighting),
hot_water=EpcPropertyDataMapper._map_energy_element(
schema.hot_water
),
secondary_heating=EpcPropertyDataMapper._map_energy_element(
schema.secondary_heating
),
sap_heating=SapHeating(
instantaneous_wwhrs=InstantaneousWwhrs(
wwhrs_index_number1=schema.sap_heating.instantaneous_wwhrs.wwhrs_index_number1,
@ -239,7 +401,8 @@ class EpcPropertyDataMapper:
)
for d in schema.sap_heating.main_heating_details
],
has_fixed_air_conditioning=schema.sap_heating.has_fixed_air_conditioning == "true",
has_fixed_air_conditioning=schema.sap_heating.has_fixed_air_conditioning
== "true",
cylinder_size=schema.sap_heating.cylinder_size,
water_heating_code=schema.sap_heating.water_heating_code,
water_heating_fuel=schema.sap_heating.water_heating_fuel,
@ -291,7 +454,8 @@ class EpcPropertyDataMapper:
gas_smart_meter_present=es.gas_smart_meter_present == "true",
is_dwelling_export_capable=es.is_dwelling_export_capable == "true",
wind_turbines_terrain_type=str(es.wind_turbines_terrain_type),
electricity_smart_meter_present=es.electricity_smart_meter_present == "true",
electricity_smart_meter_present=es.electricity_smart_meter_present
== "true",
pv_connection=es.pv_connection,
photovoltaic_supply=(
PhotovoltaicSupply(
@ -311,7 +475,11 @@ class EpcPropertyDataMapper:
else None
),
pv_batteries=(
PvBatteries(pv_battery=PvBattery(battery_capacity=es.pv_batteries.pv_battery.battery_capacity))
PvBatteries(
pv_battery=PvBattery(
battery_capacity=es.pv_batteries.pv_battery.battery_capacity
)
)
if es.pv_batteries
else None
),
@ -428,18 +596,18 @@ class EpcPropertyDataMapper:
cfl_fixed_lighting_bulbs_count=schema.cfl_fixed_lighting_bulbs_count,
incandescent_fixed_lighting_bulbs_count=schema.incandescent_fixed_lighting_bulbs_count,
# Energy elements
roofs=EpcPropertyDataMapper._map_21_0_01_energy_elements(schema.roofs),
walls=EpcPropertyDataMapper._map_21_0_01_energy_elements(schema.walls),
floors=EpcPropertyDataMapper._map_21_0_01_energy_elements(schema.floors),
main_heating=EpcPropertyDataMapper._map_21_0_01_energy_elements(
roofs=EpcPropertyDataMapper._map_energy_elements(schema.roofs),
walls=EpcPropertyDataMapper._map_energy_elements(schema.walls),
floors=EpcPropertyDataMapper._map_energy_elements(schema.floors),
main_heating=EpcPropertyDataMapper._map_energy_elements(
schema.main_heating
),
window=EpcPropertyDataMapper._map_21_0_01_energy_element(schema.window),
lighting=EpcPropertyDataMapper._map_21_0_01_energy_element(schema.lighting),
hot_water=EpcPropertyDataMapper._map_21_0_01_energy_element(
window=EpcPropertyDataMapper._map_energy_element(schema.window),
lighting=EpcPropertyDataMapper._map_energy_element(schema.lighting),
hot_water=EpcPropertyDataMapper._map_energy_element(
schema.hot_water
),
secondary_heating=EpcPropertyDataMapper._map_21_0_01_energy_element(
secondary_heating=EpcPropertyDataMapper._map_energy_element(
schema.secondary_heating
),
# SAP heating
@ -625,36 +793,25 @@ class EpcPropertyDataMapper:
)
@staticmethod
def _map_21_0_0_energy_element(
element: EnergyElement_21_0,
def _map_energy_element(
element: Union[EnergyElement_20_0, EnergyElement_21_0, EnergyElement_21_0_1],
) -> EnergyElement:
description = (
element.description
if isinstance(element.description, str)
else element.description.value
)
return EnergyElement(
description=element.description,
description=description,
energy_efficiency_rating=element.energy_efficiency_rating,
environmental_efficiency_rating=element.environmental_efficiency_rating,
)
@staticmethod
def _map_21_0_0_energy_elements(
elements: List[EnergyElement_21_0],
def _map_energy_elements(
elements: Sequence[Union[EnergyElement_20_0, EnergyElement_21_0, EnergyElement_21_0_1]],
) -> List[EnergyElement]:
return [EpcPropertyDataMapper._map_21_0_0_energy_element(e) for e in elements]
@staticmethod
def _map_21_0_01_energy_element(
element: EnergyElement_21_0_1,
) -> EnergyElement:
return EnergyElement(
description=element.description.value,
energy_efficiency_rating=element.energy_efficiency_rating,
environmental_efficiency_rating=element.environmental_efficiency_rating,
)
@staticmethod
def _map_21_0_01_energy_elements(
elements: List[EnergyElement_21_0_1],
) -> List[EnergyElement]:
return [EpcPropertyDataMapper._map_21_0_01_energy_element(e) for e in elements]
return [EpcPropertyDataMapper._map_energy_element(e) for e in elements]
# ---------------------------------------------------------------------------