diff --git a/recommendations/Costs.py b/recommendations/Costs.py index 0ef37add..bfca8038 100644 --- a/recommendations/Costs.py +++ b/recommendations/Costs.py @@ -858,7 +858,11 @@ class Costs: "labour_days": labour_days, } - def high_heat_electric_storage_heaters(self, number_heated_rooms, needs_cylinder): + def high_heat_electric_storage_heaters( + self, number_heated_rooms: int, + needs_cylinder: bool, + product: dict | None = None + ): """ We base the estimates for the cost of electric storage heaters on the cost per room as estimated by the @@ -867,18 +871,20 @@ class Costs: The cost is based on the number of heated rooms :param number_heated_rooms: int, number of rooms to be heated + :param needs_cylinder: bool, whether the property needs a hot water cylinder + :param product: dict, product data containing costs of heaters """ if needs_cylinder: - # 1000 is the cost of a new hot water cylinder - total_cost = 1300 * number_heated_rooms + 1000 + # 1500 is the cost of a new hot water cylinder + total_cost = product["total_cost"] * number_heated_rooms + 1500 else: # 500 is the cost of a dual immersion heater - a rough estimate - total_cost = 1300 * number_heated_rooms + 500 + total_cost = product["total_cost"] * number_heated_rooms + 500 + subtotal_before_vat = total_cost / (1 + self.VAT_RATE) vat = total_cost - subtotal_before_vat - # TODO: Rough estimate to be reviewed labour_hours = 3 * number_heated_rooms labour_days = np.ceil(labour_hours / 8) diff --git a/recommendations/HeatingControlRecommender.py b/recommendations/HeatingControlRecommender.py index bd015a79..aaebde9e 100644 --- a/recommendations/HeatingControlRecommender.py +++ b/recommendations/HeatingControlRecommender.py @@ -93,7 +93,8 @@ class HeatingControlRecommender: "measure_type": "programmer_appliance_thermostat", "description": "upgrade heating controls to Programmer and Appliance or Smart Thermostats", **self.costs.programmer_and_appliance_thermostat(has_programmer=has_programmer), - "simulation_config": simulation_config + "simulation_config": simulation_config, + "innovation_rate": 0.0, } ) @@ -142,7 +143,8 @@ class HeatingControlRecommender: "description": "Upgrade heating controls to High Heat Retention Storage Heater Controls", **self.costs.celect_type_controls(), "simulation_config": simulation_config, - "description_simulation": description_simulation + "description_simulation": description_simulation, + "innovation_rate": 0.0, } ) @@ -232,7 +234,8 @@ class HeatingControlRecommender: "sap_points": None, "already_installed": already_installed, "simulation_config": simulation_config, - "description_simulation": description_simulation + "description_simulation": description_simulation, + "innovation_rate": 0.0 } ) @@ -307,7 +310,8 @@ class HeatingControlRecommender: "sap_points": None, "already_installed": already_installed, "simulation_config": simulation_config, - "description_simulation": description_simulation + "description_simulation": description_simulation, + "innovation_rate": 0.0 } ) diff --git a/recommendations/HeatingRecommender.py b/recommendations/HeatingRecommender.py index 9d1a094e..baeee1d5 100644 --- a/recommendations/HeatingRecommender.py +++ b/recommendations/HeatingRecommender.py @@ -85,7 +85,7 @@ class HeatingRecommender: } } - def __init__(self, property_instance: Property): + def __init__(self, property_instance: Property, materials: list = None): self.property = property_instance self.costs = Costs(self.property) @@ -103,6 +103,11 @@ class HeatingRecommender: self.dual_heating = self.identify_dual_heating() + # Split out the different materials + self.hhrsh_products = [ + product for product in materials if product["type"] == "high_heat_retention_storage_heaters" + ] + def identify_dual_heating(self): # All heat systems are in here so we identify whether two of these are true # MainHeatAttributes.HEAT_SYSTEMS @@ -678,7 +683,7 @@ class HeatingRecommender: heating_controls_only, system_change, system_type, - measure_type, + heating_product, non_intrusive_recommendation=None ): """ @@ -695,8 +700,7 @@ class HeatingRecommender: current system. If we have a system change and we have a heat control recommendation, we only recommend both heating and controls together :param system_type: The type of heating system we are recommending - :param measure_type: The type of measure we are recommending - more granular than the "type" field, allowing us - to distinguish between different types of heating recommendations + :param heating_product: The heating product we are recommending, used to determine the system type :param non_intrusive_recommendation: A non-intrusive recommendation, which may specify the number of SAP points or a cost for this recommendation """ @@ -747,7 +751,7 @@ class HeatingRecommender: "phase": phase, "parts": [], "type": "heating", - "measure_type": measure_type, + "measure_type": heating_product["type"], "description": recommendation_description, "starting_u_value": None, "new_u_value": None, @@ -758,7 +762,10 @@ class HeatingRecommender: "description_simulation": recommendation_description_simulation, # We insert the heating system type here "system_type": system_type, - "survey": non_intrusive_recommendation.get("survey", False) + "survey": non_intrusive_recommendation.get("survey", False), + # In this instance, we are recommending an entire heating system so the innovation rate is becased + # on the heating system as whole + "innovation_rate": heating_product["innovation_rate"], } output.append(recommendation) @@ -921,10 +928,14 @@ class HeatingRecommender: if (number_heated_rooms == 1) and (self.property.number_of_rooms > 2): number_heated_rooms = self.property.number_of_rooms - 1 + # We focus on the 700 watt product + hhrsh_product = next((x for x in self.hhrsh_products if x["size"] == 700), {}) + # Upgrade to electric storage heaters costs = self.costs.high_heat_electric_storage_heaters( number_heated_rooms=number_heated_rooms, - needs_cylinder=self.property.hotwater["system_type"] == "from main system" + needs_cylinder=self.property.hotwater["system_type"] == "from main system", + product=hhrsh_product ) if self.dual_heating: description = self.DUAL_HEATING_DESCRIPTIONS[ @@ -960,8 +971,8 @@ class HeatingRecommender: heating_controls_only=heating_controls_only, system_change=system_change, system_type="high_heat_retention_storage_heater", - measure_type="high_heat_retention_storage_heater", - non_intrusive_recommendation=non_intrusive_recommendation + non_intrusive_recommendation=non_intrusive_recommendation, + heating_product=hhrsh_product ) if _return: return recommendations