From 846cd99631923224d4ba8d776bdeaed35b08884a Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Sat, 15 Feb 2025 16:05:57 +0000 Subject: [PATCH] switch off solar PV if property is listed/heritage or in a conservation area --- backend/Property.py | 5 ++++ backend/app/plan/router.py | 6 ++-- etl/customers/lambeth/re-knocks.py | 23 +++++++++++++++ .../stonewater/Wave 3 Preparation.py | 28 +++++++++++++------ etl/route_march_data_pull/app.py | 22 +++++++-------- 5 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 etl/customers/lambeth/re-knocks.py diff --git a/backend/Property.py b/backend/Property.py index a495431f..e19970eb 100644 --- a/backend/Property.py +++ b/backend/Property.py @@ -395,6 +395,7 @@ class Property: primary_recommendation_id=rec["recommendation_id"], non_invasive_recommendations=self.non_invasive_recommendations, ) + self.recommendations_scoring_data.append(scoring_dict) simulation_epc = self.epc_record.prepared_epc.copy() @@ -1258,6 +1259,10 @@ class Property: if (self.building_id is not None) and (self.solar_panel_configuration is not None): return True + # If the property is in a conservation area, don't recommend + if self.restricted_measures: + return False + is_valid_property_type = self.data["property-type"] in ["House", "Bungalow", "Maisonette"] is_valid_roof_type = ( self.roof["is_flat"] or self.roof["is_pitched"] or self.roof["is_roof_room"] diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index f85ceacc..949c8e4c 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -639,8 +639,10 @@ async def trigger_plan(body: PlanTriggerRequest): recommendations_scoring_data = pd.DataFrame(recommendations_scoring_data) recommendations_scoring_data = recommendations_scoring_data.drop( - columns=["rdsap_change", "heat_demand_change", "carbon_change", "sap_ending", "heat_demand_ending", - "carbon_ending"] + columns=[ + "rdsap_change", "heat_demand_change", "carbon_change", "sap_ending", "heat_demand_ending", + "carbon_ending" + ] ) all_predictions = await model_api.async_paginated_predictions( diff --git a/etl/customers/lambeth/re-knocks.py b/etl/customers/lambeth/re-knocks.py new file mode 100644 index 00000000..1de91b50 --- /dev/null +++ b/etl/customers/lambeth/re-knocks.py @@ -0,0 +1,23 @@ +import pandas as pd + +data = pd.read_excel( + "/Users/khalimconn-kowlessar/Downloads/Lambeth Reknocks.xlsx", sheet_name="Possible Route", + header=1 +) + +data["Outcomes"].value_counts() + +# Strip out: No + +df = data[data["Outcomes"] == "See notes"] +notes_df = df[ + ("Notes (If 'no answer' under outcomes, have you checked around the property for access issues where " + "possible?)")].value_counts().to_frame() + +example = df[df["Notes (If 'no answer' under outcomes, have you checked around the property for access issues where " + "possible?)"] == ('Access to rear of property only through number 10. Overgrown athe rear of property ' + 'installer wont be able to access') + ] + +# 18 did not attend +# diff --git a/etl/customers/stonewater/Wave 3 Preparation.py b/etl/customers/stonewater/Wave 3 Preparation.py index 50dadcaf..95fe4fcd 100644 --- a/etl/customers/stonewater/Wave 3 Preparation.py +++ b/etl/customers/stonewater/Wave 3 Preparation.py @@ -4093,7 +4093,9 @@ def revised_model(): 'Main Wall Insulation', 'Secondary Wall Insulation', 'Loft insulation', 'Flat Roof', 'Room in Roof', 'Window Upgrade', 'Door Upgrade', 'Ventilation', 'Main Heating', 'Water Heating', 'Heating Controls', - 'Solar PV', 'Other measures', 'Survey: Current SAP Rating', 'Survey: Current EPC Band', + 'Solar PV', 'Other measures', + 'Survey: Current SAP Rating', + 'Survey: Current EPC Band', 'Survey: Primary Energy Use (kWh/yr)', 'Survey: Primary Energy Use Intensity (kWh/m2/yr)', 'Survey: Number of Storeys', 'Survey: Fuel Bill', @@ -4148,7 +4150,8 @@ def revised_model(): 'Best Match Organisation Reference', 'Survey: Current EPC Band', 'Survey: Current SAP Rating', - "Was Surveyed" + "Was Surveyed", + "match_confidence", ] ].rename( columns={ @@ -4157,11 +4160,13 @@ def revised_model(): 'Survey: Current SAP Rating': "Best Match - Survey: Current SAp Rating" } ).merge( - features[["Organisation Reference", "Walls", "Roofs", "Heating", "Main Fuel", "Age", "Property Type"]], + features[["Organisation Reference", "Walls", "Roofs", "Heating", "Main Fuel", "Age", "Property Type", + "Total Floor Area"]], how="left", on="Organisation Reference" ).merge( - features[["Organisation Reference", "Walls", "Roofs", "Heating", "Main Fuel", "Age", "Property Type"]].rename( + features[["Organisation Reference", "Walls", "Roofs", "Heating", "Main Fuel", "Age", "Property Type", + "Total Floor Area"]].rename( columns={ "Organisation Reference": "Best Match - Organisation Reference", "Walls": "Best Match - Walls", @@ -4169,7 +4174,8 @@ def revised_model(): "Heating": "Best Match - Heating", "Main Fuel": "Best Match - Main Fuel", "Age": "Best Match - Age", - "Property Type": "Best Match - Property Type" + "Property Type": "Best Match - Property Type", + "Total Floor Area": "Best Match - Total Floor Area" } ), how="left", @@ -4180,7 +4186,8 @@ def revised_model(): "Organisation Reference", 'Survey: Main Wall Type', 'Survey: Main Wall Insulation', 'Survey: Main Roof Type', 'Survey: Main Roof Insulation', 'Survey: Main Roof Insulation Thickness', 'Survey: Existing Primary Heating System', 'Survey: Main Building Age Band', - 'Survey: Main Building Wall Area (m2)', + 'Survey: Main Building Wall Area (m2)', 'Survey: Total Floor Area (m2)', + 'Survey: Main Building Age Band', ] ].rename( columns={ @@ -4203,7 +4210,12 @@ def revised_model(): 'Organisation Reference', 'Address', 'Postcode', 'Address ID', 'uprn', 'Archetype ID', 'SAP', 'SAP Band', "Property Type", "Walls", "Roofs", 'Glazing', 'Heating', 'Main Fuel', 'Hot Water', 'Number of matches', 'Proportion', - 'Estimated SAP Rating', 'Estimated EPC Rating', "Was Surveyed" + 'Estimated SAP Rating', 'Estimated EPC Rating', "Was Surveyed", + 'Main Wall Insulation', + 'Secondary Wall Insulation', 'Loft insulation', 'Flat Roof', + 'Room in Roof', 'Window Upgrade', 'Door Upgrade', 'Ventilation', + 'Main Heating', 'Water Heating', 'Heating Controls', 'Solar PV', + 'Other measures', "2 of 3 Data Sources Have Consensus on EPC" ] ].rename( columns={ @@ -4271,7 +4283,7 @@ def revised_model(): worksheet = worksheet.drop(columns=["Last EPC - uprn"]) # Save to Excel with multiple sheets - excel_path = os.path.join(CUSTOMER_FOLDER_PATH, "Jan 2025 Project", "04022025 Stonewater Priority List.xlsx") + excel_path = os.path.join(CUSTOMER_FOLDER_PATH, "Jan 2025 Project", "13022025 Stonewater Priority List.xlsx") with pd.ExcelWriter(excel_path, engine="xlsxwriter") as writer: worksheet.to_excel(writer, sheet_name="Worksheet", index=False, header=True) mapped_lookup.to_excel(writer, sheet_name="Lookup Table", index=False, header=True) diff --git a/etl/route_march_data_pull/app.py b/etl/route_march_data_pull/app.py index dba85b3f..1b937b2d 100644 --- a/etl/route_march_data_pull/app.py +++ b/etl/route_march_data_pull/app.py @@ -258,18 +258,16 @@ def app(): # - We want: fully insulated property (all wall types), EPC D or below (floors should be solid) # - Or the insulation required is loft/cavity (floors should be solid) - DATA_FOLDER = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Eastlight" - DATA_FILENAME = "Eastlight addresses potential PV data pull required.xlsx" - SHEET_NAME = "Sheet1" - POSTCODE_COLUMN = "Postcode" - FULLADDRESS_COLUMN = None - ADDRESS1_COLUMN = "HouseName" + DATA_FOLDER = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Stonewater" + DATA_FILENAME = "Stonewater All Props for EPC Check 10.02.25.xlsx" + SHEET_NAME = "stonewater sap, insta" + POSTCODE_COLUMN = "Post Code" + FULLADDRESS_COLUMN = "Name" + ADDRESS1_COLUMN = "Name" ADDRESS1_METHOD = None - ADDRESS_COLS_TO_CONCAT = [ - "HouseName", "Block", "Address1" - ] + ADDRESS_COLS_TO_CONCAT = [] MISSING_POSTCODES_METHOD = None - PROPERTY_YEAR_BUILT = 'Built In Year' + PROPERTY_YEAR_BUILT = None # Maps addresses to uprn in problematic cases MANUAL_UPRN_MAP = {} @@ -633,7 +631,7 @@ def app(): # We want to deduce if flats have 50% of the properties below C75 # We group by postcode and property type - grouped = asset_list.groupby(["Postcode", "Property Type"]) + grouped = asset_list.groupby([POSTCODE_COLUMN, "Property Type"]) flat_data = [] for _, group in grouped: @@ -643,7 +641,7 @@ def app(): flat_data.append( { - "Postcode": group["Postcode"].iloc[0], + "Postcode": group[POSTCODE_COLUMN].iloc[0], "Property Type": "Flat", "Number of Flats with EPC": num_flats, "Number of Flats below C75": num_below_c75,