update flat roof insulation recommendations

This commit is contained in:
Khalim Conn-Kowlessar 2024-09-24 14:35:35 +01:00
parent 0c6d8121c2
commit e6fc34741c
3 changed files with 12 additions and 113 deletions

View file

@ -290,9 +290,9 @@ class Costs:
"labour_days": labour_days
}
def loft_insulation(self, floor_area, material):
def loft_and_flat_insulation(self, floor_area, material):
"""
Calculates the total cost for cavity wall insulation based on material and labor costs,
Calculates the total cost for loft/flat roof insulation based on material and labor costs,
including contingency, preliminaries, profit, and VAT.
:return: A dictionary containing detailed cost breakdown.
@ -624,92 +624,6 @@ class Costs:
"labour_cost": labour_cost
}
def flat_roof_insulation(self, floor_area, material, non_insulation_materials):
"""
A model of a warm, flat roof construction can be seen in this video:
https://www.youtube.com/watch?v=WZ6Ng6YI9OA
Warm, flat roof insulation will normally be 100-125mm in depth
We break this measure down into the following jobs to be done
1) Preparation of the room. This involves cleaning the existing roof surface, removing any debris and repairing
any damage. Additionally, an edge barrier will likely need to be installed, to protect the sides of the
roof from water ingress.
2) Primer Application. A layer of primer is applied to the clean roof surface to enhance the adhestia of
subsequent layers, and seal the existing roof surface.
3) Vapour Proof Layer Installation. Lay a vapour control layer to prevent moisture ingress from inside the
building, which is essential in warm roof construction.
4) Insulation Layer Application. Place and securely fix insulation boards over the roof. These could be rigid
boards like PIR (Polyisocyanurate).
5) Waterproofing Membrane Installation: Cover the insulation (and timber layer, if used) with a
waterproofing membrane, like EPDM, PVC, or bituminous felt. Carefully seal all joints, edges, and around any
roof penetrations to ensure water tightness
:param floor_area: Area of the flat roof to be insulated, based on the area of the floor
:param material: Selected insulation material
:param non_insulation_materials: Non-insulation materials required for the job
:return:
"""
preparation_data_m2 = [
x for x in non_insulation_materials if
(x["type"] == "flat_roof_preparation") and (x["cost_unit"] == "gbp_per_m2")
]
vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "flat_roof_vapour_barrier"]
waterproofing_data = [x for x in non_insulation_materials if x["type"] == "flat_roof_waterproofing"]
if (len(preparation_data_m2) != 2) or (len(vapour_barrier_data) != 1) or (
len(waterproofing_data) != 1):
raise ValueError("Incorrect number of data entries for non-insulation materials")
# Break out the individual material costs
preparation_m2_material_costs = sum([x["material_cost"] * floor_area for x in preparation_data_m2])
vapour_barrier_material_costs = vapour_barrier_data[0]["material_cost"] * floor_area
insulation_material_costs = material["material_cost"] * floor_area
preparation_m2_labour_costs = sum([x["labour_cost"] * floor_area for x in preparation_data_m2])
vapour_barrier_labour_costs = vapour_barrier_data[0]["labour_cost"] * floor_area
# For waterproofing and upstand, we only have a total cost
waterproofing_total_costs = waterproofing_data[0]["total_cost"] * floor_area
labour_costs = preparation_m2_labour_costs + vapour_barrier_labour_costs
labour_costs = labour_costs * self.labour_adjustment_factor
materials_costs = preparation_m2_material_costs + vapour_barrier_material_costs + insulation_material_costs
subtotal_before_profit = labour_costs + materials_costs + waterproofing_total_costs
contingency_cost = subtotal_before_profit * self.FLAT_ROOF_CONTINGENCY
preliminaries_cost = subtotal_before_profit * self.PRELIMINARIES
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
preparation_m2_labour_hours = sum([x["labour_hours_per_unit"] * floor_area for x in preparation_data_m2])
vapour_barrier_labour_hours = vapour_barrier_data[0]["labour_hours_per_unit"] * floor_area
waterproofing_labour_hours = waterproofing_data[0]["labour_hours_per_unit"] * floor_area
labour_hours = preparation_m2_labour_hours + vapour_barrier_labour_hours + waterproofing_labour_hours
# To install flat roof insulation, assume a small/medium project might be conducted by a team of 2-4.
# We'll assume a team of 2 since a lot of the roofs will be on the smaller side and will review this later
labour_days = (labour_hours / 8) / 2
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 window_glazing(self, number_of_windows, material, is_secondary_glazing=False):
"""
We characterise the jobs to be done for window glazing as the following:

View file

@ -9,7 +9,7 @@ class FireplaceRecommendations(Definitions):
"""
# This is our base assumption for the cost of the work
COST_OF_WORK = 300
COST_OF_WORK = 235
def __init__(
self,

View file

@ -46,19 +46,12 @@ class RoofRecommendations:
self.loft_insulation_materials = [
part for part in materials if (part["type"] == "loft_insulation") and (part["is_installer_quote"])
]
self.loft_non_insulation_materials = []
# We don't have proper installer quotes for flat roof insulation
self.flat_roof_insulation_materials = [
part for part in materials if part["type"] == "flat_roof_insulation"
]
self.flat_roof_non_insulation_materials = [
part for part in materials if part["type"] in [
"flat_roof_preparation", "flat_roof_vapour_barrier", "flat_roof_waterproofing"
]
]
# Extract the insulation thickness from the roof, which is used throughout this method
self.insulation_thickness = convert_thickness_to_numeric(
self.property.roof["insulation_thickness"],
@ -252,10 +245,8 @@ class RoofRecommendations:
if is_pitched:
insulation_materials = self.loft_insulation_materials
non_insulation_materials = self.loft_non_insulation_materials
elif is_flat:
insulation_materials = self.flat_roof_insulation_materials
non_insulation_materials = self.flat_roof_non_insulation_materials
else:
raise ValueError("Roof is not pitched or flat")
@ -297,14 +288,16 @@ class RoofRecommendations:
if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value)
cost_result = self.costs.loft_and_flat_insulation(
floor_area=self.property.insulation_floor_area,
material=material
)
already_installed = material["type"] in self.property.already_installed
if already_installed:
cost_result = override_costs(cost_result)
if material["type"] == "loft_insulation":
cost_result = self.costs.loft_insulation(
floor_area=self.property.insulation_floor_area,
material=material
)
already_installed = "loft_insulation" in self.property.already_installed
if already_installed:
cost_result = override_costs(cost_result)
new_thickness = insulation_thickness + material["depth"]
# This is based on the values we have in the training data
@ -341,14 +334,6 @@ class RoofRecommendations:
new_description = f"Pitched, {int(proposed_depth)}mm loft insulation"
elif material["type"] == "flat_roof_insulation":
cost_result = self.costs.flat_roof_insulation(
floor_area=self.property.insulation_floor_area,
material=material,
non_insulation_materials=non_insulation_materials
)
already_installed = "flat_roof_insulation" in self.property.already_installed
if already_installed:
cost_result = override_costs(cost_result)
new_description = "Flat, insulated"
new_efficiency = "Good"
else: