diff --git a/recommendations/Costs.py b/recommendations/Costs.py index c71316ad..101de0dd 100644 --- a/recommendations/Costs.py +++ b/recommendations/Costs.py @@ -364,26 +364,9 @@ class Costs: "labour_days": labour_days } - def internal_wall_insulation(self, wall_area, material): + def solid_wall_insulation(self, wall_area, material): """ - Broadly speaking, the high level steps to an internal wall insulation job are the following: - - 1) Demolition: This involves removing existing wall linings, fittings, and any other obstacles. - It's important to factor in the disposal of debris and the potential need for additional protective - measures to ensure the safety of the work area. - - 2) Insulation Installation: This is the core part of the process where the chosen insulation material is - applied. The choice of insulation material will depend on several factors including thermal performance, - wall construction, and space constraints. - - 3) Vapour Barrier Installation: This is crucial for preventing moisture from penetrating the insulation, - which can compromise its effectiveness and lead to mold growth. - - 4) Re-decoration: This involves applying plaster to the wall and then painting. - The quality of finish here is important for both aesthetic and functional reasons. - - 5) Trim and Finishing Work: Post-insulation, tasks such as re-installing skirting boards, door frames, - or window sills might be necessary. + Implements costing methodology now that we have direct quotes from installers. :return: """ @@ -638,151 +621,6 @@ class Costs: "labour_cost": labour_costs } - def external_wall_insulation(self, wall_area, material, non_insulation_materials): - """ - We characterise external wall insulation as the following steps: - - 1) Preparation of the Area: Tidying up the surroundings, trimming back foliage, and laying down protective - sheets to protect the flooring and landscaping around the work area. - - 2) Scaffolding Setup (if needed): Erecting scaffolding for safe access to the walls of semi-detached or - detached houses. For terraced houses or lower-level work, scaffolding might not be necessary. - - 3) Wall Surface Preparation: Cleaning the wall surface, removing any loose or flaking material, - and possibly applying a primer. If the existing wall is weak or damaged, partial or full replacement - of the top surface may be necessary. - - 4) Applying Primer: If the existing wall is suitable, applying a primer to improve adhesion of the insulation - boards and stabilize the wall surface, especially if it's old or weathered. - - 5) Insulation Application: Attaching insulation boards to the primed wall using adhesive, mechanical fixings, - or a combination of both. - - 6) Basecoat and Mesh Application: Applying a basecoat embedded with a reinforcing mesh over the insulation. - This layer provides strength and helps prevent cracking. - - 7) Decorative Finish: Applying a decorative finish, such as render or cladding, which protects the insulation - and provides an aesthetic look. - - 8) Reinstalling Fixtures: Reattaching any fixtures like downpipes, satellite dishes, or lighting fixtures that - were removed during preparation. Extensions or adjustments may be required due to the increased wall thickness. - - 9) Inspection and Cleanup: Conducting a thorough inspection to ensure quality and integrity of the EWI system, - followed by cleaning up the site to remove all debris and materials. - - In the actual materials data, at this point, we have costing for: - - wall preparation, hacking off existing wall finishes, linings, etc (ewi_wall_demolition) - - wall surface cleaning and priming (ewi_wall_preparation) - - insulation (external_wall_insulation) - - basecoat and mesh with decorative render topcoat finish (ewi_basecoat_and_mesh) - - All of this data comes from SPONS, however there are some clear features missing. Because we could not find - suitable cost records in SPONS for steps like cleaning the area, setting up small scale scaffolding, - re-attaching any fitings and cleaning up the area afterwards, instead we have accounted for these steps by - increasing the preliminaries rate. It is acknowldeged though, that this is not ideal and that the cost of these - steps should be included in the materials data. We will look to improve this in the future, with data from - installers - - :param wall_area: - :param material: - :param non_insulation_materials: - :return: - """ - - if material["is_installer_quote"]: - total_cost = material["total_cost"] * wall_area - # Add on a buffer for scaffolding - if self.property.data["property-type"] == "House": - total_cost += self.EWI_SCAFFOLDING_PRELIMINARIES * total_cost - - labour_hours = material["labour_hours_per_unit"] * wall_area - - # To install internal wall insulation, a small to medium size project might be conducted by a team of 3-5 - # people - labour_days = (labour_hours / 8) / 4 - - return { - "total": total_cost, - "labour_hours": labour_hours, - "labour_days": labour_days, - } - - # For semi detatched and detatched houses, as well as maisonettes, we price for scaffolding - - if self.property.data["property-type"] == "House": - if self.property.data["built-form"] in ['Semi-Detached', 'Detached', "End-Terrace"]: - preliminaries_rate = self.EWI_SCAFFOLDING_PRELIMINARIES - else: - preliminaries_rate = self.EWI_NO_SCAFFOLDING_PRELIMINARIES - elif self.property.data["property-type"] in ["Maisonette", "Flat"]: - preliminaries_rate = self.EWI_SCAFFOLDING_PRELIMINARIES - elif self.property.data["property-type"] == "Bungalow": - preliminaries_rate = self.EWI_NO_SCAFFOLDING_PRELIMINARIES - - demolition_data = [x for x in non_insulation_materials if x["type"] == "ewi_wall_demolition"] - preparation_data = [x for x in non_insulation_materials if x["type"] == "ewi_wall_preparation"] - redecoration_data = [x for x in non_insulation_materials if x["type"] == "ewi_wall_redecoration"] - - if (len(demolition_data) != 3) or (len(preparation_data) != 1) or (len(redecoration_data) != 1): - raise ValueError("Incorrect number of data entries for non-insulation materials") - - # Break out the individual material costs - # Since we don't know the exact wall construction, we take an average for demolition costs, since - # the cost will depend on the type of wall construction - demolition_material_costs = np.mean([x["material_cost"] * wall_area for x in demolition_data]) - insulation_material_costs = material["material_cost"] * wall_area - preparation_material_costs = preparation_data[0]["material_cost"] * wall_area - redecoration_material_costs = redecoration_data[0]["material_cost"] * wall_area - - demolition_plant_costs = np.mean([x["plant_cost"] * wall_area for x in demolition_data]) - - demolition_labour_costs = np.mean([x["labour_cost"] * wall_area for x in demolition_data]) - insulation_labour_costs = material["labour_cost"] * wall_area - preparation_labour_costs = preparation_data[0]["labour_cost"] * wall_area - redecoration_labour_costs = redecoration_data[0]["labour_cost"] * wall_area - - labour_costs = (demolition_labour_costs + insulation_labour_costs + redecoration_labour_costs + - preparation_labour_costs) - - labour_costs = labour_costs * self.labour_adjustment_factor - - materials_costs = (demolition_material_costs + insulation_material_costs + preparation_material_costs + - redecoration_material_costs) - - subtotal_before_profit = labour_costs + materials_costs + demolition_plant_costs - - contingency_cost = subtotal_before_profit * self.CONTINGENCY - preliminaries_cost = subtotal_before_profit * preliminaries_rate - profit_cost = subtotal_before_profit * self.PROFIT_MARGIN - - subtotal_before_vat = subtotal_before_profit + contingency_cost + preliminaries_cost + profit_cost - vat_cost = subtotal_before_vat * self.VAT_RATE - total_cost = subtotal_before_vat + vat_cost - - demolition_labour_hours = np.mean([x["labour_hours_per_unit"] * wall_area for x in demolition_data]) - insulation_labour_hours = material["labour_hours_per_unit"] * wall_area - preparation_labour_hours = preparation_data[0]["labour_hours_per_unit"] * wall_area - redecoration_labour_hours = redecoration_data[0]["labour_hours_per_unit"] * wall_area - - labour_hours = (demolition_labour_hours + insulation_labour_hours + redecoration_labour_hours + - preparation_labour_hours) - - # Assume a team of 3-5 people for a small to medium size project - labour_days = (labour_hours / 8) / 4 - - return { - "total": total_cost, - "subtotal": subtotal_before_vat, - "vat": vat_cost, - "contingency": contingency_cost, - "preliminaries": preliminaries_cost, - "material": materials_costs, - "profit": profit_cost, - "labour_hours": labour_hours, - "labour_days": labour_days, - "labour_cost": labour_costs - } - def low_energy_lighting(self, number_of_lights, number_current_lel_lights, material): """ diff --git a/recommendations/WallRecommendations.py b/recommendations/WallRecommendations.py index 0ddd7b0b..1c483bff 100644 --- a/recommendations/WallRecommendations.py +++ b/recommendations/WallRecommendations.py @@ -172,7 +172,6 @@ class WallRecommendations(Definitions): ewi_recommendations = self._find_insulation( u_value=u_value, insulation_materials=pd.DataFrame(self.external_wall_insulation_materials), - non_insulation_materials=self.external_wall_non_insulation_materials, phase=phase ) @@ -437,7 +436,7 @@ class WallRecommendations(Definitions): return simulation_config - def _find_insulation(self, u_value, insulation_materials, non_insulation_materials, phase): + def _find_insulation(self, u_value, insulation_materials, phase): lowest_selected_u_value = None recommendations = [] @@ -482,6 +481,11 @@ class WallRecommendations(Definitions): lowest_selected_u_value, new_u_value ) + cost_result = self.costs.solid_wall_insulation( + wall_area=self.property.insulation_wall_area, + material=material.to_dict(), + ) + if material["type"] == "internal_wall_insulation": if iwi_non_invasive_recommendations.get("cost") is not None: @@ -492,10 +496,6 @@ class WallRecommendations(Definitions): sap_points = iwi_non_invasive_recommendations.get("sap_points", None) survey = iwi_non_invasive_recommendations.get("survey", False) - cost_result = self.costs.internal_wall_insulation( - wall_area=self.property.insulation_wall_area, - material=material.to_dict(), - ) already_installed = ( "internal_wall_insulation" in self.property.already_installed @@ -511,12 +511,7 @@ class WallRecommendations(Definitions): sap_points = ewi_non_invasive_recommendations.get("sap_points", None) survey = ewi_non_invasive_recommendations.get("survey", False) - - cost_result = self.costs.external_wall_insulation( - wall_area=self.property.insulation_wall_area, - material=material.to_dict(), - non_insulation_materials=non_insulation_materials, - ) + already_installed = ( "external_wall_insulation" in self.property.already_installed @@ -594,7 +589,6 @@ class WallRecommendations(Definitions): insulation_materials=pd.DataFrame( self.external_wall_insulation_materials ), - non_insulation_materials=self.external_wall_non_insulation_materials, phase=phase, )