diff --git a/.idea/Model.iml b/.idea/Model.iml
index b0f9c00d..4413bb06 100644
--- a/.idea/Model.iml
+++ b/.idea/Model.iml
@@ -7,7 +7,7 @@
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1122b380..6f308057 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/recommendations/Costs.py b/recommendations/Costs.py
index 113bb6f8..fd3c1692 100644
--- a/recommendations/Costs.py
+++ b/recommendations/Costs.py
@@ -37,21 +37,22 @@ MCS_SOLAR_PV_COST_DATA = {
"average_cost_per_kwh-Northern Ireland": 2126.09,
}
-# This data is based on the MCS database
+# This data is based on the MCS database, We use the larger figure between the 2023 and 2024 average,
+# to be conservative
MCS_AIR_SOURCE_HEAT_PUMP_COST_DATA = {
- "Outer London": None,
- "Inner London": None,
- "South East England": None,
- "South West England": None,
- "East of England": None,
- "East Midlands": None,
- "West Midlands": None,
- "North East England": None,
- "North West England": None,
- "Yorkshire and the Humber": None,
- "Wales": None,
- "Scotland": None,
- "Northern Ireland": None,
+ "Outer London": 13220,
+ "Inner London": 13220,
+ "South East England": 13547,
+ "South West England": 12776,
+ "East of England": 12585,
+ "East Midlands": 12239,
+ "West Midlands": 13182,
+ "North East England": 11829,
+ "North West England": 11714,
+ "Yorkshire and the Humber": 11919,
+ "Wales": 13701,
+ "Scotland": 12586,
+ "Northern Ireland": 12000, # There are hardly any air source heat pump installs going on in Northern Ireland
}
BOILER_UPGRADE_SCHEME_ASHP_VALUE = 7500
@@ -1264,8 +1265,23 @@ class Costs:
Based on the region and type of property, this function will produce a cost estimation for an air source heat
pump. This cost will include the boiler upgrade scheme grant
- :return:
"""
+ # This is the average cost of a project, we'll add some additional contingency
regional_cost = MCS_AIR_SOURCE_HEAT_PUMP_COST_DATA[self.region]
- pass
+
+ total_cost = regional_cost * (1 + self.CONTINGENCY) - BOILER_UPGRADE_SCHEME_ASHP_VALUE
+ subtotal_before_vat = total_cost / (1 + self.VAT_RATE)
+ vat = total_cost - subtotal_before_vat
+
+ # We assume 3 days installation
+ labour_days = 3
+ labour_hours = labour_days * 8
+
+ return {
+ "total": total_cost,
+ "subtotal": subtotal_before_vat,
+ "vat": vat,
+ "labour_hours": labour_hours,
+ "labour_days": labour_days,
+ }
diff --git a/recommendations/HeatingRecommender.py b/recommendations/HeatingRecommender.py
index b42a9d5b..a51803f2 100644
--- a/recommendations/HeatingRecommender.py
+++ b/recommendations/HeatingRecommender.py
@@ -16,10 +16,10 @@ class HeatingRecommender:
self.heating_recommendations = []
self.heating_control_recommendations = []
- def recommend(self, has_cavity_and_loft_recommendations, phase=0):
+ def recommend(self, has_cavity_or_loft_recommendations, phase=0):
"""
Produces heating recommendations
- :param has_cavity_and_loft_recommendations: boolean indicating if we have produced a cavity or loft insulation
+ :param has_cavity_or_loft_recommendations: boolean indicating if we have produced a cavity or loft insulation
recommendation. If there are cavity or loft recommendations, the property would need to complete those measures
before being able to get the boiler upgrade scheme benefits. The messaging in the front end would be to
:param phase: indicates the phase of the retrofit programme
@@ -93,17 +93,17 @@ class HeatingRecommender:
# In the future, we'll allow overrides, so that non-intrusive surveys can contradict these conditions
# and either allow or prevent the recommendation of an air source heat pump
- # suitable_property_types = self.property.data["property-type"] in ["House", "Bungalow"]
- # has_air_source_heat_pump = self.property.main_heating["has_air_source_heat_pump"]
- #
- # if suitable_property_types and not has_air_source_heat_pump:
- # self.recommend_air_source_heat_pump(
- # phase=phase, has_cavity_and_loft_recommendations=has_cavity_and_loft_recommendations
- # )
+ suitable_property_type = self.property.data["property-type"] in ["House", "Bungalow"]
+ has_air_source_heat_pump = self.property.main_heating["has_air_source_heat_pump"]
+
+ if suitable_property_type and not has_air_source_heat_pump:
+ self.recommend_air_source_heat_pump(
+ phase=phase, has_cavity_or_loft_recommendations=has_cavity_or_loft_recommendations
+ )
return
- def recommend_air_source_heat_pump(self, phase, has_cavity_and_loft_recommendations):
+ def recommend_air_source_heat_pump(self, phase, has_cavity_or_loft_recommendations):
"""
This method will implement the recommendation for an air source heat pump
This is ultimately an overhaul to the heating system and so is recommended as an alternative to other
@@ -127,20 +127,20 @@ class HeatingRecommender:
else:
if controls_recommender.recommendation:
description = ("Install an air source heat pump, and upgrade heating controls to Smart Thermostats, "
- "room sensors and smart radiator valves (time & temperature zone control) ")
+ "room sensors and smart radiator valves (time & temperature zone control).")
else:
description = "Install an air source heat pump."
# If the property does not have existing cavity and loft insulation, we include a note that the cost
# includes the boiler upgrade scheme and that the cavity and loft need to be treated, to ensure access
# to the funding
- if has_cavity_and_loft_recommendations:
- description = description + (f" The cost of works includes the £"
+ if has_cavity_or_loft_recommendations:
+ description = description + (f" The cost includes the £"
f"{BOILER_UPGRADE_SCHEME_ASHP_VALUE} boiler upgrade scheme grant. "
f"You must ensure that the property has an insulated cavity and "
f"270mm+ loft insulation to qualify for the grant")
else:
- description = description + (f" The cost of works includes the £"
+ description = description + (f" The cost includes the £"
f"{BOILER_UPGRADE_SCHEME_ASHP_VALUE} boiler upgrade scheme grant")
simulation_config = {
@@ -178,6 +178,8 @@ class HeatingRecommender:
if controls_recommender.recommendation:
# We should have just the single recommendation for heat controls, which is time
# and temperature zone controls
+ if len(controls_recommender.recommendation) != 1:
+ raise NotImplementedError("More than one heat controls recommendation for air source heat pump")
simulation_config = {
**simulation_config,
**controls_recommender.recommendation[0]["simulation_config"]
diff --git a/recommendations/Recommendations.py b/recommendations/Recommendations.py
index 1a6d7a1c..0942ab12 100644
--- a/recommendations/Recommendations.py
+++ b/recommendations/Recommendations.py
@@ -109,7 +109,16 @@ class Recommendations:
# Heating and Electical systems
if "heating" not in self.exclusions:
- self.heating_recommender.recommend(phase=phase, has_cavity_and_loft_recommendations=None)
+
+ cavity_or_loft_recommendations = [
+ r for r in self.wall_recomender.recommendations + self.roof_recommender.recommendations
+ if r["type"] in ["cavity_wall_insulation", "loft_insulation"]
+ ]
+ has_cavity_or_loft_recommendations = len(cavity_or_loft_recommendations) > 0
+
+ self.heating_recommender.recommend(
+ phase=phase, has_cavity_or_loft_recommendations=has_cavity_or_loft_recommendations
+ )
if (
self.heating_recommender.heating_recommendations or
self.heating_recommender.heating_control_recommendations