refactoring costing function for solid wall insulation|

This commit is contained in:
Khalim Conn-Kowlessar 2024-09-23 15:57:06 +01:00
parent 767d0d3132
commit fe86886adc
2 changed files with 9 additions and 177 deletions

View file

@ -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):
"""

View file

@ -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,
)