mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
378 lines
14 KiB
Python
378 lines
14 KiB
Python
from dataclasses import dataclass
|
|
from datetime import date
|
|
from typing import List, Optional, Union
|
|
|
|
from domain.epc.epc import Epc
|
|
|
|
|
|
@dataclass
|
|
class EnergyElement:
|
|
description: str
|
|
energy_efficiency_rating: int
|
|
environmental_efficiency_rating: int
|
|
|
|
|
|
@dataclass
|
|
class InstantaneousWwhrs:
|
|
wwhrs_index_number1: Optional[int] = None
|
|
wwhrs_index_number2: Optional[int] = None
|
|
|
|
|
|
@dataclass
|
|
class MainHeatingDetail:
|
|
has_fghrs: bool
|
|
main_fuel_type: Union[int, str] # int from API, str from site notes
|
|
heat_emitter_type: Union[int, str] # int from API, str from site notes
|
|
emitter_temperature: Union[int, str]
|
|
main_heating_control: Union[int, str] # int from API, str from site notes
|
|
fan_flue_present: Optional[bool] = None
|
|
boiler_flue_type: Optional[int] = None # TODO: make enum?
|
|
boiler_ignition_type: Optional[int] = None # TODO: make enum?
|
|
central_heating_pump_age: Optional[int] = None
|
|
central_heating_pump_age_str: Optional[str] = None # str from site notes e.g. "Unknown", "Pre 2013"
|
|
main_heating_index_number: Optional[int] = None
|
|
sap_main_heating_code: Optional[int] = None # TODO: make enum?
|
|
main_heating_number: Optional[int] = None
|
|
main_heating_category: Optional[int] = None
|
|
main_heating_fraction: Optional[int] = None
|
|
main_heating_data_source: Optional[int] = None
|
|
condensing: Optional[bool] = None
|
|
weather_compensator: Optional[bool] = None
|
|
|
|
|
|
@dataclass
|
|
class ShowerOutlet:
|
|
shower_outlet_type: Union[int, str]
|
|
shower_wwhrs: Optional[int] = None
|
|
|
|
|
|
@dataclass
|
|
class ShowerOutlets:
|
|
# TODO: consolidate ShowerOutlet and ShowerOutlets
|
|
shower_outlet: ShowerOutlet
|
|
|
|
|
|
@dataclass
|
|
class SapHeating:
|
|
instantaneous_wwhrs: InstantaneousWwhrs
|
|
main_heating_details: List[MainHeatingDetail]
|
|
has_fixed_air_conditioning: bool
|
|
cylinder_size: Optional[Union[int, str]] = (
|
|
None # int code from API; str (e.g. "Normal (90-130 litres)") from site notes
|
|
)
|
|
water_heating_code: Optional[int] = None # TODO: make enum?
|
|
water_heating_fuel: Optional[int] = None # TODO: make enum?
|
|
immersion_heating_type: Optional[Union[int, str]] = None # TODO: make enum?
|
|
shower_outlets: Optional[ShowerOutlets] = None
|
|
cylinder_insulation_type: Optional[Union[int, str]] = None
|
|
cylinder_thermostat: Optional[str] = None
|
|
secondary_fuel_type: Optional[int] = None
|
|
secondary_heating_type: Optional[Union[int, str]] = None # int from API; str from site notes
|
|
cylinder_insulation_thickness_mm: Optional[int] = None
|
|
|
|
|
|
@dataclass
|
|
class SapVentilation:
|
|
ventilation_type: Optional[str] = None
|
|
draught_lobby: Optional[bool] = None
|
|
pressure_test: Optional[str] = None # str from site notes e.g. "No test"; int in API via mechanical_ventilation
|
|
open_flues_count: Optional[int] = None
|
|
closed_flues_count: Optional[int] = None
|
|
boiler_flues_count: Optional[int] = None
|
|
other_flues_count: Optional[int] = None
|
|
extract_fans_count: Optional[int] = None
|
|
passive_vents_count: Optional[int] = None
|
|
flueless_gas_fires_count: Optional[int] = None
|
|
ventilation_in_pcdf_database: Optional[bool] = None
|
|
|
|
|
|
@dataclass
|
|
class WindowTransmissionDetails:
|
|
u_value: float
|
|
data_source: Union[int, str]
|
|
solar_transmittance: float
|
|
|
|
|
|
@dataclass
|
|
class SapWindow:
|
|
frame_material: Optional[str]
|
|
glazing_gap: Union[int, str]
|
|
orientation: Union[int, str]
|
|
window_type: Union[int, str]
|
|
glazing_type: Union[int, str]
|
|
window_width: float
|
|
window_height: float
|
|
draught_proofed: Union[bool, str] # TODO: make enum/mapping?
|
|
window_location: Union[int, str] # TODO: make enum/mapping
|
|
window_wall_type: Union[int, str] # TODO: make enum/mapping
|
|
permanent_shutters_present: Union[bool, str] # TODO: make enum/mapping
|
|
frame_factor: Optional[float] = None
|
|
window_transmission_details: Optional[WindowTransmissionDetails] = None
|
|
permanent_shutters_insulated: Optional[str] = None
|
|
|
|
|
|
@dataclass
|
|
class PvBattery:
|
|
battery_capacity: float
|
|
|
|
|
|
@dataclass
|
|
class PvBatteries:
|
|
pv_battery: PvBattery
|
|
|
|
|
|
@dataclass
|
|
class WindTurbineDetails:
|
|
hub_height: float
|
|
rotor_diameter: float
|
|
|
|
|
|
@dataclass
|
|
class PhotovoltaicSupplyNoneOrNoDetails:
|
|
percent_roof_area: int
|
|
|
|
|
|
@dataclass
|
|
class PhotovoltaicSupply:
|
|
none_or_no_details: PhotovoltaicSupplyNoneOrNoDetails
|
|
|
|
|
|
@dataclass
|
|
class SapEnergySource:
|
|
mains_gas: bool
|
|
meter_type: str # int in API, str (e.g. "Single") in site notes
|
|
pv_battery_count: int
|
|
wind_turbines_count: int
|
|
gas_smart_meter_present: bool
|
|
is_dwelling_export_capable: bool
|
|
wind_turbines_terrain_type: str # int in API, str (e.g. "Suburban") in site notes
|
|
electricity_smart_meter_present: bool
|
|
|
|
pv_connection: Optional[Union[int, str]] = None # int from API; str from site notes
|
|
photovoltaic_supply: Optional[PhotovoltaicSupply] = None
|
|
wind_turbine_details: Optional[WindTurbineDetails] = None
|
|
pv_batteries: Optional[PvBatteries] = None
|
|
|
|
|
|
@dataclass
|
|
class SapFloorDimension:
|
|
room_height_m: float
|
|
total_floor_area_m2: float
|
|
party_wall_length_m: float
|
|
heat_loss_perimeter_m: float
|
|
|
|
floor: Optional[int] = None
|
|
floor_insulation: Optional[int] = None
|
|
floor_construction: Optional[int] = None
|
|
|
|
|
|
@dataclass
|
|
class SapRoomInRoof:
|
|
floor_area: Union[int, float]
|
|
construction_age_band: str
|
|
|
|
|
|
@dataclass
|
|
class SapAlternativeWall:
|
|
wall_area: float
|
|
wall_dry_lined: str
|
|
wall_construction: int
|
|
wall_insulation_type: int
|
|
wall_thickness_measured: str
|
|
wall_insulation_thickness: Optional[str] = None
|
|
|
|
|
|
@dataclass
|
|
class SapBuildingPart:
|
|
# General
|
|
identifier: str # e.g. "main", "roof"
|
|
construction_age_band: str
|
|
|
|
# Wall
|
|
wall_construction: Union[
|
|
int, str
|
|
] # int from API, str from site notes TODO: make enum/mapping?
|
|
wall_insulation_type: Union[
|
|
int, str
|
|
] # int from API, str from site notes TODO: make enum/mapping?
|
|
wall_thickness_measured: bool
|
|
party_wall_construction: Union[int, str] # TODO: make enum/mapping?
|
|
|
|
# Floor
|
|
sap_floor_dimensions: List[
|
|
SapFloorDimension
|
|
] # Not included in site notes; should this be optional?
|
|
|
|
# Optional
|
|
building_part_number: Optional[int] = (
|
|
None # Not sure how we get this from site notes
|
|
)
|
|
wall_dry_lined: Optional[bool] = None # Don't think we have this in site notes
|
|
wall_thickness_mm: Optional[int] = None
|
|
wall_insulation_thickness: Optional[str] = None
|
|
sap_alternative_wall_1: Optional[SapAlternativeWall] = None
|
|
sap_alternative_wall_2: Optional[SapAlternativeWall] = None
|
|
|
|
floor_heat_loss: Optional[int] = None
|
|
floor_insulation_thickness: Optional[str] = None
|
|
flat_roof_insulation_thickness: Optional[Union[str, int]] = (
|
|
None # TODO: make enum/mapping?
|
|
)
|
|
floor_type: Optional[str] = None # str from site notes e.g. "Ground Floor"
|
|
floor_construction_type: Optional[str] = None # str from site notes; distinct from floor_construction: int in SapFloorDimension
|
|
floor_insulation_type_str: Optional[str] = None # str from site notes e.g. "As Built"
|
|
floor_u_value_known: Optional[bool] = None
|
|
|
|
roof_construction: Optional[int] = None
|
|
roof_insulation_location: Optional[Union[int, str]] = (
|
|
None # TODO: make enum/mapping?
|
|
)
|
|
roof_insulation_thickness: Optional[Union[str, int]] = (
|
|
None # TODO: make enum/mapping?
|
|
)
|
|
sap_room_in_roof: Optional[SapRoomInRoof] = None
|
|
|
|
|
|
@dataclass
|
|
class WindowsTransmissionDetails:
|
|
u_value: float
|
|
data_source: int
|
|
solar_transmittance: float
|
|
|
|
|
|
@dataclass
|
|
class SapFlatDetails:
|
|
level: int
|
|
top_storey: str
|
|
flat_location: int
|
|
heat_loss_corridor: int
|
|
storey_count: Optional[int] = None
|
|
unheated_corridor_length_m: Optional[int] = None
|
|
|
|
|
|
@dataclass
|
|
class EpcPropertyData:
|
|
# General
|
|
dwelling_type: str # TODO: make enum?
|
|
inspection_date: date
|
|
tenure: str # str in site notes; stringified int (e.g. "1") from API
|
|
transaction_type: str # str in site notes; stringified int from API
|
|
address_line_1: str
|
|
postcode: str
|
|
post_town: str
|
|
|
|
# Elements
|
|
roofs: List[EnergyElement]
|
|
walls: List[EnergyElement]
|
|
floors: List[EnergyElement]
|
|
main_heating: List[EnergyElement]
|
|
door_count: int
|
|
sap_heating: SapHeating
|
|
sap_windows: List[SapWindow]
|
|
sap_energy_source: SapEnergySource
|
|
sap_building_parts: List[SapBuildingPart]
|
|
solar_water_heating: bool
|
|
has_hot_water_cylinder: bool # must be inferred when mapping from site notes
|
|
has_fixed_air_conditioning: bool
|
|
|
|
# Counts
|
|
wet_rooms_count: int # If this isn't provided, should it be 0 or None?
|
|
extensions_count: int # If this isn't provided, should it be 0 or None?
|
|
heated_rooms_count: int # If this isn't provided, should it be 0 or None?
|
|
open_chimneys_count: int
|
|
habitable_rooms_count: int
|
|
insulated_door_count: (
|
|
int # Called "number_of_insulated_external_doors" in site notes; same thing?
|
|
)
|
|
cfl_fixed_lighting_bulbs_count: int
|
|
led_fixed_lighting_bulbs_count: int
|
|
incandescent_fixed_lighting_bulbs_count: int
|
|
|
|
# Measurements
|
|
total_floor_area_m2: float
|
|
|
|
# Optional fields
|
|
assessment_type: Optional[str] = None # not available from site notes
|
|
sap_version: Optional[float] = None # not available from site notes
|
|
uprn: Optional[int] = None # not available from site notes
|
|
status: Optional[str] = None # not available from site notes
|
|
window: Optional[EnergyElement] = None # not available from site notes
|
|
lighting: Optional[EnergyElement] = None # not available from site notes
|
|
hot_water: Optional[EnergyElement] = None # not available from site notes
|
|
schema_type: Optional[str] = None
|
|
schema_versions_original: Optional[str] = None
|
|
report_type: Optional[str] = None # TODO: make enum?
|
|
report_reference: Optional[str] = None
|
|
uprn_source: Optional[str] = None
|
|
address_line_2: Optional[str] = None
|
|
region_code: Optional[str] = None # TODO: make enum?
|
|
country_code: Optional[str] = None
|
|
built_form: Optional[str] = None # TODO: make enum?
|
|
property_type: Optional[str] = None
|
|
pressure_test: Optional[int] = None
|
|
language_code: Optional[str] = None
|
|
completion_date: Optional[date] = None
|
|
registration_date: Optional[date] = None
|
|
measurement_type: Optional[int] = None # What is this?
|
|
conservatory_type: Optional[int] = (
|
|
None # What is this? site notes have "has_conservatory" flag
|
|
)
|
|
has_conservatory: Optional[bool] = None # mapped directly from site notes
|
|
has_heated_separate_conservatory: Optional[bool] = None
|
|
secondary_heating: Optional[EnergyElement] = (
|
|
None # For site notes, secondary_fuel maps to sap_heating.secondary_fuel_type
|
|
)
|
|
blocked_chimneys_count: Optional[int] = None
|
|
energy_rating_average: Optional[int] = None
|
|
main_heating_controls: Optional[EnergyElement] = (
|
|
None # site notes has heating_and_hot_water.main_heating.controls: str - doesn't map to EnergyElement
|
|
)
|
|
current_energy_efficiency_band: Optional[Epc] = None # not available in site notes?
|
|
environmental_impact_current: Optional[int] = None
|
|
heating_cost_current: Optional[float] = None
|
|
co2_emissions_current: Optional[float] = None
|
|
energy_consumption_current: Optional[int] = None
|
|
energy_rating_current: Optional[int] = None
|
|
lighting_cost_current: Optional[float] = None
|
|
hot_water_cost_current: Optional[float] = None
|
|
insulated_door_u_value: Optional[float] = None # Not available in site notes
|
|
mechanical_ventilation: Optional[int] = (
|
|
None # ventilation details present in site notes, but I'm not sure they correspond directly to the integers returned by the API here
|
|
)
|
|
percent_draughtproofed: Optional[int] = (
|
|
None # Site notes have draught_proofed: bool field for each window, can we use that to infer percentage?
|
|
)
|
|
heating_cost_potential: Optional[float] = None
|
|
co2_emissions_potential: Optional[float] = None
|
|
energy_consumption_potential: Optional[int] = None
|
|
energy_rating_potential: Optional[float] = None
|
|
lighting_cost_potential: Optional[float] = None
|
|
hot_water_cost_potential: Optional[float] = None
|
|
environmental_impact_potential: Optional[int] = None
|
|
potential_energy_efficiency_band: Optional[Epc] = (
|
|
None # not available in site notes
|
|
)
|
|
# renewable_heat_incentive: Optional[Any] = None # Not sure what this is, skip for now
|
|
draughtproofed_door_count: Optional[int] = None
|
|
mechanical_vent_duct_type: Optional[int] = None
|
|
windows_transmission_details: Optional[WindowsTransmissionDetails] = None
|
|
multiple_glazed_propertion: Optional[int] = None
|
|
calculation_software_version: Optional[str] = None # Do we care about this?
|
|
mechanical_vent_duct_placement: Optional[int] = None
|
|
mechanical_vent_duct_insulation: Optional[int] = None
|
|
pressure_test_certificate_number: Optional[int] = None
|
|
mechanical_ventilation_index_number: Optional[int] = None
|
|
mechanical_vent_measured_installation: Optional[str] = None
|
|
co2_emissions_current_per_floor_area: Optional[int] = None
|
|
low_energy_fixed_lighting_bulbs_count: Optional[int] = None
|
|
sap_flat_details: Optional[SapFlatDetails] = None
|
|
# survey_addendum: Optional[Any] = None # not sure how to handle, skip for now
|
|
fixed_lighting_outlets_count: Optional[int] = None
|
|
low_energy_fixed_lighting_outlets_count: Optional[int] = None
|
|
# Site-notes-only fields
|
|
sap_ventilation: Optional[SapVentilation] = None
|
|
number_of_storeys: Optional[int] = None
|
|
any_unheated_rooms: Optional[bool] = None
|
|
waste_water_heat_recovery: Optional[str] = None
|
|
hydro: Optional[bool] = None
|
|
photovoltaic_array: Optional[bool] = None
|