mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Adding in updates to db
This commit is contained in:
parent
45ecd767df
commit
347008296b
5 changed files with 84 additions and 52 deletions
|
|
@ -38,6 +38,7 @@ class Property(BaseUtility):
|
|||
self.full_sap_epc = None
|
||||
self.in_conservation_area = None
|
||||
self.year_built = None
|
||||
self.number_of_rooms = None
|
||||
|
||||
self.energy = None
|
||||
self.ventilation = None
|
||||
|
|
@ -184,7 +185,7 @@ class Property(BaseUtility):
|
|||
"wind_turbine": wind_turbine_count,
|
||||
}
|
||||
|
||||
def set_property_counts(self):
|
||||
def set_count_variables(self):
|
||||
|
||||
"""
|
||||
For EPC fields that are just counts, we'll set them here
|
||||
|
|
@ -197,12 +198,18 @@ class Property(BaseUtility):
|
|||
"number_of_open_fireplaces": "number-open-fireplaces",
|
||||
"number_of_extensions": "extension-count",
|
||||
"number_of_storeys": "flat-storey-count",
|
||||
"number_of_rooms": "number-habitable-rooms",
|
||||
}
|
||||
|
||||
null_attributes = ["number_of_storeys", "number_of_rooms"]
|
||||
|
||||
for attribute, epc_field in fields.items():
|
||||
value = self.data["extension-count"]
|
||||
if value == "" or value in self.DATA_ANOMALY_MATCHES:
|
||||
value = 0
|
||||
if attribute in null_attributes:
|
||||
value = None
|
||||
else:
|
||||
value = 0
|
||||
else:
|
||||
value = int(value)
|
||||
|
||||
|
|
@ -227,7 +234,7 @@ class Property(BaseUtility):
|
|||
self.set_solar_pv()
|
||||
self.set_solar_hot_water()
|
||||
self.set_wind_turbine()
|
||||
self.set_property_counts()
|
||||
self.set_count_variables()
|
||||
|
||||
for description, attribute in cleaned.items():
|
||||
|
||||
|
|
@ -274,3 +281,37 @@ class Property(BaseUtility):
|
|||
|
||||
# We don't know when the property was built
|
||||
self.year_built = None
|
||||
|
||||
def _clean_upload_data(self, to_update):
|
||||
for k, v in to_update.items():
|
||||
if v in self.DATA_ANOMALY_MATCHES:
|
||||
to_update[k] = None
|
||||
return to_update
|
||||
|
||||
def get_full_property_data(self):
|
||||
"""
|
||||
This method extracts the data which is pushed to the database, containing core information, from the EPC
|
||||
about a property
|
||||
:return:
|
||||
"""
|
||||
|
||||
property_data = {
|
||||
"creation_status": "READY",
|
||||
"uprn": int(self.data["uprn"]),
|
||||
"building_reference_number": int(self.data["building-reference-number"]),
|
||||
"has_pre_condition_report": True,
|
||||
"has_recommendations": True,
|
||||
"property_type": self.data["property-type"],
|
||||
"built_form": self.data["built-form"],
|
||||
"local_authority": self.data["local-authority-label"],
|
||||
"constituency": self.data["constituency-label"],
|
||||
"number_of_rooms": self.number_of_rooms,
|
||||
"year_built": self.year_built,
|
||||
"tenure": self.data["tenure"],
|
||||
"current_epc_rating": self.data["current-energy-rating"],
|
||||
"current_sap_points": self.data["current-energy-efficiency"]
|
||||
}
|
||||
|
||||
property_data = self._clean_upload_data(property_data)
|
||||
|
||||
return property_data
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
# This script contains methods for interacting with the property table in the database
|
||||
###
|
||||
import datetime
|
||||
import pytz
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from backend.app.db.models.portfolio import PropertyModel, PropertyCreationStatus, PortfolioStatus, PropertyTargetsModel
|
||||
from backend.app.db.connection import db_engine
|
||||
|
|
@ -20,8 +21,6 @@ def create_property(portfolio_id: int, address: str, postcode: str) -> (int, boo
|
|||
Session = sessionmaker(bind=db_engine)
|
||||
with Session() as session:
|
||||
|
||||
now = datetime.datetime.now()
|
||||
|
||||
try:
|
||||
# Attempt to fetch the existing property
|
||||
existing_property = session.query(PropertyModel).filter_by(
|
||||
|
|
@ -29,7 +28,7 @@ def create_property(portfolio_id: int, address: str, postcode: str) -> (int, boo
|
|||
).one()
|
||||
|
||||
# Update the 'updated_at' field
|
||||
existing_property.updated_at = now
|
||||
existing_property.updated_at = datetime.datetime.now(pytz.utc)
|
||||
|
||||
# Merge the updated property back into the session
|
||||
session.merge(existing_property)
|
||||
|
|
@ -43,8 +42,6 @@ def create_property(portfolio_id: int, address: str, postcode: str) -> (int, boo
|
|||
address=address,
|
||||
postcode=postcode,
|
||||
portfolio_id=portfolio_id,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
creation_status=PropertyCreationStatus.LOADING,
|
||||
status=PortfolioStatus.ASSESSMENT.value,
|
||||
has_pre_condition_report=False,
|
||||
|
|
@ -69,12 +66,10 @@ def create_property_targets(property_id: int, portfolio_id: int, epc_target=None
|
|||
:return:
|
||||
"""
|
||||
Session = sessionmaker(bind=db_engine)
|
||||
now = datetime.datetime.now()
|
||||
with Session() as session:
|
||||
new_target = PropertyTargetsModel(
|
||||
property_id=property_id,
|
||||
portfolio_id=portfolio_id,
|
||||
created_at=now,
|
||||
epc=epc_target,
|
||||
heat_demand=heat_demand_target
|
||||
)
|
||||
|
|
@ -84,16 +79,28 @@ def create_property_targets(property_id: int, portfolio_id: int, epc_target=None
|
|||
return True
|
||||
|
||||
|
||||
def update_property_data(property_data):
|
||||
def update_property_data(property_id: int, portfolio_id: int, property_data: dict):
|
||||
Session = sessionmaker(bind=db_engine)
|
||||
now = datetime.datetime.now()
|
||||
now = datetime.datetime.now(pytz.utc)
|
||||
with Session() as session:
|
||||
new_target = PropertyTargetsModel(
|
||||
property_id=property_id,
|
||||
portfolio_id=portfolio_id,
|
||||
created_at=now,
|
||||
epc=epc_target,
|
||||
heat_demand=heat_demand_target
|
||||
)
|
||||
session.add(new_target)
|
||||
session.commit()
|
||||
try:
|
||||
# Attempt to fetch the existing property
|
||||
existing_property = session.query(PropertyModel).filter_by(
|
||||
id=property_id, portfolio_id=portfolio_id
|
||||
).one()
|
||||
|
||||
# Update the fields with the data in property_data
|
||||
for key, value in property_data.items():
|
||||
setattr(existing_property, key, value)
|
||||
|
||||
# Optionally, update the 'updated_at' field
|
||||
existing_property.updated_at = now
|
||||
|
||||
# Merge the updated property back into the session and commit
|
||||
session.merge(existing_property)
|
||||
session.commit()
|
||||
|
||||
except NoResultFound:
|
||||
raise Exception(f"Property with property_id {property_id} and portfolio_id {portfolio_id} not found")
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import enum
|
||||
import pytz
|
||||
import datetime
|
||||
from sqlalchemy import Column, Integer, Text, Boolean, Float, DateTime, Enum, ForeignKey
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
|
|
@ -40,8 +42,8 @@ class Portfolio(Base):
|
|||
property_valuation_increase = Column(Float) # Unit is always £ so we don't need to store the unit for the moment
|
||||
rental_yield_increase = Column(Float) # Unit is always £ so we don't need to store the unit for the moment
|
||||
total_work_hours = Column(Float)
|
||||
created_at = Column(DateTime, nullable=False)
|
||||
updated_at = Column(DateTime, nullable=False)
|
||||
created_at = Column(DateTime, nullable=False, default=datetime.datetime.now(pytz.utc))
|
||||
updated_at = Column(DateTime, nullable=False, default=datetime.datetime.now(pytz.utc))
|
||||
|
||||
|
||||
class PropertyCreationStatus(enum.Enum):
|
||||
|
|
@ -66,13 +68,14 @@ class PropertyModel(Base):
|
|||
portfolio_id = Column(Integer, ForeignKey('portfolio.id'), nullable=False)
|
||||
creation_status = Column(Enum(PropertyCreationStatus), nullable=False)
|
||||
uprn = Column(Integer)
|
||||
building_reference_number = Column(Integer)
|
||||
status = Column(Enum(PortfolioStatus, values_callable=lambda x: [e.value for e in x]), nullable=False)
|
||||
address = Column(Text)
|
||||
postcode = Column(Text)
|
||||
has_pre_condition_report = Column(Boolean)
|
||||
has_recommendations = Column(Boolean)
|
||||
created_at = Column(DateTime, nullable=False)
|
||||
updated_at = Column(DateTime, nullable=False)
|
||||
created_at = Column(DateTime, nullable=False, default=datetime.datetime.now(pytz.utc))
|
||||
updated_at = Column(DateTime, nullable=False, default=datetime.datetime.now(pytz.utc))
|
||||
property_type = Column(Text)
|
||||
built_form = Column(Text)
|
||||
local_authority = Column(Text)
|
||||
|
|
@ -148,6 +151,6 @@ class PropertyTargetsModel(Base):
|
|||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
property_id = Column(Integer, ForeignKey('property.id'), nullable=False)
|
||||
portfolio_id = Column(Integer, ForeignKey('portfolio.id'), nullable=False)
|
||||
created_at = Column(DateTime, nullable=False)
|
||||
created_at = Column(DateTime, nullable=False, default=datetime.datetime.now(pytz.utc))
|
||||
epc = Column(Enum(Epc))
|
||||
heat_demand = Column(Text)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import datetime
|
||||
from fastapi import APIRouter, Depends
|
||||
from backend.app.dependencies import validate_token
|
||||
from backend.app.plan.schemas import PlanTriggerRequest
|
||||
|
|
@ -13,7 +12,7 @@ from utils.uvalue_estimates import classify_decile_newvalues
|
|||
from model_data.EpcClean import EpcClean
|
||||
|
||||
# database interaction functions
|
||||
from backend.app.db.functions.property_functions import create_property, create_property_targets
|
||||
from backend.app.db.functions.property_functions import create_property, create_property_targets, update_property_data
|
||||
|
||||
# TODO: This is placeholder until data is stored in DB
|
||||
from backend.app.plan.uvalue_estimates_walls import uvalue_estimates_walls
|
||||
|
|
@ -105,6 +104,7 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
property_id=property_id,
|
||||
portfolio_id=body.portfolio_id,
|
||||
epc_target=body.goal_value,
|
||||
heat_demand_target=None
|
||||
)
|
||||
|
||||
input_properties.append(
|
||||
|
|
@ -212,30 +212,6 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
|
||||
# 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)
|
||||
|
||||
def prepare_rating(field):
|
||||
rating_lookup = {
|
||||
"Very Good": 5,
|
||||
|
|
@ -286,4 +262,7 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
"co2_emissions": p.energy["co2_emissions"],
|
||||
}
|
||||
|
||||
property_data = p.get_full_property_data()
|
||||
update_property_data(property_id=p.id, portfolio_id=body.portfolio_id, property_data=property_data)
|
||||
|
||||
return {"recommendations": recommendations}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ def app():
|
|||
cleaner = EpcClean(data)
|
||||
lighting_averages = cleaner.lighting_averages
|
||||
# TODO: WE need to store lighting_averages to a db
|
||||
# We should also extend these averages so they're by more variables (property type, age band, constituency,
|
||||
# etc)
|
||||
cleaner.clean()
|
||||
# TODO: cleaner.cleaned datasets to a db
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue