diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index 15f75569..f4b50566 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -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] # ---------------------------------------------------------------------------