mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
tested iwi costs
This commit is contained in:
parent
824b92fedd
commit
11ba4c64d0
5 changed files with 153 additions and 121 deletions
|
|
@ -82,6 +82,7 @@ class Property(Definitions):
|
||||||
self.insulation_wall_area = None
|
self.insulation_wall_area = None
|
||||||
self.floor_area = None
|
self.floor_area = None
|
||||||
self.pitched_roof_area = None
|
self.pitched_roof_area = None
|
||||||
|
self.insulation_floor_area = None
|
||||||
|
|
||||||
if epc_client:
|
if epc_client:
|
||||||
self.epc_client = epc_client
|
self.epc_client = epc_client
|
||||||
|
|
@ -619,8 +620,10 @@ class Property(Definitions):
|
||||||
built_form=self.data["built-form"],
|
built_form=self.data["built-form"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.insulation_floor_area = self.floor_area / self.number_of_floors
|
||||||
|
|
||||||
self.pitched_roof_area = esimtate_pitched_roof_area(
|
self.pitched_roof_area = esimtate_pitched_roof_area(
|
||||||
floor_area=self.floor_area / self.number_of_floors, floor_height=self.floor_height
|
floor_area=self.insulation_floor_area, floor_height=self.floor_height
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_wall_type(self):
|
def set_wall_type(self):
|
||||||
|
|
|
||||||
|
|
@ -160,19 +160,7 @@ class Costs:
|
||||||
|
|
||||||
:return: A dictionary containing detailed cost breakdown.
|
:return: A dictionary containing detailed cost breakdown.
|
||||||
"""
|
"""
|
||||||
# Cost per m2
|
|
||||||
# material = {
|
|
||||||
# "description": "Crown Loft Roll 44 glass fibre roll",
|
|
||||||
# "depth": 270,
|
|
||||||
# "thermal_conductivity": 0.044,
|
|
||||||
# "prime_cost": None,
|
|
||||||
# "material_cost": 5.91938,
|
|
||||||
# "labour_cost": 1.96,
|
|
||||||
# "labour_hours": 0.11
|
|
||||||
# }
|
|
||||||
|
|
||||||
material_cost_per_m2 = material["material_cost"]
|
material_cost_per_m2 = material["material_cost"]
|
||||||
# floor_area = self.property.floor_area
|
|
||||||
|
|
||||||
base_material_cost = material_cost_per_m2 * floor_area
|
base_material_cost = material_cost_per_m2 * floor_area
|
||||||
labour_cost = material["labour_cost"] * floor_area * self.labour_adjustment_factor
|
labour_cost = material["labour_cost"] * floor_area * self.labour_adjustment_factor
|
||||||
|
|
@ -225,110 +213,6 @@ class Costs:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Parsing the provided table into a list of dictionaries
|
|
||||||
|
|
||||||
# non_insulation_materials = [
|
|
||||||
# {'type': 'iwi_wall_demolition',
|
|
||||||
# 'description': 'Solid & Dry Lined walls: Hack of wall finishes with chipping hammer; plaster to walls.',
|
|
||||||
# 'depth': 0.0, 'depth_unit': 0.0, 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.0,
|
|
||||||
# 'thermal_conductivity_unit': 0.0, 'prime_material_cost': 0.0, 'material_cost': 0.0, 'labour_cost': 10.27,
|
|
||||||
# 'labour_hours_per_unit': 0.33, 'plant_cost': 1.28, 'total_cost': 11.55, 'link': 'SPONs', 'Notes': 0.0},
|
|
||||||
# {'type': 'iwi_wall_demolition',
|
|
||||||
# 'description': 'Stud walls: Remove wall linings including battening behind; plasterboard and skim',
|
|
||||||
# 'depth': 0.0, 'depth_unit': 0.0, 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.0,
|
|
||||||
# 'thermal_conductivity_unit': 0.0, 'prime_material_cost': 0.0, 'material_cost': 0.0, 'labour_cost': 6.23,
|
|
||||||
# 'labour_hours_per_unit': 0.2, 'plant_cost': 1.25, 'total_cost': 7.48, 'link': 'SPONs', 'Notes': 0.0},
|
|
||||||
# {'type': 'iwi_wall_demolition',
|
|
||||||
# 'description': 'Lathe and Plaster walls: Remove wall linings including battening behind; wood lath and '
|
|
||||||
# 'plaster',
|
|
||||||
# 'depth': 0.0, 'depth_unit': 0.0, 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.0,
|
|
||||||
# 'thermal_conductivity_unit': 0.0, 'prime_material_cost': 0.0, 'material_cost': 0.0, 'labour_cost': 6.85,
|
|
||||||
# 'labour_hours_per_unit': 0.22, 'plant_cost': 2.09, 'total_cost': 8.94, 'link': 'SPONs', 'Notes': 0.0},
|
|
||||||
# {'Notes': "",
|
|
||||||
# 'cost_unit': "",
|
|
||||||
# 'depth': "",
|
|
||||||
# 'depth_unit': "",
|
|
||||||
# 'description': 'Visqueen High Performance Vapour Barrier',
|
|
||||||
# 'labour_cost': 0.48,
|
|
||||||
# 'labour_hours_per_unit': 0.02,
|
|
||||||
# 'link': 'SPONs',
|
|
||||||
# 'material_cost': 1.21,
|
|
||||||
# 'plant_cost': 0,
|
|
||||||
# 'prime_material_cost': 0.58,
|
|
||||||
# 'thermal_conductivity': "",
|
|
||||||
# 'thermal_conductivity_unit': "",
|
|
||||||
# 'total_cost': 1.69,
|
|
||||||
# 'type': 'iwi_vapour_barrier'},
|
|
||||||
# {'Notes': "",
|
|
||||||
# 'cost_unit': "",
|
|
||||||
# 'depth': "",
|
|
||||||
# 'depth_unit': "",
|
|
||||||
# 'description': 'Plaster; one coat Thistle board finish or other equal; steel trowelled; 3 mm thick work '
|
|
||||||
# 'to walls or ceilings; one coat; to plasterboard base; over 600mm wide',
|
|
||||||
# 'labour_cost': 6.58,
|
|
||||||
# 'labour_hours_per_unit': 0.25,
|
|
||||||
# 'link': "",
|
|
||||||
# 'material_cost': 0.06,
|
|
||||||
# 'plant_cost': 0,
|
|
||||||
# 'prime_material_cost': 0.0,
|
|
||||||
# 'thermal_conductivity': "",
|
|
||||||
# 'thermal_conductivity_unit': "",
|
|
||||||
# 'total_cost': 6.64,
|
|
||||||
# 'type': 'iwi_redecoration'},
|
|
||||||
# {'Notes': "",
|
|
||||||
# 'cost_unit': "",
|
|
||||||
# 'depth': "",
|
|
||||||
# 'depth_unit': "",
|
|
||||||
# 'description': 'Two coats emulsion paint on plaster, over 40mm girth; 3.5m - '
|
|
||||||
# '5m high',
|
|
||||||
# 'labour_cost': 0.0,
|
|
||||||
# 'labour_hours_per_unit': 0.21,
|
|
||||||
# 'link': "",
|
|
||||||
# 'material_cost': 0.41,
|
|
||||||
# 'plant_cost': 0,
|
|
||||||
# 'prime_material_cost': "",
|
|
||||||
# 'thermal_conductivity': "",
|
|
||||||
# 'thermal_conductivity_unit': "",
|
|
||||||
# 'total_cost': 4.34,
|
|
||||||
# 'type': 'iwi_redecoration'},
|
|
||||||
# {'Notes': "",
|
|
||||||
# 'cost_unit': "",
|
|
||||||
# 'depth': "",
|
|
||||||
# 'depth_unit': "",
|
|
||||||
# 'description': 'Fitting existing softwood skirting or architrave to new '
|
|
||||||
# 'frames; 150mm high',
|
|
||||||
# 'labour_cost': 4.87,
|
|
||||||
# 'labour_hours_per_unit': 0.01,
|
|
||||||
# 'link': "",
|
|
||||||
# 'material_cost': 4.86,
|
|
||||||
# 'plant_cost': 0,
|
|
||||||
# 'prime_material_cost': "",
|
|
||||||
# 'thermal_conductivity': "",
|
|
||||||
# 'thermal_conductivity_unit': "",
|
|
||||||
# 'total_cost': 4.88,
|
|
||||||
# 'type': 'iwi_redecoration'}
|
|
||||||
# ]
|
|
||||||
#
|
|
||||||
# material = {
|
|
||||||
# "type": "internal_wall_insulation",
|
|
||||||
# "description": "Ecotherm Eco-Versal PIR Insulation Board",
|
|
||||||
# "depth": 150,
|
|
||||||
# "depth_unit": "mm",
|
|
||||||
# "cost_unit": "gbp_per_m2",
|
|
||||||
# "thermal_conductivity": 0.022,
|
|
||||||
# "thermal_conductivity_unit": "watt_per_meter_kelvin",
|
|
||||||
# "prime_material_cost": "",
|
|
||||||
# "material_cost": 11.68,
|
|
||||||
# "labour_cost": 3.12,
|
|
||||||
# "labour_hours_per_unit": 0.18,
|
|
||||||
# "plant_cost": "",
|
|
||||||
# "total_cost": 14.8,
|
|
||||||
# "link": "SPONs"
|
|
||||||
# }
|
|
||||||
|
|
||||||
# Cost per m2
|
|
||||||
# wall_area = self.property.insulation_wall_area
|
|
||||||
|
|
||||||
# Extract and check the different types of data we'll need
|
# Extract and check the different types of data we'll need
|
||||||
demolition_data = [x for x in non_insulation_materials if x["type"] == "iwi_wall_demolition"]
|
demolition_data = [x for x in non_insulation_materials if x["type"] == "iwi_wall_demolition"]
|
||||||
vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "iwi_vapour_barrier"]
|
vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "iwi_vapour_barrier"]
|
||||||
|
|
@ -365,7 +249,8 @@ class Costs:
|
||||||
|
|
||||||
subtotal_before_profit = labour_costs + materials_costs + demolition_plant_costs
|
subtotal_before_profit = labour_costs + materials_costs + demolition_plant_costs
|
||||||
|
|
||||||
contingency_cost = subtotal_before_profit * self.CONTINGENCY
|
# We use high risk contingency for iwi
|
||||||
|
contingency_cost = subtotal_before_profit * self.HIGH_RISK_CONTINGENCY
|
||||||
preliminaries_cost = subtotal_before_profit * self.PRELIMINARIES
|
preliminaries_cost = subtotal_before_profit * self.PRELIMINARIES
|
||||||
profit_cost = subtotal_before_profit * self.PROFIT_MARGIN
|
profit_cost = subtotal_before_profit * self.PROFIT_MARGIN
|
||||||
|
|
||||||
|
|
@ -384,7 +269,7 @@ class Costs:
|
||||||
redecoration_labour_hours)
|
redecoration_labour_hours)
|
||||||
|
|
||||||
# To install internal wall insulation, a small to medium size project might be conducted by a team of 3-5 people
|
# 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) / 5
|
labour_days = (labour_hours / 8) / 4
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"total": total_cost,
|
"total": total_cost,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ class FloorRecommendations(Definitions):
|
||||||
)
|
)
|
||||||
property_type = self.property.data["property-type"]
|
property_type = self.property.data["property-type"]
|
||||||
|
|
||||||
floor_area = self.property.floor_area / self.property.number_of_floors
|
floor_area = self.property.insulation_floor_area
|
||||||
year_built = self.property.year_built
|
year_built = self.property.year_built
|
||||||
|
|
||||||
if self.property.floor["another_property_below"] | (self.property.floor["insulation_thickness"] in [
|
if self.property.floor["another_property_below"] | (self.property.floor["insulation_thickness"] in [
|
||||||
|
|
@ -137,7 +137,7 @@ class FloorRecommendations(Definitions):
|
||||||
|
|
||||||
if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
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)
|
lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value)
|
||||||
quantity = self.property.floor_area / self.property.number_of_floors
|
quantity = self.property.insulation_floor_area
|
||||||
|
|
||||||
estimated_cost = cost_per_unit * quantity
|
estimated_cost = cost_per_unit * quantity
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ class RoofRecommendations:
|
||||||
if new_u_value <= self.BUILDING_REGULATIONS_PART_L_MAX_U_VALUE:
|
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)
|
lowest_selected_u_value = update_lowest_selected_u_value(lowest_selected_u_value, new_u_value)
|
||||||
|
|
||||||
|
# TODO: We should use the floor area divided by the number of floors to get the area of the roof
|
||||||
estimated_cost = cost_per_unit * self.property.floor_area
|
estimated_cost = cost_per_unit * self.property.floor_area
|
||||||
|
|
||||||
if roof["is_pitched"]:
|
if roof["is_pitched"]:
|
||||||
|
|
|
||||||
|
|
@ -31,3 +31,146 @@ class TestCosts:
|
||||||
'contingency': 63.396792997100626, 'preliminaries': 63.396792997100626,
|
'contingency': 63.396792997100626, 'preliminaries': 63.396792997100626,
|
||||||
'material': 539.0166061175574, 'profit': 95.09518949565093,
|
'material': 539.0166061175574, 'profit': 95.09518949565093,
|
||||||
'labour_hours': 6.234177828761786}
|
'labour_hours': 6.234177828761786}
|
||||||
|
|
||||||
|
def test_loft_insulation(self):
|
||||||
|
mock_property = Mock()
|
||||||
|
mock_property.data = {
|
||||||
|
"county": "Northamptonshire"
|
||||||
|
}
|
||||||
|
|
||||||
|
costs = Costs(mock_property)
|
||||||
|
loft_material = {
|
||||||
|
"description": "Crown Loft Roll 44 glass fibre roll",
|
||||||
|
"depth": 270,
|
||||||
|
"thermal_conductivity": 0.044,
|
||||||
|
"prime_cost": None,
|
||||||
|
"material_cost": 5.91938,
|
||||||
|
"labour_cost": 1.96,
|
||||||
|
"labour_hours": 0.11
|
||||||
|
}
|
||||||
|
|
||||||
|
loft_results = costs.loft_insulation(
|
||||||
|
floor_area=33.5,
|
||||||
|
material=loft_material,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert loft_results == {'total': 414.8496486, 'subtotal': 345.70804050000004, 'vat': 69.14160810000001,
|
||||||
|
'contingency': 25.608003000000004, 'preliminaries': 25.608003000000004,
|
||||||
|
'material': 198.29923000000002, 'profit': 38.4120045, 'labour_hours': 3.685}
|
||||||
|
|
||||||
|
def test_internal_wall_insulation(self):
|
||||||
|
mock_property = Mock()
|
||||||
|
mock_property.data = {
|
||||||
|
"county": "Northamptonshire"
|
||||||
|
}
|
||||||
|
|
||||||
|
costs = Costs(mock_property)
|
||||||
|
iwi_non_insulation_materials = [
|
||||||
|
{'type': 'iwi_wall_demolition',
|
||||||
|
'description': 'Solid & Dry Lined walls: Hack of wall finishes with chipping hammer; plaster to walls.',
|
||||||
|
'depth': 0.0, 'depth_unit': 0.0, 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.0,
|
||||||
|
'thermal_conductivity_unit': 0.0, 'prime_material_cost': 0.0, 'material_cost': 0.0, 'labour_cost': 10.27,
|
||||||
|
'labour_hours_per_unit': 0.33, 'plant_cost': 1.28, 'total_cost': 11.55, 'link': 'SPONs', 'Notes': 0.0},
|
||||||
|
{'type': 'iwi_wall_demolition',
|
||||||
|
'description': 'Stud walls: Remove wall linings including battening behind; plasterboard and skim',
|
||||||
|
'depth': 0.0, 'depth_unit': 0.0, 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.0,
|
||||||
|
'thermal_conductivity_unit': 0.0, 'prime_material_cost': 0.0, 'material_cost': 0.0, 'labour_cost': 6.23,
|
||||||
|
'labour_hours_per_unit': 0.2, 'plant_cost': 1.25, 'total_cost': 7.48, 'link': 'SPONs', 'Notes': 0.0},
|
||||||
|
{'type': 'iwi_wall_demolition',
|
||||||
|
'description': 'Lathe and Plaster walls: Remove wall linings including battening behind; wood lath and '
|
||||||
|
'plaster',
|
||||||
|
'depth': 0.0, 'depth_unit': 0.0, 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.0,
|
||||||
|
'thermal_conductivity_unit': 0.0, 'prime_material_cost': 0.0, 'material_cost': 0.0, 'labour_cost': 6.85,
|
||||||
|
'labour_hours_per_unit': 0.22, 'plant_cost': 2.09, 'total_cost': 8.94, 'link': 'SPONs', 'Notes': 0.0},
|
||||||
|
{'Notes': "",
|
||||||
|
'cost_unit': "",
|
||||||
|
'depth': "",
|
||||||
|
'depth_unit': "",
|
||||||
|
'description': 'Visqueen High Performance Vapour Barrier',
|
||||||
|
'labour_cost': 0.48,
|
||||||
|
'labour_hours_per_unit': 0.02,
|
||||||
|
'link': 'SPONs',
|
||||||
|
'material_cost': 1.21,
|
||||||
|
'plant_cost': 0,
|
||||||
|
'prime_material_cost': 0.58,
|
||||||
|
'thermal_conductivity': "",
|
||||||
|
'thermal_conductivity_unit': "",
|
||||||
|
'total_cost': 1.69,
|
||||||
|
'type': 'iwi_vapour_barrier'},
|
||||||
|
{'Notes': "",
|
||||||
|
'cost_unit': "",
|
||||||
|
'depth': "",
|
||||||
|
'depth_unit': "",
|
||||||
|
'description': 'Plaster; one coat Thistle board finish or other equal; steel trowelled; 3 mm thick work '
|
||||||
|
'to walls or ceilings; one coat; to plasterboard base; over 600mm wide',
|
||||||
|
'labour_cost': 6.58,
|
||||||
|
'labour_hours_per_unit': 0.25,
|
||||||
|
'link': "",
|
||||||
|
'material_cost': 0.06,
|
||||||
|
'plant_cost': 0,
|
||||||
|
'prime_material_cost': 0.0,
|
||||||
|
'thermal_conductivity': "",
|
||||||
|
'thermal_conductivity_unit': "",
|
||||||
|
'total_cost': 6.64,
|
||||||
|
'type': 'iwi_redecoration'},
|
||||||
|
{'Notes': "",
|
||||||
|
'cost_unit': "",
|
||||||
|
'depth': "",
|
||||||
|
'depth_unit': "",
|
||||||
|
'description': 'Two coats emulsion paint on plaster, over 40mm girth; 3.5m - '
|
||||||
|
'5m high',
|
||||||
|
'labour_cost': 0.0,
|
||||||
|
'labour_hours_per_unit': 0.21,
|
||||||
|
'link': "",
|
||||||
|
'material_cost': 0.41,
|
||||||
|
'plant_cost': 0,
|
||||||
|
'prime_material_cost': "",
|
||||||
|
'thermal_conductivity': "",
|
||||||
|
'thermal_conductivity_unit': "",
|
||||||
|
'total_cost': 4.34,
|
||||||
|
'type': 'iwi_redecoration'},
|
||||||
|
{'Notes': "",
|
||||||
|
'cost_unit': "",
|
||||||
|
'depth': "",
|
||||||
|
'depth_unit': "",
|
||||||
|
'description': 'Fitting existing softwood skirting or architrave to new '
|
||||||
|
'frames; 150mm high',
|
||||||
|
'labour_cost': 4.87,
|
||||||
|
'labour_hours_per_unit': 0.01,
|
||||||
|
'link': "",
|
||||||
|
'material_cost': 4.86,
|
||||||
|
'plant_cost': 0,
|
||||||
|
'prime_material_cost': "",
|
||||||
|
'thermal_conductivity': "",
|
||||||
|
'thermal_conductivity_unit': "",
|
||||||
|
'total_cost': 4.88,
|
||||||
|
'type': 'iwi_redecoration'}
|
||||||
|
]
|
||||||
|
|
||||||
|
iwi_material = {
|
||||||
|
"type": "internal_wall_insulation",
|
||||||
|
"description": "Ecotherm Eco-Versal PIR Insulation Board",
|
||||||
|
"depth": 150,
|
||||||
|
"depth_unit": "mm",
|
||||||
|
"cost_unit": "gbp_per_m2",
|
||||||
|
"thermal_conductivity": 0.022,
|
||||||
|
"thermal_conductivity_unit": "watt_per_meter_kelvin",
|
||||||
|
"prime_material_cost": "",
|
||||||
|
"material_cost": 11.68,
|
||||||
|
"labour_cost": 3.12,
|
||||||
|
"labour_hours_per_unit": 0.18,
|
||||||
|
"plant_cost": "",
|
||||||
|
"total_cost": 14.8,
|
||||||
|
"link": "SPONs"
|
||||||
|
}
|
||||||
|
|
||||||
|
iwi_results = costs.internal_wall_insulation(
|
||||||
|
wall_area=95.9104281347967,
|
||||||
|
material=iwi_material,
|
||||||
|
non_insulation_materials=iwi_non_insulation_materials
|
||||||
|
)
|
||||||
|
|
||||||
|
assert iwi_results == {'total': 6421.5484411659245, 'subtotal': 5351.29036763827, 'vat': 1070.258073527654,
|
||||||
|
'contingency': 573.3525393898148, 'preliminaries': 382.2350262598765,
|
||||||
|
'material': 1747.488000615996, 'profit': 573.3525393898148,
|
||||||
|
'labour_hours': 88.23759388401297, 'labour_days': 2.757424808875405}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue