Added pushing of spatial data to backend

This commit is contained in:
Khalim Conn-Kowlessar 2023-12-01 14:50:46 +00:00
parent 1f53cb3d44
commit 24e22fa56a
4 changed files with 78 additions and 14 deletions

View file

@ -45,7 +45,7 @@ class Property(Definitions):
windows = None
lighting = None
coordinates = None
spatial = None
def __init__(self, id, postcode, address1, epc_client=None, data=None):
self.id = id
@ -129,13 +129,6 @@ class Property(Definitions):
else:
self.uprn = int(self.data["uprn"])
def set_coordinates(self, coordinates):
"""
This method sets the coordinates of the property, given the open uprn data
:param coordinates: dictionary
"""
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
@ -364,6 +357,9 @@ class Property(Definitions):
def set_spatial(self, spatial: pd.DataFrame):
"""
Sets whether the property is in a conservation area given the output of the ConservationAreaClient
Will store a dictionary, spatial, which is used to populate the property spatial table in the database
:param spatial: Dataframe, containing the spatial data for the property
"""
self.in_conservation_area = spatial["conservation_status"].values[0]
@ -373,6 +369,17 @@ class Property(Definitions):
if self.in_conservation_area is True | self.is_listed is True | self.is_heritage is True:
self.restricted_measures = True
spatial_dict = spatial.to_dict("records")[0]
self.spatial = {
"x_coordinate": spatial_dict["X_COORDINATE"],
"y_coordinate": spatial_dict["Y_COORDINATE"],
"latitude": spatial_dict["LATITUDE"],
"longitude": spatial_dict["LONGITUDE"],
"conservation_status": spatial_dict["conservation_status"],
"is_listed_building": spatial_dict["is_listed_building"],
"is_heritage_building": spatial_dict["is_heritage_building"],
}
def set_year_built(self):
"""
Estimates when the property was built based on as much available data as possible.

View file

@ -3,13 +3,15 @@
###
import datetime
import pytz
from sqlalchemy.orm import Session
from backend.app.db.models.portfolio import (
PropertyModel, PropertyCreationStatus, PortfolioStatus, PropertyTargetsModel, PropertyDetailsEpcModel
PropertyModel, PropertyCreationStatus, PortfolioStatus, PropertyTargetsModel, PropertyDetailsEpcModel,
PropertyDetailsSpatial
)
from sqlalchemy.orm.exc import NoResultFound
def create_property(session, portfolio_id: int, address: str, postcode: str) -> (int, bool):
def create_property(session: Session, portfolio_id: int, address: str, postcode: str) -> (int, bool):
"""
This function will create a record for the property in the database if it does not exist.
If it does exist, it will just update the updated_at field.
@ -55,7 +57,9 @@ def create_property(session, portfolio_id: int, address: str, postcode: str) ->
return new_property.id, True
def create_property_targets(session, property_id: int, portfolio_id: int, epc_target=None, heat_demand_target=None):
def create_property_targets(
session: Session, property_id: int, portfolio_id: int, epc_target=None, heat_demand_target=None
):
"""
This function will create a record for the property targets in the database if it does not exist.
:param session: The database session
@ -78,7 +82,9 @@ def create_property_targets(session, property_id: int, portfolio_id: int, epc_ta
return True
def update_property_data(session, property_id: int, portfolio_id: int, property_data: dict):
def update_property_data(
session: Session, property_id: int, portfolio_id: int, property_data: dict
):
now = datetime.datetime.now(pytz.utc)
try:
@ -103,7 +109,9 @@ def update_property_data(session, property_id: int, portfolio_id: int, property_
return True
def create_property_details_epc(session, property_details_epc: dict):
def create_property_details_epc(
session: Session, property_details_epc: dict
):
"""
This function will create or update a record for the property details EPC in the database.
:param session: The database session
@ -128,3 +136,36 @@ def create_property_details_epc(session, property_details_epc: dict):
session.flush()
return True
def update_or_create_property_spatial_details(session: Session, uprn: int, property_details_spatial: dict):
"""
Update an existing property details record or create a new one based on the UPRN.
:param session: The SQLAlchemy session for database interaction.
:param uprn: The unique property reference number (UPRN) of the property.
:param property_details_spatial: A dictionary containing the spatial property details to store or update.
:return: True if the operation is successful, otherwise raises an exception.
"""
try:
# Attempt to fetch the existing property details
existing_property_details = session.query(PropertyDetailsSpatial).filter_by(
uprn=uprn
).one()
# Update the fields with the data in property_details
for key, value in property_details_spatial.items():
setattr(existing_property_details, key, value)
# Merge the updated property details back into the session and flush
session.merge(existing_property_details)
session.flush()
except NoResultFound:
# Create a new record if not found
new_property_details = PropertyDetailsSpatial(uprn=uprn, **property_details_spatial)
session.add(new_property_details)
session.flush()
return True

View file

@ -155,6 +155,19 @@ class PropertyDetailsEpcModel(Base):
adjusted_energy_consumption = Column(Float)
class PropertyDetailsSpatial(Base):
__tablename__ = "property_details_spatial"
id = Column(Integer, primary_key=True, autoincrement=True)
uprn = Column(Integer, nullable=False)
x_coordinate = Column(Float)
y_coordinate = Column(Float)
latitude = Column(Float)
longitude = Column(Float)
conservation_status = Column(Boolean)
is_listed_building = Column(Boolean)
is_heritage_building = Column(Boolean)
class PropertyDetailsMeter(Base):
__tablename__ = 'property_details_meter'
id = Column(Integer, primary_key=True, autoincrement=True)

View file

@ -13,7 +13,8 @@ from backend.app.db.connection import db_engine
from backend.app.db.functions.materials_functions import get_materials
from backend.app.db.functions.portfolio_functions import aggregate_portfolio_recommendations
from backend.app.db.functions.property_functions import (
create_property, create_property_details_epc, create_property_targets, update_property_data
create_property, create_property_details_epc, create_property_targets, update_property_data,
update_or_create_property_spatial_details
)
from backend.app.db.functions.recommendations_functions import (
create_plan, create_plan_recommendations, upload_recommendations
@ -507,6 +508,8 @@ async def trigger_plan(body: PlanTriggerRequest):
)
create_property_details_epc(session, property_details_epc)
update_or_create_property_spatial_details(session, p.uprn, p.spatial)
# TODO: TEMP
if p.data["uprn"] == "":
print("Get rid of me!")