mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge branch 'main' of github.com:Hestia-Homes/Model into michael-initial
This commit is contained in:
commit
9fe640dd50
3 changed files with 172 additions and 0 deletions
71
backend/app/db/functions/recommendations_functions.py
Normal file
71
backend/app/db/functions/recommendations_functions.py
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
from backend.app.db.connection import db_engine
|
||||||
|
from backend.app.db.models.recommendations import Plan, Recommendation, RecommendationMaterials
|
||||||
|
|
||||||
|
|
||||||
|
def create_plan(plan):
|
||||||
|
"""
|
||||||
|
This function will create a record for the plan in the database if it does not exist.
|
||||||
|
:param plan: dictionary of data representing a plan to be created
|
||||||
|
"""
|
||||||
|
|
||||||
|
Session = sessionmaker(bind=db_engine)
|
||||||
|
with Session() as session:
|
||||||
|
new_plan = Plan(**plan)
|
||||||
|
session.add(new_plan)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return new_plan.id
|
||||||
|
|
||||||
|
|
||||||
|
def create_recommendation(recommendation):
|
||||||
|
"""
|
||||||
|
This function will create a record for the recommendation in the database if it does not exist.
|
||||||
|
:param recommendation: dictionary of data representing a recommendation to be created
|
||||||
|
"""
|
||||||
|
|
||||||
|
Session = sessionmaker(bind=db_engine)
|
||||||
|
with Session() as session:
|
||||||
|
new_recommendation = Recommendation(**recommendation)
|
||||||
|
session.add(new_recommendation)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return new_recommendation.id
|
||||||
|
|
||||||
|
|
||||||
|
def create_recommendation_material(recommendation_id, material_id, depth):
|
||||||
|
"""
|
||||||
|
This function will create a record for the recommendation_material in the database if it does not exist.
|
||||||
|
:param recommendation_id: ID of the recommendation
|
||||||
|
:param material_id: ID of the material
|
||||||
|
:param depth: depth of the material, may be null if a material where depth is not applicable
|
||||||
|
"""
|
||||||
|
|
||||||
|
Session = sessionmaker(bind=db_engine)
|
||||||
|
with Session() as session:
|
||||||
|
new_recommendation_material = RecommendationMaterials(
|
||||||
|
recommendation_id=recommendation_id,
|
||||||
|
material_id=material_id,
|
||||||
|
depth=depth
|
||||||
|
)
|
||||||
|
session.add(new_recommendation_material)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return new_recommendation_material.id
|
||||||
|
|
||||||
|
|
||||||
|
def create_plan_recommendations(plan_id, recommendation_ids):
|
||||||
|
"""
|
||||||
|
This function will create a record for the plan_recommendation in the database if it does not exist.
|
||||||
|
:param plan_id: ID of the plan
|
||||||
|
:param recommendation_ids: list of recommendation IDs
|
||||||
|
"""
|
||||||
|
|
||||||
|
Session = sessionmaker(bind=db_engine)
|
||||||
|
with Session() as session:
|
||||||
|
for recommendation_id in recommendation_ids:
|
||||||
|
session.execute(
|
||||||
|
'INSERT INTO plan_recommendations (plan_id, recommendation_id) VALUES (:plan_id, :recommendation_id)',
|
||||||
|
{'plan_id': plan_id, 'recommendation_id': recommendation_id}
|
||||||
|
)
|
||||||
|
session.commit()
|
||||||
55
backend/app/db/models/recommendations.py
Normal file
55
backend/app/db/models/recommendations.py
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
from sqlalchemy import Column, BigInteger, String, Float, Boolean, TIMESTAMP, ForeignKey
|
||||||
|
from sqlalchemy.orm import declarative_base, relationship
|
||||||
|
from sqlalchemy.sql import func
|
||||||
|
from backend.app.db.models.portfolio import Portfolio, PropertyModel
|
||||||
|
from backend.app.db.models.materials import Material
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
|
|
||||||
|
|
||||||
|
class Recommendation(Base):
|
||||||
|
__tablename__ = 'recommendation'
|
||||||
|
|
||||||
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||||
|
property_id = Column(BigInteger, ForeignKey(PropertyModel.id), nullable=False)
|
||||||
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
||||||
|
type = Column(String, nullable=False)
|
||||||
|
description = Column(String, nullable=False)
|
||||||
|
estimated_cost = Column(Float)
|
||||||
|
default = Column(Boolean, nullable=False)
|
||||||
|
starting_u_value = Column(Float)
|
||||||
|
new_u_value = Column(Float)
|
||||||
|
sap_points = Column(Float)
|
||||||
|
heat_demand = Column(Float)
|
||||||
|
co2_equivalent_savings = Column(Float)
|
||||||
|
energy_savings = Column(Float)
|
||||||
|
energy_cost_savings = Column(Float)
|
||||||
|
property_valuation_increase = Column(Float)
|
||||||
|
rental_yield_increase = Column(Float)
|
||||||
|
total_work_hours = Column(Float)
|
||||||
|
|
||||||
|
|
||||||
|
class RecommendationMaterials(Base):
|
||||||
|
__tablename__ = 'recommendation_materials'
|
||||||
|
|
||||||
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||||
|
recommendation_id = Column(BigInteger, ForeignKey('recommendation.id'), nullable=False)
|
||||||
|
material_id = Column(BigInteger, ForeignKey(Material.id), nullable=False)
|
||||||
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
||||||
|
|
||||||
|
|
||||||
|
class Plan(Base):
|
||||||
|
__tablename__ = 'plan'
|
||||||
|
|
||||||
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||||
|
portfolio_id = Column(BigInteger, ForeignKey(Portfolio.id), nullable=False)
|
||||||
|
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
|
||||||
|
is_default = Column(Boolean, nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
class PlanRecommendations(Base):
|
||||||
|
__tablename__ = 'plan_recommendations'
|
||||||
|
|
||||||
|
id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||||
|
plan_id = Column(BigInteger, ForeignKey('plan.id'), nullable=False)
|
||||||
|
recommendation_id = Column(BigInteger, ForeignKey('recommendation.id'), nullable=False)
|
||||||
|
|
@ -19,6 +19,9 @@ from backend.app.db.functions.property_functions import (
|
||||||
create_property, create_property_targets, update_property_data, create_property_details_epc
|
create_property, create_property_targets, update_property_data, create_property_details_epc
|
||||||
)
|
)
|
||||||
from backend.app.db.functions.materials_functions import get_materials
|
from backend.app.db.functions.materials_functions import get_materials
|
||||||
|
from backend.app.db.functions.recommendations_functions import (
|
||||||
|
create_plan, create_recommendation, create_recommendation_material, create_plan_recommendations
|
||||||
|
)
|
||||||
|
|
||||||
# TODO: This is placeholder until data is stored in DB
|
# TODO: This is placeholder until data is stored in DB
|
||||||
from backend.app.plan.uvalue_estimates_walls import uvalue_estimates_walls
|
from backend.app.plan.uvalue_estimates_walls import uvalue_estimates_walls
|
||||||
|
|
@ -249,9 +252,52 @@ async def trigger_plan(body: PlanTriggerRequest):
|
||||||
update_property_data(property_id=p.id, portfolio_id=body.portfolio_id, property_data=property_data)
|
update_property_data(property_id=p.id, portfolio_id=body.portfolio_id, property_data=property_data)
|
||||||
|
|
||||||
# Upload recommendations
|
# Upload recommendations
|
||||||
|
|
||||||
|
# TODO: We start off by optimising the recommendations
|
||||||
|
|
||||||
recommendations_to_upload = recommendations[p.id]
|
recommendations_to_upload = recommendations[p.id]
|
||||||
if not recommendations:
|
if not recommendations:
|
||||||
continue
|
continue
|
||||||
# Create a plan
|
# Create a plan
|
||||||
|
new_plan_id = create_plan(
|
||||||
|
{
|
||||||
|
"portfolio_id": body.portfolio_id,
|
||||||
|
"is_default": True
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# upload recommendations
|
||||||
|
uploaded_recommendation_ids = []
|
||||||
|
for rec in recommendations_to_upload:
|
||||||
|
# TODO: implement costs (at least a placeholder)
|
||||||
|
estimated_cost = sum([x["cost"] if x["cost"] else 0 for x in rec["parts"]])
|
||||||
|
|
||||||
|
recommendation_id = create_recommendation(
|
||||||
|
{
|
||||||
|
"type": rec["type"], # TODO: Add this to output
|
||||||
|
"description": rec["description"], # TODO: Add this to output
|
||||||
|
"estimated_cost": estimated_cost,
|
||||||
|
"default": True,
|
||||||
|
"starting_u_value": rec.get("starting_u_value"), # TODO: Add this to output
|
||||||
|
"new_u_value": rec.get("new_u_value"),
|
||||||
|
"sap_points": rec["sap_points"] # TODO: Add this to output
|
||||||
|
# Remaining outputs yet to be handled
|
||||||
|
}
|
||||||
|
)
|
||||||
|
uploaded_recommendation_ids.append(recommendation_id)
|
||||||
|
|
||||||
|
# create the bridging between the recommendation and the materials
|
||||||
|
for part in rec["parts"]:
|
||||||
|
create_recommendation_material(
|
||||||
|
recommendation_id=recommendation_id,
|
||||||
|
material_id=part["id"],
|
||||||
|
depth=part["depths"][0] if part["depths"] else None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Finally, match the recommendation to the plan
|
||||||
|
create_plan_recommendations(
|
||||||
|
plan_id=new_plan_id,
|
||||||
|
recommendation_ids=uploaded_recommendation_ids
|
||||||
|
)
|
||||||
|
|
||||||
return Response(status_code=200)
|
return Response(status_code=200)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue