mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
adding additional attributes to property for posting to the database
This commit is contained in:
parent
2c4d06f746
commit
6f579b6939
2 changed files with 159 additions and 0 deletions
|
|
@ -38,6 +38,10 @@ class Property(BaseUtility):
|
|||
self.in_conservation_area = None
|
||||
self.year_built = None
|
||||
|
||||
self.energy = None
|
||||
self.ventilation = None
|
||||
self.solar_pv = None
|
||||
|
||||
if epc_client:
|
||||
self.epc_client = epc_client
|
||||
else:
|
||||
|
|
@ -76,6 +80,70 @@ class Property(BaseUtility):
|
|||
"""
|
||||
self.coordinates = {key.lower(): value for key, value in coordinates.items()}
|
||||
|
||||
def set_energy(self):
|
||||
"""
|
||||
Extracts and formats data about the home's energy and co2 consumption
|
||||
To being with, this is just formatting epc data
|
||||
|
||||
Data:
|
||||
- primary_energy_consumption
|
||||
This is based on the "energy-consumption-current" field in the EPC data.
|
||||
Current estimated total energy consumption for the property in a 12 month period (kWh/m2). Displayed on EPC
|
||||
as the current primary energy use per square metre of floor area.
|
||||
|
||||
- co2_emissions
|
||||
This is based on the "co2-emissions-current" field in the EPC data.
|
||||
CO₂ emissions per year in tonnes/year.
|
||||
"""
|
||||
|
||||
self.energy = {
|
||||
"primary_energy_consumption": float(self.data["energy-consumption-current"]),
|
||||
"co2_emissions": float(self.data["co2-emissions-current"]),
|
||||
}
|
||||
|
||||
def set_ventilation(self):
|
||||
"""
|
||||
Extracts and formats data about the home's ventilation
|
||||
To being with, this is just formatting epc data
|
||||
|
||||
Data:
|
||||
- ventilation
|
||||
This is based on the "ventilation-type" field in the EPC data.
|
||||
Ventilation type of the property.
|
||||
"""
|
||||
|
||||
ventilation = self.data["mechanical-ventilation"]
|
||||
# perform some simple cleaning - when checking 300k properties, the only unique values were
|
||||
# {'', 'mechanical, supply and extract', 'NO DATA!', 'natural', 'mechanical, extract only'}
|
||||
if ventilation in self.DATA_ANOMALY_MATCHES or ventilation in [""]:
|
||||
ventilation = None
|
||||
|
||||
self.ventilation = {
|
||||
"ventilation": ventilation,
|
||||
}
|
||||
|
||||
def set_solar_pv(self):
|
||||
"""
|
||||
Extracts and formats data about the home's solar pv
|
||||
To being with, this is just formatting epc data
|
||||
|
||||
Data:
|
||||
- solar_pv
|
||||
This is based on the "photo-supply" field in the EPC data.
|
||||
|
||||
When checking 100k properties, either the value was "" or a stringified number
|
||||
"""
|
||||
|
||||
solar_pv = self.data["photo-supply"]
|
||||
if solar_pv == "":
|
||||
solar_pv = None
|
||||
else:
|
||||
solar_pv = float(solar_pv)
|
||||
|
||||
self.solar_pv = {
|
||||
"solar_pv": solar_pv,
|
||||
}
|
||||
|
||||
def get_components(self, cleaned):
|
||||
"""
|
||||
Given the cleaning that has been performed, we'll use this to identify the property
|
||||
|
|
@ -90,6 +158,10 @@ class Property(BaseUtility):
|
|||
if not self.data:
|
||||
raise ValueError("Property does not contain data")
|
||||
|
||||
self.set_energy()
|
||||
self.set_ventilation()
|
||||
self.set_solar_pv()
|
||||
|
||||
for description, attribute in cleaned.items():
|
||||
|
||||
if self.data[description] in self.DATA_ANOMALY_MATCHES:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import datetime
|
||||
from fastapi import APIRouter, Depends
|
||||
from backend.app.dependencies import validate_token
|
||||
from backend.app.plan.schemas import PlanTriggerRequest
|
||||
|
|
@ -93,6 +94,15 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
if not is_new:
|
||||
continue
|
||||
|
||||
# TODO: push property targets
|
||||
# TODO: Need to add heat demand target
|
||||
property_targets = {
|
||||
"property_id": property_id,
|
||||
"portfolio_id": body.portfolio_id,
|
||||
"created_at": datetime.datetime.now(),
|
||||
"epc": body.goal_value,
|
||||
}
|
||||
|
||||
input_properties.append(
|
||||
Property(
|
||||
postcode=config['postcode'],
|
||||
|
|
@ -187,4 +197,81 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
|
||||
recommendations.extend(wall_recomendations.recommendations)
|
||||
|
||||
# Once we're done, we'll store:
|
||||
# 1) the property data
|
||||
# 2) the property details (epc)
|
||||
# 3) the recommendations
|
||||
|
||||
# Upload property data
|
||||
for p in input_properties:
|
||||
property_data = {
|
||||
"creation_status": "COMPLETE",
|
||||
"uprn": int(p.data["uprn"]),
|
||||
"has_pre_condition_report": True,
|
||||
"has_recommendations": True,
|
||||
"property_type": p.data["property-type"],
|
||||
"built_form": p.data["built-form"],
|
||||
"local_authority": p.data["local-authority-label"],
|
||||
"constituency": p.data["constituency-label"],
|
||||
"number_of_rooms": p.data["number-habitable-rooms"],
|
||||
"year_built": p.year_built,
|
||||
"tenure": p.data["tenure"],
|
||||
"current_epc_rating": p.data["current-energy-rating"],
|
||||
"current_sap_points": p.data["current-energy-efficiency"]
|
||||
}
|
||||
|
||||
def clean_upload_data(to_update, to_clean_values):
|
||||
for k, v in to_update.items():
|
||||
if v in to_clean_values:
|
||||
to_update[k] = None
|
||||
return to_update
|
||||
|
||||
property_data = clean_upload_data(property_data, to_clean_values=p.DATA_ANOMALY_MATCHES)
|
||||
|
||||
rating_lookup = {
|
||||
"Very Good": 5,
|
||||
"Good": 4,
|
||||
"Average": 3,
|
||||
"Poor": 2,
|
||||
"Very Poor": 1,
|
||||
"N/A": None
|
||||
}
|
||||
|
||||
property_details_epc = {
|
||||
"property_id": p.id,
|
||||
"portfolio_id": body.portfolio_id,
|
||||
"full_address": p.data["address"],
|
||||
"total_floor_area": float(p.data["total-floor-area"]),
|
||||
"walls": p.walls["cleaned_description"],
|
||||
"walls_rating": rating_lookup[p.data["walls-energy-eff"]],
|
||||
"roof": p.roof["cleaned_description"],
|
||||
"roof_rating": rating_lookup[p.data["roof-energy-eff"]],
|
||||
"floor": p.floor["cleaned_description"],
|
||||
"floor_rating": rating_lookup[p.data["floor-energy-eff"]],
|
||||
"windows": p.windows["cleaned_description"],
|
||||
"windows_rating": rating_lookup[p.data["windows-energy-eff"]],
|
||||
"heating": p.main_heating["cleaned_description"],
|
||||
"heating_rating": rating_lookup[p.data["mainheat-energy-eff"]],
|
||||
"heating_controls": p.main_heating_controls["cleaned_description"],
|
||||
"heating_controls_rating": rating_lookup[p.data["mainheatc-energy-eff"]],
|
||||
"hot_water": p.hotwater["cleaned_description"],
|
||||
"hot_water_rating": rating_lookup[p.data["hot-water-energy-eff"]],
|
||||
"lighting": p.lighting["cleaned_description"],
|
||||
"lighting_rating": rating_lookup[p.data["lighting-energy-eff"]],
|
||||
"ventilation": p.ventilation["ventilation"],
|
||||
"solar_pv": p.solar_pv["cleaned_description"],
|
||||
"solar_hot_water": p.solar_hot_water["cleaned_description"],
|
||||
"wind_turbine": p.wind_turbine["cleaned_description"],
|
||||
"floor_height": p.data["floor-height"],
|
||||
"heat_loss_corridor": p.data["heat-loss-corridor"],
|
||||
"unheated_corridor_length": p.data["unheated-corridor-length"],
|
||||
"number_of_open_fireplaces": int(p.data["number-open-fireplaces"]),
|
||||
"number_of_extensions": int(p.data["extension-count"]),
|
||||
"number_of_storeys": int(p.data["flat-storey-count"]),
|
||||
"mains_gas": p.data["mains-gas-flag"],
|
||||
"energy_tarrif": p.data["energy-tariff"],
|
||||
"primary_energy_consumption": p.energy["primary-energy-consumption"],
|
||||
"co2_emissions": p.energy["co2-emissions"],
|
||||
}
|
||||
|
||||
return {"recommendations": recommendations}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue