diff --git a/backend/Property.py b/backend/Property.py index ab8930c5..79108dc1 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -1204,7 +1204,7 @@ class Property: return False suitable_house = self.data["property-type"] == "House" and self.data["built-form"] in [ - "Detached", "Semi-Detached", + "Detached", "Semi-Detached", "End-Terrace", ] suitable_bungalow = self.data["property-type"] == "Bungalow" and self.data["built-form"] in [ diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index f4924c71..3b91a461 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -543,7 +543,11 @@ async def trigger_plan(body: PlanTriggerRequest): representative_recommendations = {} for p in tqdm(input_properties): recommender = Recommendations( - property_instance=p, materials=materials, exclusions=body.exclusions, inclusions=body.inclusions + property_instance=p, + materials=materials, + exclusions=body.exclusions, + inclusions=body.inclusions, + default_u_values=body.default_u_values ) property_recommendations, property_representative_recommendations = recommender.recommend() diff --git a/backend/app/plan/schemas.py b/backend/app/plan/schemas.py index 0d58c7e9..4b43db80 100644 --- a/backend/app/plan/schemas.py +++ b/backend/app/plan/schemas.py @@ -89,6 +89,9 @@ class PlanTriggerRequest(BaseModel): # if False, allows optimisation to be switched off optimise: Optional[bool] = True + # If True, uses default u-values for models + default_u_values: Optional[bool] = True + _allowed_goals = {"Increasing EPC"} _allowed_housing_types = {"Social", "Private"} diff --git a/backend/ml_models/Valuation.py b/backend/ml_models/Valuation.py index cbcebb9f..68432577 100644 --- a/backend/ml_models/Valuation.py +++ b/backend/ml_models/Valuation.py @@ -103,6 +103,8 @@ class PropertyValuation: # Vander Elliot Intrusive surveys 12103116: 1_537_000, 12103117: 1_404_000, + # GLA Proposal + 100020606627: 409_000 } # We base our valuation uplifts on a number of sources diff --git a/etl/customers/gla/example_model_outputs.py b/etl/customers/gla/example_model_outputs.py new file mode 100644 index 00000000..e239c43d --- /dev/null +++ b/etl/customers/gla/example_model_outputs.py @@ -0,0 +1,38 @@ +import pandas as pd +from utils.s3 import save_csv_to_s3 + +asset_list = [ + { + "address": "4, King Henrys Drive", + "postcode": "CR0 0PA" + }, +] +portfolio_id = 110 +user_id = 8 + +asset_list = pd.DataFrame(asset_list) + +filename = f"{user_id}/{portfolio_id}/asset_list.csv" +save_csv_to_s3( + dataframe=asset_list, + bucket_name="retrofit-plan-inputs-dev", + file_name=filename +) + +body1 = { + "portfolio_id": str(portfolio_id), + "housing_type": "Private", + "goal": "Increasing EPC", + "goal_value": "A", + "trigger_file_path": filename, + "already_installed_file_path": "", + "patches_file_path": "", + "non_invasive_recommendations_file_path": "", + "inclusions": [ + "cavity_wall_insulation", "loft_insulation", "air_source_heat_pump", "solar_pv" + ], + "budget": None, + "scenario_name": "Whole House", + "multi_plan": False, +} +print(body1) diff --git a/etl/customers/gla/proposal_investigation.py b/etl/customers/gla/proposal_investigation.py index 05df6be7..f6a87af1 100644 --- a/etl/customers/gla/proposal_investigation.py +++ b/etl/customers/gla/proposal_investigation.py @@ -76,13 +76,20 @@ ownership.prepare_for_matching() # Step 4: Match EPC data to ownership data ownership.match() -from utils.s3 import save_excel_to_s3 +from utils.s3 import save_excel_to_s3, read_excel_from_s3 # Save the data to S3 -save_excel_to_s3( - df=ownership.matched_addresses, +# save_excel_to_s3( +# df=ownership.matched_addresses, +# bucket_name=ownership.bucket, +# file_key=ownership.matched_addresses_pre_filter_filepath +# ) + +# Read in matches +matches = read_excel_from_s3( bucket_name=ownership.bucket, - file_key=ownership.matched_addresses_pre_filter_filepath + file_key="ownership/gla-proposal/2024-10-10 19:02:34.131365/matched_addresses_pre_filter.xlsx", + header_row=0 ) # We have the matches, which we now need to match to the postcodes @@ -95,6 +102,7 @@ matches = matches[~matches["TENURE"].isin( "Not defined - use in the case of a new dwelling for which the intended tenure in not known. It is not to be " "used for an existing dwelling", "NO DATA!"]) ] +matches["is_prs"] = matches["TENURE"].isin(["rental (private)", "Rented (private)"]) # Look at the EPC ratings epc_ratings = matches.groupby(["CURRENT_ENERGY_RATING"]).size().reset_index() epc_ratings.columns = ["EPC Rating", "Count"] @@ -103,6 +111,8 @@ epc_ratings["Percentage"] = epc_ratings["Count"] / epc_ratings["Count"].sum() * # Take properties that are below an EPC C rating, as defined by the guidance and remove any new builds matches = matches[matches["CURRENT_ENERGY_RATING"].isin(["D", "E", "F", "G"])] # 11,694 properties +matches["epc_postcode"].nunique() +# 6899 owners_count = matches.groupby(['Proprietor Name (1)', 'Company Registration No. (1)']).size().reset_index() owners_count.columns = ['Owner', 'Owner Registration #', 'Count'] @@ -111,7 +121,26 @@ owners_count["Percentage"] = owners_count["Count"] / owners_count["Count"].sum() # Take an example postal region matches = matches.sort_values("epc_postcode", ascending=True) -example = matches[matches["epc_postcode"].str.startswith("BR1 ")].copy() +# BR1, BR5 +example = matches[matches["epc_postcode"].str.startswith("CR0 ")].copy() +example = example[example["TENURE"].isin(["rental (private)", "Rented (private)"])] + +pd.set_option('display.max_rows', 500) +pd.set_option('display.max_columns', 500) +pd.set_option('display.width', 1000) +example[ + ["epc_address", "epc_postcode", "CURRENT_ENERGY_RATING", "CURRENT_ENERGY_EFFICIENCY", "Proprietor Name (1)", + "Company Registration No. (1)"] +].head(4) + +ownership.epc_data["UPRN"] = ownership.epc_data["UPRN"].astype(int) +example = example.merge( + ownership.epc_data[["UPRN", "BUILT_FORM", "PROPERTY_TYPE", "WALLS_DESCRIPTION", "ROOF_DESCRIPTION"]], + on="UPRN", + how="left" +) +z = example[example["CURRENT_ENERGY_RATING"] == "E"] +z = z[z["TENURE"].isin(["rental (private)", "Rented (private)"])] companies_house_api_key = "1d9c2877-3271-4642-80ed-a6170971653f"