diff --git a/.idea/Model.iml b/.idea/Model.iml
index df6c4faa..762580d9 100644
--- a/.idea/Model.iml
+++ b/.idea/Model.iml
@@ -7,7 +7,7 @@
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 50cad4ca..c916a158 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py
index 4a5b3bd4..dbef6435 100644
--- a/backend/app/plan/router.py
+++ b/backend/app/plan/router.py
@@ -366,7 +366,7 @@ def extract_property_request_data(
property_non_invasive_recommendations["recommendations"] = str(transformed)
property_valution = next((
- float(x["value"]) for x in valuation_data if
+ float(x["valuation"]) for x in valuation_data if
(str(x["uprn"]) == str(uprn))
), None)
@@ -611,6 +611,7 @@ async def trigger_plan(body: PlanTriggerRequest):
property_instance=property_instance,
all_predictions=all_predictions,
recommendations=recommendations,
+ representative_recommendations=representative_recommendations
)
)
diff --git a/etl/customers/cottons/remote_assessments.py b/etl/customers/cottons/remote_assessments.py
index 6ac895f1..7855a1a9 100644
--- a/etl/customers/cottons/remote_assessments.py
+++ b/etl/customers/cottons/remote_assessments.py
@@ -10,8 +10,8 @@ from utils.s3 import save_csv_to_s3
load_dotenv(dotenv_path="backend/.env")
EPC_AUTH_TOKEN = os.getenv("EPC_AUTH_TOKEN")
-PORTFOLIO_ID = 121
USER_ID = 8
+PORTFOLIO_ID = 121
def app():
@@ -22,7 +22,8 @@ def app():
# Read in the asset list
cottons_asset_list = pd.read_excel(
- "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Cottons/Cottons Asset List EPC Data Pull.xlsx"
+ "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Cottons/Cottons Asset List EPC Data Pull with "
+ "valuations.xlsx"
)
# A number are missing EPCs due to the space in the postcode
# Breakdowns:
@@ -79,6 +80,9 @@ def app():
} for r in extracted_data
]
+ valuations_data = asset_list[["uprn", "Zoopla Valuation"]].copy().rename(columns={"Zoopla Valuation": "valuation"})
+ valuations_data = valuations_data[~pd.isnull(valuations_data["valuation"])]
+
filename = f"{USER_ID}/{PORTFOLIO_ID}/asset_list.csv"
save_csv_to_s3(
dataframe=pd.DataFrame(model_asset_list),
@@ -94,6 +98,14 @@ def app():
file_name=non_invasive_recommendations_filename
)
+ # Store the valuations data in s3
+ valuations_filename = f"{USER_ID}/{PORTFOLIO_ID}/valuations.csv"
+ save_csv_to_s3(
+ dataframe=valuations_data,
+ bucket_name="retrofit-plan-inputs-dev",
+ file_name=valuations_filename
+ )
+
body = {
"portfolio_id": str(PORTFOLIO_ID),
"housing_type": "Social",
@@ -103,9 +115,10 @@ def app():
"already_installed_file_path": "",
"patches_file_path": "",
"non_invasive_recommendations_file_path": non_invasive_recommendations_filename,
- "valuation_file_path": "",
+ "valuation_file_path": valuations_filename,
"scenario_name": "Wave 3 Packages",
"multi_plan": True,
"budget": None,
+ "exclusions": ['air_source_heat_pump', 'boiler_upgrade', 'floor_insulation']
}
print(body)
diff --git a/etl/find_my_epc/RetrieveFindMyEpc.py b/etl/find_my_epc/RetrieveFindMyEpc.py
index 4db72b23..3dd486b3 100644
--- a/etl/find_my_epc/RetrieveFindMyEpc.py
+++ b/etl/find_my_epc/RetrieveFindMyEpc.py
@@ -282,7 +282,8 @@ class RetrieveFindMyEpc:
"Low energy lighting for all fixed outlets": ["low_energy_lighting"],
"Cylinder thermostat recommendation": [],
"Heating controls recommendation": [],
- "Replace boiler with Band A condensing boiler": [],
+ "Replace boiler with Band A condensing boiler": ["boiler_upgrade"],
+ "Band A condensing gas boiler": ["boiler_upgrade"],
"Solar panel recommendation": [],
"Double glazing recommendation": [],
"Solid wall insulation recommendation": [],
@@ -296,6 +297,17 @@ class RetrieveFindMyEpc:
"Cylinder thermostat": ["cylinder_thermostat"],
"Heat recovery system for mixer showers": ["heat_recovery_shower"],
"Room-in-roof insulation": ["room_in_roof_insulation"],
+ "Fan assisted storage heaters": [],
+ "Fan-assisted storage heaters": [],
+ "Step 1:": [],
+ "Biomass stove with boiler": [],
+ "Replace boiler with biomass boiler": [],
+ "Heating controls (room thermostat and thermostatic radiator valves)": [
+ "roomstat_programmer_trvs", "time_temperature_zone_control"
+ ],
+ "Heating controls (programmer, and thermostatic radiator valves)": [
+ "roomstat_programmer_trvs", "time_temperature_zone_control"
+ ],
}
survey = True
diff --git a/etl/route_march_data_pull/app.py b/etl/route_march_data_pull/app.py
index 0f3e0068..11dd19b8 100644
--- a/etl/route_march_data_pull/app.py
+++ b/etl/route_march_data_pull/app.py
@@ -25,6 +25,7 @@ def get_data(asset_list, fulladdress_column, address1_column, postcode_column):
epc_data = []
errors = []
no_epc = []
+ # home = asset_list[asset_list["row_id"] == errors[15]].squeeze()
for _, home in tqdm(asset_list.iterrows(), total=len(asset_list)):
try:
postcode = home[postcode_column]
@@ -94,7 +95,7 @@ def get_data(asset_list, fulladdress_column, address1_column, postcode_column):
)
find_epc_data = find_epc_searcher.retrieve_newest_find_my_epc_data()
except ValueError as e:
- if "No EPC found" in str(e):
+ if "No EPC found" in str(e) and "address1" in searcher.newest_epc:
find_epc_searcher = RetrieveFindMyEpc(
address=searcher.newest_epc["address1"], postcode=searcher.newest_epc["postcode"]
)
@@ -151,17 +152,17 @@ def app():
Property UPRN
"""
- DATA_FOLDER = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Cottons/"
- DATA_FILENAME = "Cottons Asset List.xlsx"
- SHEET_NAME = "Sheet1"
- POSTCODE_COLUMN = "postcode"
- FULLADDRESS_COLUMN = "Property Address"
- ADDRESS1_COLUMN = "address1"
- ADDRESS1_METHOD = None
- ADDRESS_COLS_TO_CONCAT = []
+ DATA_FOLDER = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Bromford"
+ DATA_FILENAME = "BROMFORD - SOLAR PV ROOFs INSPECTED - Electric only properties getting to C list.xlsx"
+ SHEET_NAME = "MAIN"
+ POSTCODE_COLUMN = "Post Code"
+ FULLADDRESS_COLUMN = "Full Address"
+ ADDRESS1_COLUMN = None
+ ADDRESS1_METHOD = "first_two_words"
+ ADDRESS_COLS_TO_CONCAT = ["House No", "Street", "District"]
asset_list = pd.read_excel(os.path.join(DATA_FOLDER, DATA_FILENAME), header=0, sheet_name=SHEET_NAME)
- # asset_list = asset_list[~pd.isnull(asset_list[POSTCODE_COLUMN])].reset_index()
+ asset_list = asset_list[~pd.isnull(asset_list[POSTCODE_COLUMN])].reset_index()
asset_list["row_id"] = asset_list.index
# We clean up portential non-breaking spaces, and double spaces
@@ -249,6 +250,8 @@ def app():
[
"row_id",
"uprn",
+ "address1",
+ "postcode",
"property-type",
"built-form",
"inspection-date",
@@ -256,6 +259,7 @@ def app():
"current-energy-efficiency",
"roof-description",
"walls-description",
+ "floor-description",
"transaction-type",
# New fields needed
"secondheat-description",
@@ -268,7 +272,7 @@ def app():
"energy-consumption-current", # kwh/m2
"photo-supply",
]
- ]
+ ].rename(columns={"address1": "Address1 on EPC", "postcode": "Postcode on EPC"})
asset_list = asset_list.merge(
epc_df,
@@ -308,6 +312,7 @@ def app():
"number-habitable-rooms": "Number of Habitable Rooms",
"walls-description": "Wall Construction",
"roof-description": "Roof Construction",
+ "floor-description": "Floor Construction",
"mainheat-description": "Heating Type",
"secondheat-description": "Secondary Heating",
"transaction-type": "Reason for last EPC",
@@ -363,3 +368,7 @@ def app():
# Store as an excel
filename = os.path.join(DATA_FOLDER, ".".join(DATA_FILENAME.split(".")[:-1])) + " EPC Data Pull.xlsx"
asset_list.to_excel(filename, index=False)
+
+ matches_review = asset_list[
+ [FULLADDRESS_COLUMN, ADDRESS1_COLUMN, POSTCODE_COLUMN, "Address1 on EPC", "Postcode on EPC"]
+ ]
diff --git a/recommendations/HeatingRecommender.py b/recommendations/HeatingRecommender.py
index a4443bad..1eab7d42 100644
--- a/recommendations/HeatingRecommender.py
+++ b/recommendations/HeatingRecommender.py
@@ -1111,17 +1111,14 @@ class HeatingRecommender:
if not controls_recommender.recommendation and not boiler_recommendation:
return
- # If this is true, we set SAP points to None and survey to False for the boiler recommendation
- if boiler_recommendation:
- boiler_recommendation["sap_points"] = None
- boiler_recommendation["survey"] = False
-
if not system_change and len(boiler_recommendation):
# If there is not a system change, we add the boiler recommendation at point.
self.heating_recommendations.extend([boiler_recommendation])
if system_change:
# We combine the heating and controls recommendations, in the case of a system change
+ # If this is true, we set SAP points to None and survey to False for the boiler recommendation
+
combined_recommendations = []
for controls_recommendation in controls_recommender.recommendation:
combined_recommendation = self.combine_heating_and_controls(
diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py
index ed6a8526..189581d8 100644
--- a/recommendations/Recommendations.py
+++ b/recommendations/Recommendations.py
@@ -311,7 +311,7 @@ class Recommendations:
continue
has_u_value = recommendations_by_type[0].get("new_u_value") is not None
- has_sap_points = recommendations_by_type[0].get("sap_points") is not None
+ has_sap_points = all([r.get("sap_points") is not None for r in recommendations_by_type])
has_rank = recommendations_by_type[0].get("rank") is not None
# When check if these recommendations have two different types, such as solid wall insulation
@@ -449,6 +449,7 @@ class Recommendations:
property_instance,
all_predictions,
recommendations,
+ representative_recommendations,
):
"""
@@ -473,6 +474,9 @@ class Recommendations:
property_recommendations = recommendations[property_instance.id].copy()
+ representative_recs = representative_recommendations[property_instance.id].copy()
+ representative_ids = [r["recommendation_id"] for r in representative_recs]
+
increasing_variables = ["sap"]
decreasing_variables = ["carbon", "heat_demand"]
@@ -530,7 +534,9 @@ class Recommendations:
else:
- previous_phase_values_multiple = [x for x in impact_summary if x["phase"] == (rec["phase"] - 1)]
+ previous_phase_values_multiple = [
+ x for x in impact_summary if x["phase"] == (rec["phase"] - 1) and x["representative"]
+ ]
if len(previous_phase_values_multiple) != 1:
# Take an average of each of the previous phases
keys_to_median = ["sap", "carbon", "heat_demand"]
@@ -628,7 +634,9 @@ class Recommendations:
impact_summary.append(
{
"phase": rec["phase"],
+ "representative": rec["recommendation_id"] in representative_ids,
"recommendation_id": rec["recommendation_id"],
+ "measure_type": rec["measure_type"],
**current_phase_values
}
)