Adding temp portfolio id

This commit is contained in:
Khalim Conn-Kowlessar 2024-02-21 17:41:34 +00:00
parent 35a75bc4e5
commit 504796625b
4 changed files with 57 additions and 23 deletions

View file

@ -166,7 +166,9 @@ async def trigger_plan(body: PlanTriggerRequest):
p.get_components(cleaned, photo_supply_lookup, floor_area_decile_thresholds)
recommender = Recommendations(property_instance=p, materials=materials)
property_recommendations, property_representative_recommendations = recommender.recommend()
# TODO: portfolio id as an input is temp
print("DELETE PORTFOLIO ID AS AN INPUT!!")
property_recommendations, property_representative_recommendations = recommender.recommend(body.portfolio_id)
if not property_recommendations:
continue

View file

@ -1,5 +1,5 @@
import os
from pptx.enum.text import PP_ALIGN
from pptx.enum.text import PP_ALIGN # NOQA
from pptx import Presentation
from pptx.util import Inches, Pt
import matplotlib.pyplot as plt
@ -8,6 +8,7 @@ from sqlalchemy.sql import true
from backend.app.db.utils import row2dict
from backend.app.db.models.portfolio import PropertyModel, PropertyDetailsEpcModel
from backend.app.db.models.recommendations import Recommendation
from backend.app.db.models.recommendations import Plan
EPC_COLOURS = {
"A": "#028051",
@ -70,6 +71,23 @@ def get_property_details_by_portfolio_id(session: Session, portfolio_id: int):
return property_details_dict
def get_plan_by_portfolio_id(session: Session, portfolio_id: int):
"""
This function retrieves all plans associated with a given portfolio_id.
:param session: The SQLAlchemy session used to execute the query.
:param portfolio_id: The ID of the portfolio for which to retrieve plans.
:return: A list of dictionaries, where each dictionary represents a plan.
Returns an empty list if no plans are found.
"""
plans = session.query(Plan).filter(Plan.portfolio_id == portfolio_id).all()
# Convert the SQLAlchemy objects to dictionaries
plans_dict = [row2dict(plan) for plan in plans] if plans else []
return plans_dict
def plot_epc_distribution(df, customer_key, title='Your Units', background_color='white', bar_height=0.4, font_size=15):
"""
Plots a horizontal bar chart of EPC rating distribution with adjustable bar thickness and text sizes.

View file

@ -11,6 +11,7 @@ from sqlalchemy.orm import sessionmaker
from etl.customers.slide_utils import (
plot_epc_distribution,
get_property_details_by_portfolio_id,
get_plan_by_portfolio_id,
get_properties_with_default_recommendations,
create_powerpoint
)
@ -37,6 +38,9 @@ def app():
property_details = get_property_details_by_portfolio_id(session, PORTFOLIO_ID)
property_details_df = pd.DataFrame(property_details)
plans = get_plan_by_portfolio_id(session, PORTFOLIO_ID)
plans_df = pd.DataFrame(plans)
# Unnest the recommendations. Each recommendation is a list of dictionaries
recommendations_exploded = properties_df["recommendations"].explode().tolist()
recommendations_df = pd.DataFrame([r for r in recommendations_exploded if not pd.isnull(r)])
@ -103,8 +107,13 @@ def app():
property_details_df["co2_emissions"].mean()
)
# Valuation: upper and lower bounds - TODO!
min_valuation, max_valuation, average_valuation = (0, 0, 0)
# Valuation: upper and lower bounds and average - take positive values in case we have just a sample
valuation_df = properties_df[properties_df["current_valuation"] > 0]
min_valuation, max_valuation, average_valuation = (
valuation_df["current_valuation"].min(),
valuation_df["current_valuation"].max(),
valuation_df["current_valuation"].median()
)
recommendations_df.keys()
@ -134,10 +143,13 @@ def app():
measures = "Electrical heating system upgrades & heating controls and Hot water system improvements"
# Per property
# Take positive entries just in case we we have a sample
valuation_impact_df = plans_df[plans_df["property_id"].isin(units_hitting_target["property_id"])]
valuation_impact_df = valuation_impact_df[valuation_impact_df["valuation_increase_lower_bound"] > 0]
min_valuation_impact, max_valuation_impact, average_valuation_impact = (
units_hitting_target["total_valuation_impact"].min(),
units_hitting_target["total_valuation_impact"].max(),
units_hitting_target["total_valuation_impact"].mean()
valuation_impact_df["valuation_increase_lower_bound"].median(),
valuation_impact_df["valuation_increase_upper_bound"].median(),
valuation_impact_df["valuation_increase_average"].median()
)
# Bill savings per property

View file

@ -45,7 +45,7 @@ class Recommendations:
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
self.hotwater_recommender = HotwaterRecommendations(property_instance=property_instance)
def recommend(self):
def recommend(self, portfolio_id):
"""
This method runs the recommendations for the individual measures and then appends them to a list for output
@ -59,21 +59,23 @@ class Recommendations:
phase = 0
print("WALL RECOMMENDATIONS HAVE BEEN COMMENTED OUT TEMPORARILY - ADD ME BACK IN")
# # Building Fabric
# self.wall_recomender.recommend(phase=phase)
# if self.wall_recomender.recommendations:
# property_recommendations.append(self.wall_recomender.recommendations)
# phase += 1
#
# # Ventilation recommendations
# # We only produce a ventilation recommendation if the property is recommended to have wall or roof insulation
# # We will not attribute a SAP impact to the ventilation recommendation, since we've seen that this has no
# # real impact on the SAP score. Therefore, we don't need to include phasing for ventilation. If we have any
# # wall or roof recommendations, we will ensure that ventilation is included in the simulation
# if self.wall_recomender.recommendations or self.roof_recommender.recommendations:
# self.ventilation_recomender.recommend()
# if self.ventilation_recomender.recommendation:
# property_recommendations.append(self.ventilation_recomender.recommendation)
if portfolio_id != 66:
# Building Fabric
self.wall_recomender.recommend(phase=phase)
if self.wall_recomender.recommendations:
property_recommendations.append(self.wall_recomender.recommendations)
phase += 1
# Ventilation recommendations
# We only produce a ventilation recommendation if the property is recommended to have wall or roof
# insulation
# We will not attribute a SAP impact to the ventilation recommendation, since we've seen that this has no
# real impact on the SAP score. Therefore, we don't need to include phasing for ventilation. If we have any
# wall or roof recommendations, we will ensure that ventilation is included in the simulation
if self.wall_recomender.recommendations or self.roof_recommender.recommendations:
self.ventilation_recomender.recommend()
if self.ventilation_recomender.recommendation:
property_recommendations.append(self.ventilation_recomender.recommendation)
self.roof_recommender.recommend(phase=phase)
if self.roof_recommender.recommendations: