From 800b673150a2cb37c90bdff36b497a6afa30ae60 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 17 Oct 2024 15:02:03 +0100 Subject: [PATCH] Making it possible to pass valutations as a separate data input and injecting it into the property" --- backend/Property.py | 3 +++ backend/app/plan/router.py | 37 +++++++++++++++++++------- backend/ml_models/Valuation.py | 6 ++++- recommendations/WallRecommendations.py | 10 +++---- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/backend/Property.py b/backend/Property.py index 79108dc1..2f5341bb 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -75,6 +75,7 @@ class Property: postcode, address, epc_record, + property_valuation=None, already_installed=None, non_invasive_recommendations=None, measures=None, @@ -111,6 +112,8 @@ class Property: else: self.measures = ast.literal_eval(measures) if measures else None + self.valuation = property_valuation + self.uprn = epc_record.get("uprn") self.uprn_source = self.data.get("uprn-source") diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index 356aca84..d376b01e 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -289,7 +289,7 @@ def create_epc_records(epc_searcher: SearchEpc, energy_assessment: dict): }, energy_assessment_is_newer -def get_on_site_data(body: PlanTriggerRequest): +def get_request_property_data(body: PlanTriggerRequest): """ This function will read in the on-site data from the S3 bucket :param body: The request body @@ -311,10 +311,18 @@ def get_on_site_data(body: PlanTriggerRequest): bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.non_invasive_recommendations_file_path ) - return patches, already_installed, non_invasive_recommendations + valuation_data = [] + if body.valuation_file_path: + valuation_data = read_csv_from_s3( + bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.valuation_file_path + ) + + return patches, already_installed, non_invasive_recommendations, valuation_data -def extract_property_on_site_recommendations(config, patches, already_installed, non_invasive_recommendations, uprn): +def extract_property_request_data( + config, patches, already_installed, non_invasive_recommendations, valuation_data, uprn +): patch_has_uprn = "uprn" in patches[0] if patches else True if patch_has_uprn: patch = next(( @@ -360,7 +368,12 @@ def extract_property_on_site_recommendations(config, patches, already_installed, property_non_invasive_recommendations["recommendations"] = str(transformed) - return patch, property_already_installed, property_non_invasive_recommendations + property_valution = next(( + x for x in valuation_data if + (str(x["uprn"]) == str(uprn)) + ), {}) + + return patch, property_already_installed, property_non_invasive_recommendations, property_valution router = APIRouter( @@ -384,7 +397,7 @@ async def trigger_plan(body: PlanTriggerRequest): logger.info("Getting the inputs") plan_input = read_csv_from_s3(bucket_name=get_settings().PLAN_TRIGGER_BUCKET, filepath=body.trigger_file_path) # If we have patches or overrides, we should read them in here - patches, already_installed, non_invasive_recommendations = get_on_site_data(body) + patches, already_installed, non_invasive_recommendations, valuation_data = get_request_property_data(body) cleaning_data = read_dataframe_from_s3_parquet( bucket_name=get_settings().DATA_BUCKET, file_key="sap_change_model/cleaning_dataset.parquet", @@ -411,7 +424,7 @@ async def trigger_plan(body: PlanTriggerRequest): # We check for an energy assessment we have performed on this property: energy_assessment = get_latest_assessment_by_uprn(session, uprn if uprn is not None else epc_searcher.uprn) - + # Create a record in db property_id, is_new = create_property( session, body.portfolio_id, epc_searcher.address_clean, epc_searcher.postcode_clean, @@ -438,9 +451,14 @@ async def trigger_plan(body: PlanTriggerRequest): epc_searcher, energy_assessment ) - patch, property_already_installed, property_non_invasive_recommendations = ( - extract_property_on_site_recommendations( - config, patches, already_installed, non_invasive_recommendations, uprn + patch, property_already_installed, property_non_invasive_recommendations, property_valuation = ( + extract_property_request_data( + config=config, + patches=patches, + already_installed=already_installed, + non_invasive_recommendations=non_invasive_recommendations, + valuation_data=valuation_data, + uprn=epc_searcher.uprn, ) ) @@ -460,6 +478,7 @@ async def trigger_plan(body: PlanTriggerRequest): postcode=epc_searcher.postcode_clean, epc_record=prepared_epc, already_installed=property_already_installed, + property_valuation=property_valuation, non_invasive_recommendations=property_non_invasive_recommendations, energy_assessment=energy_assessment, **Property.extract_kwargs(config), # TODO: Depraecate this diff --git a/backend/ml_models/Valuation.py b/backend/ml_models/Valuation.py index 68432577..c0e49ffc 100644 --- a/backend/ml_models/Valuation.py +++ b/backend/ml_models/Valuation.py @@ -1,4 +1,5 @@ import numpy as np +from scipy.constants import value class PropertyValuation: @@ -203,7 +204,10 @@ class PropertyValuation: @classmethod def estimate(cls, property_instance, target_epc): - value = cls.UPRN_VALUE_LOOKUP.get(property_instance.uprn) + value = ( + property_instance.valuation if property_instance.valuation else + cls.UPRN_VALUE_LOOKUP.get(property_instance.uprn) + ) if not value: return { diff --git a/recommendations/WallRecommendations.py b/recommendations/WallRecommendations.py index 5dea13c8..88242709 100644 --- a/recommendations/WallRecommendations.py +++ b/recommendations/WallRecommendations.py @@ -339,11 +339,11 @@ class WallRecommendations(Definitions): "starting_u_value": None, "new_u_value": None, "sap_points": extension_cavity_insulation_recommendation["sap_points"], - "heat_demand": None, - "kwh_savings": None, - "energy_savings": None, - "energy_cost_savings": None, - "co2_equivalent_savings": None, + "heat_demand": 0, + "kwh_savings": 0, + "energy_savings": 0, + "energy_cost_savings": 0, + "co2_equivalent_savings": 0, "already_installed": False, "simulation_config": {}, "description_simulation": {},