From 1f1bf9981ce2e0b3a9bf42a8d096fb9aba333f4e Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 3 Oct 2024 10:38:14 +0100 Subject: [PATCH] adding measure type for wall and roof insulation --- backend/Property.py | 8 ++++++-- backend/app/db/models/portfolio.py | 7 +++++++ backend/app/plan/router.py | 11 ++++++----- recommendations/Recommendations.py | 17 +++++++++-------- recommendations/RoofRecommendations.py | 8 +++++--- recommendations/WallRecommendations.py | 2 ++ 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/backend/Property.py b/backend/Property.py index 55e3a912..491a886f 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -621,7 +621,7 @@ class Property: self.set_windows_count() self.set_energy_source() self.find_energy_sources() - self.set_current_energy_bill(kwh_client, kwh_predictions) + self.set_current_energy(kwh_client, kwh_predictions) def set_solar_panel_configuration( self, solar_panel_configuration, roof_area @@ -651,7 +651,7 @@ class Property: else: self.roof_area = roof_area - def set_current_energy_bill(self, kwh_client, kwh_predictions): + def set_current_energy(self, kwh_client, kwh_predictions): """ Given what we know about the property now, estimates the current energy consumption using the UCL paper https://www.sciencedirect.com/science/article/pii/S0378778823002542 @@ -808,6 +808,9 @@ class Property: def get_property_details_epc(self, portfolio_id: int, rating_lookup): + if self.current_energy_bill is None: + raise ValueError("Current energy bill has not been set") + property_details_epc = { "property_id": self.id, "portfolio_id": portfolio_id, @@ -865,6 +868,7 @@ class Property: "current_energy_demand": self.current_energy_consumption, "current_energy_demand_heating_hotwater": self.current_energy_consumption_heating_hotwater, "estimated": self.data.get("estimated", False), + **self.current_energy_bill } return property_details_epc diff --git a/backend/app/db/models/portfolio.py b/backend/app/db/models/portfolio.py index e2b258f4..5f51cf46 100644 --- a/backend/app/db/models/portfolio.py +++ b/backend/app/db/models/portfolio.py @@ -173,6 +173,13 @@ class PropertyDetailsEpcModel(Base): current_energy_demand = Column(Float) current_energy_demand_heating_hotwater = Column(Float) estimated = Column(Boolean, default=False) + # Include estimates for energy bills, across the different types of energy + heating_cost_current = Column(Float) + hot_water_cost_current = Column(Float) + lighting_cost_current = Column(Float) + appliances_cost_current = Column(Float) + gas_standing_charge = Column(Float) + electricity_standing_charge = Column(Float) class PropertyDetailsSpatial(Base): diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index 9d77c1a1..6b8c5bea 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -10,7 +10,6 @@ from sqlalchemy.exc import IntegrityError, OperationalError from sqlalchemy.orm import sessionmaker from starlette.responses import Response -import backend.app.assumptions as assumptions from backend.app.config import get_settings, get_prediction_buckets from backend.app.db.connection import db_engine from backend.app.db.functions.materials_functions import get_materials @@ -614,10 +613,12 @@ async def trigger_plan(body: PlanTriggerRequest): property_recommendations = recommendations.get(property_id, []) property_instance = [p for p in input_properties if p.id == property_id][0] - property_current_energy_bill = Recommendations.calculate_recommendation_tenant_savings( - property_instance=property_instance, - kwh_simulation_predictions=kwh_simulation_predictions, - property_recommendations=property_recommendations + property_current_energy_bill = ( + Recommendations.calculate_recommendation_tenant_savings( + property_instance=property_instance, + kwh_simulation_predictions=kwh_simulation_predictions, + property_recommendations=property_recommendations + ) ) property_instance.current_energy_bill = property_current_energy_bill diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py index 526cb2a2..78725c2d 100644 --- a/recommendations/Recommendations.py +++ b/recommendations/Recommendations.py @@ -797,13 +797,14 @@ class Recommendations: electricity_standing_charge = AnnualBillSavings.DAILY_STANDARD_CHARGE_ELECTRICITY * 365 - current_energy_bill = ( - starting_figures["heating_cost"] + - starting_figures["hotwater_cost"] + - property_instance.energy_cost_estimates["unadjusted"]["lighting"] + - property_instance.energy_cost_estimates["unadjusted"]["appliances"] + - gas_standing_charge + - electricity_standing_charge - ) + # We return a dictionary that contains the individual costs, that can be stored to the database + current_energy_bill = { + "heating_cost_current": starting_figures["heating_cost"], + "hot_water_cost_current": starting_figures["hotwater_cost"], + "lighting_cost_current": property_instance.energy_cost_estimates["unadjusted"]["lighting"], + "appliances_cost_current": property_instance.energy_cost_estimates["unadjusted"]["appliances"], + "gas_standing_charge": gas_standing_charge, + "electricity_standing_charge": electricity_standing_charge, + } return current_energy_bill diff --git a/recommendations/RoofRecommendations.py b/recommendations/RoofRecommendations.py index 4d22eb2d..3e266cee 100644 --- a/recommendations/RoofRecommendations.py +++ b/recommendations/RoofRecommendations.py @@ -250,8 +250,10 @@ class RoofRecommendations: if is_pitched: insulation_materials = self.loft_insulation_materials + measure_type = "loft_insulation" elif is_flat: insulation_materials = self.flat_roof_insulation_materials + measure_type = "flat_roof_insulation" else: raise ValueError("Roof is not pitched or flat") @@ -367,6 +369,7 @@ class RoofRecommendations: ) ], "type": material["type"], + "measure_type": measure_type, "description": self.make_roof_insulation_description(material), "starting_u_value": u_value, "new_u_value": new_u_value, @@ -490,10 +493,9 @@ class RoofRecommendations: recommendations.append( { "phase": phase, - "parts": [ - # TODO - ], + "parts": [], "type": "room_roof_insulation", + "measure_type": "room_roof_insulation", "description": "Insulate room in roof at rafters and re-decorate", "starting_u_value": u_value, "new_u_value": new_u_value, diff --git a/recommendations/WallRecommendations.py b/recommendations/WallRecommendations.py index 4902ae03..dd5e861c 100644 --- a/recommendations/WallRecommendations.py +++ b/recommendations/WallRecommendations.py @@ -374,6 +374,7 @@ class WallRecommendations(Definitions): ) ], "type": "cavity_wall_insulation", + "measure_type": "cavity_wall_insulation", "description": description, "starting_u_value": u_value, "new_u_value": new_u_value, @@ -545,6 +546,7 @@ class WallRecommendations(Definitions): ) ], "type": material["type"], + "measure_type": material["type"], # This is distinguished between EWI & IWI "description": self._make_description(material), "starting_u_value": u_value, "new_u_value": new_u_value,