Creating new cost class to handle new costing data

This commit is contained in:
Khalim Conn-Kowlessar 2023-11-22 11:53:22 +00:00
parent 2cc5a8f465
commit a74459bf46
2 changed files with 140 additions and 1 deletions

View file

@ -173,7 +173,7 @@ def create_recommendation_scoring_data(
parts = recommendation["parts"]
if len(parts) != 1:
raise ValueError("More than one part for roof insulation - investiage me")
scoring_dict["roof_insulation_thickness_ENDING"] = str(parts[0]["depths"][0])
scoring_dict["ROOF_ENERGY_EFF_ENDING"] = "Very Good"
else:

139
recommendations/Costs.py Normal file
View file

@ -0,0 +1,139 @@
class Costs:
"""
A class to calculate the costs associated with construction works,
specifically focusing on cavity wall insulation.
It includes contingency, preliminaries, profit margin, and VAT calculations.
As a sense check, there is a useful article from checkatrade on retrofitting walls and expected costs:
https://www.checkatrade.com/blog/cost-guides/retrofit-insulation-cost/
"""
# Contingency is a percentage of the total cost of the work and covers unforseen expenses
# We assume a conservative 10% contingency for all works which is a rate defined by SPONs
CONTINGENCY = 0.1
# Preliminaries are a percentage of the total cost of the work and covers the cost of site-specific costs
# such as site preparation, safety measures and project management. This rate can vary but we'll assume a 10%
# rate, on the total cost before VAT, as recommended by SPONs
PRELIMINARIES = 0.1
VAT_RATE = 0.2
PROFIT_MARGIN = 0.15
def __init__(self, property_instance):
"""
Initializes the Costs class with a property instance.
:param property_instance: Instance of a Property class containing relevant details like wall area.
"""
if not hasattr(property_instance, 'insulation_wall_area'):
raise ValueError("Property instance must have an 'insulation_wall_area' attribute")
self.property = property_instance
def cavity_wall_insulation(self, material):
"""
Calculates the total cost for cavity wall insulation based on material and labor costs,
including contingency, preliminaries, profit, and VAT.
:return: A dictionary containing detailed cost breakdown.
"""
# Cost per m2
material = {
"description": "Crown Dritherm Cavity Slab 37 (Thermal conductivity 0.037 W/mK) glass fibre batt or other "
"equal; as full or partial cavity fill; including cutting and fitting around wall ties and "
"retaining discs",
"depth": 75,
"thermal_conductivity": 0.037,
"prime_cost": 5.17,
"material_cost": 5.62,
"labour_cost": 2.25,
"labour_hours": 0.13
}
material_cost_per_m2 = material["material_cost"]
wall_area = self.property.insulation_wall_area
# This is the amount of material required in m3, assuming a standard 75mm depth
volume = 0.075 * wall_area
base_material_cost = material_cost_per_m2 * wall_area
labour_cost = material["labour_cost"] * wall_area
subtotal_before_profit = base_material_cost + labour_cost
contingency_cost = subtotal_before_profit * self.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
labour_hours = material["labour_hours"] * wall_area
return {
"total": total_cost,
"subtotal": subtotal_before_vat,
"vat": vat_cost,
"contingency": contingency_cost,
"preliminaries": preliminaries_cost,
"material": base_material_cost,
"profit": profit_cost,
"labour_hours": labour_hours
}
def cavity_wall_insulation(self, material):
"""
Calculates the total cost for cavity wall insulation based on material and labor costs,
including contingency, preliminaries, profit, and VAT.
:return: A dictionary containing detailed cost breakdown.
"""
# Cost per m2
material = {
"description": "Crown Dritherm Cavity Slab 37 (Thermal conductivity 0.037 W/mK) glass fibre batt or other "
"equal; as full or partial cavity fill; including cutting and fitting around wall ties and "
"retaining discs",
"depth": 75,
"thermal_conductivity": 0.037,
"prime_cost": 5.17,
"material_cost": 5.62,
"labour_cost": 2.25,
"labour_hours": 0.13
}
material_cost_per_m2 = material["material_cost"]
wall_area = self.property.insulation_wall_area
# This is the amount of material required in m3, assuming a standard 75mm depth
volume = 0.075 * wall_area
base_material_cost = material_cost_per_m2 * wall_area
labour_cost = material["labour_cost"] * wall_area
subtotal_before_profit = base_material_cost + labour_cost
contingency_cost = subtotal_before_profit * self.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
labour_hours = material["labour_hours"] * wall_area
return {
"total": total_cost,
"subtotal": subtotal_before_vat,
"vat": vat_cost,
"contingency": contingency_cost,
"preliminaries": preliminaries_cost,
"material": base_material_cost,
"profit": profit_cost,
"labour_hours": labour_hours
}