adding additional attributes to property for posting to the database

This commit is contained in:
Khalim Conn-Kowlessar 2023-08-01 11:38:35 +01:00
parent 2c4d06f746
commit 6f579b6939
2 changed files with 159 additions and 0 deletions

View file

@ -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:

View file

@ -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}