diff --git a/recommendations/Costs.py b/recommendations/Costs.py index e8f9d122..8f54a79a 100644 --- a/recommendations/Costs.py +++ b/recommendations/Costs.py @@ -150,7 +150,8 @@ class Costs: "preliminaries": preliminaries_cost, "material": base_material_cost, "profit": profit_cost, - "labour_hours": labour_hours + "labour_hours": labour_hours, + "labour_cost": labour_cost } def loft_insulation(self, floor_area, material): @@ -187,7 +188,8 @@ class Costs: "preliminaries": preliminaries_cost, "material": base_material_cost, "profit": profit_cost, - "labour_hours": labour_hours + "labour_hours": labour_hours, + "labour_cost": labour_cost } def internal_wall_insulation(self, wall_area, material, non_insulation_materials): @@ -280,7 +282,8 @@ class Costs: "material": materials_costs, "profit": profit_cost, "labour_hours": labour_hours, - "labour_days": labour_days + "labour_days": labour_days, + "labour_cost": labour_costs } def suspended_floor_insulation(self, insulation_floor_area, material, non_insulation_materials): @@ -297,45 +300,6 @@ class Costs: :return: """ - # material = {'type': 'suspended_floor_insulation', 'description': 'Thermafleece CosyWool Roll', 'depth': 140.0, - # 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.039, - # 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 0, - # 'material_cost': 11.68, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1, 'plant_cost': 0, - # 'total_cost': 13.46, 'link': 'SPONs', - # 'Notes': 'Spons did not contain labour costs so we use values for similar insulations. We use - # the ' - # 'same values as in Crown loft roll 44, since it is also an insulation roll'} - # - # non_insulation_materials = [ - # {'type': 'suspended_floor_demolition', 'description': 'Removal of carpet and underfelt', 'depth': 0, - # 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11, - # 'plant_cost': 0, 'total_cost': 3.32, 'link': 'SPONs', - # 'Notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and ' - # 'therefore there is no need for a skip'}, - # {'type': 'suspended_floor_demolition', - # 'description': 'Remove boarding; withdraw nails; set aside for reuse; ground level', 'depth': 0, - # 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 9.34, 'labour_hours_per_unit': 0.3, - # 'plant_cost': 0, 'total_cost': 9.34, 'link': 'SPONs', 'Notes': 0}, - # {'type': 'suspended_floor_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, 'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, - # 'labour_hours_per_unit': 0.02, 'plant_cost': 0, 'total_cost': 1.69, 'link': 'SPONs', 'Notes': 0}, - # {'type': 'suspended_floor_redecoration', 'description': 'refix floorboards previously set aside', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, 'prime_material_cost': 0, 'material_cost': 1.54, 'labour_cost': 24.98, - # 'labour_hours_per_unit': 0.74, 'plant_cost': 0, 'total_cost': 26.52, 'link': 'SPONs', 'Notes': 0}, - # {'type': 'suspended_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0, 'depth_unit': 0, - # 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37, - # 'plant_cost': 0, 'total_cost': 6.59, 'link': 'SPONs', - # 'Notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; ' - # 'Gradus woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, ' - # 'therefore we need just labour rates'}] - - # insulation_floor_area = self.property.floor_area / self.property.number_of_floors - demolition_data = [x for x in non_insulation_materials if x["type"] == "suspended_floor_demolition"] vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "suspended_floor_vapour_barrier"] redecoration_data = [x for x in non_insulation_materials if x["type"] == "suspended_floor_redecoration"] @@ -394,7 +358,8 @@ class Costs: "material": materials_costs, "profit": profit_cost, "labour_hours": labour_hours, - "labour_days": labour_days + "labour_days": labour_days, + "labour_cost": labour_costs } def solid_floor_insulation(self, insulation_floor_area, material, non_insulation_materials): @@ -428,78 +393,13 @@ class Costs: 7) Considerations for Doors and Fixtures: It's important to note that raising the floor level can affect door thresholds and other fixtures. Doors may need to be trimmed, and fixtures might need adjustments. - :param material: - :param non_insulation_materials: + + :param insulation_floor_area: Area of the floor to be insulated + :param material: Selected insulation material + :param non_insulation_materials: Non-insulation materials required for the job :return: """ - # material = { - # 'type': 'solid_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board', - # 'depth': 100.0, 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.033, - # 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 0, - # 'material_cost': 12.02, 'labour_cost': 4.4, 'labour_hours_per_unit': 0.19, 'plant_cost': 0, - # 'total_cost': 16.42, 'link': 'SPONs', 'Notes': 0 - # } - # - # non_insulation_materials = [ - # {'type': 'solid_floor_demolition', 'description': 'Removal of carpet and underfelt', 'depth': 0, - # 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11, - # 'plant_cost': 0, 'total_cost': 3.32, 'link': 'SPONs', - # 'Notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and ' - # 'therefore there is no need for a skip'}, - # {'type': 'solid_floor_preparation', - # 'description': 'clean surface of concrete to receive new damp-proof membrane', 'depth': 0, - # 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 4.36, 'labour_hours_per_unit': 0.14, - # 'plant_cost': 0, 'total_cost': 4.36, 'link': 0, 'Notes': 0}, {'type': 'solid_floor_preparation', - # 'description': 'Clean out crack to ' - # 'form a 20mm×20mm ' - # 'groove and fill with ' - # 'cement: mortar mixed ' - # 'with bonding agent', - # 'depth': 0, 'depth_unit': 0, - # 'cost_unit': 0, - # 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, - # 'material_cost': 6.91, - # 'labour_cost': 18.99, - # 'labour_hours_per_unit': 0.61, - # 'plant_cost': 0.16, - # 'total_cost': 26.06, 'link': 0, - # 'Notes': 'This step is the ' - # 'assessment and repair of ' - # 'any damage to the concrete ' - # 'floor such as filling ' - # 'cracks or levelling uneven ' - # 'areas'}, - # {'type': 'solid_floor_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, 'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, - # 'labour_hours_per_unit': 0.02, 'plant_cost': 0, 'total_cost': 1.69, 'link': 'SPONs', 'Notes': 0}, - # {'type': 'solid_floor_redecoration', - # 'description': 'Screeded beds; protection to compressible formwork exceeding 600mm wide', 'depth': 0, - # 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 9.6, 'material_cost': 9.89, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15, - # 'plant_cost': 0, 'total_cost': 12.56, 'link': 'SPONs', - # 'Notes': 'This is the screed layer, placed on top of the insulation'}, - # {'type': 'solid_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0, 'depth_unit': 0, - # 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37, - # 'plant_cost': 0, 'total_cost': 6.59, 'link': 'SPONs', - # 'Notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; ' - # 'Gradus woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, ' - # 'therefore we need just labour rates'}, - # {'type': 'solid_floor_redecoration', - # 'description': 'Fitting existing softwood skirting or architrave to new frames; 150mm high', 'depth': 0, - # 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0.01, 'labour_cost': 4.87, 'labour_hours_per_unit': 0.12, - # 'plant_cost': 0, 'total_cost': 4.88, 'link': 'SPONs', 'Notes': 0} - # ] - - # insulation_floor_area = self.property.floor_area / self.property.number_of_floors - demolition_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_demolition"] preparation_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_preparation"] vapour_barrier_data = [x for x in non_insulation_materials if x["type"] == "solid_floor_vapour_barrier"] @@ -564,7 +464,8 @@ class Costs: "material": materials_cost, "profit": profit_cost, "labour_hours": labour_hours, - "labour_days": labour_days + "labour_days": labour_days, + "labour_cost": labour_costs } def external_wall_insulation(self, wall_area, material, non_insulation_materials): @@ -632,73 +533,6 @@ class Costs: else: raise ValueError("Unsupported property type - haven't handled flats") - # non_insulation_materials = [x for x in df if x["type"] != "external_wall_insulation"] - # insulation_materials = [x for x in df if x["type"] == "external_wall_insulation"] - # material = {'type': 'external_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board', - # 'depth': 150.0, 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.022, - # 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 23.53, - # 'material_cost': 34.62, 'labour_cost': 33.06, 'labour_hours_per_unit': 1.4, 'plant_cost': 0, - # 'total_cost': 67.68, 'link': 'SPONs', 'Notes': 0} - # non_insulation_materials = [ - # {'type': 'ewi_wall_demolition', - # 'description': 'Solid & Dry Lined walls: Hack of wall finishes with chipping ' - # 'hammer; plaster to walls.', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 'gbp_per_m2', - # 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 10.27, - # 'labour_hours_per_unit': 0.33, 'plant_cost': 1.28, 'total_cost': 11.55, - # 'link': 'SPONs', 'Notes': 0}, {'type': 'ewi_wall_demolition', - # 'description': 'Stud walls: Remove wall linings ' - # 'including battening behind; ' - # 'plasterboard and skim', - # 'depth': 0, 'depth_unit': 0, - # 'cost_unit': 'gbp_per_m2', - # 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, - # 'labour_cost': 6.23, 'labour_hours_per_unit': 0.2, - # 'plant_cost': 1.25, 'total_cost': 7.48, - # 'link': 'SPONs', 'Notes': 0}, - # {'type': 'ewi_wall_demolition', - # 'description': 'Lathe and Plaster walls: Remove wall linings including battening ' - # 'behind; wood lath and plaster', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 'gbp_per_m2', - # 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.85, - # 'labour_hours_per_unit': 0.22, 'plant_cost': 2.09, 'total_cost': 8.94, - # 'link': 'SPONs', 'Notes': 0}, {'type': 'ewi_wall_preparation', - # 'description': 'Clean and prepare surfaces, ' - # 'one coat Keim dilution, ' - # 'one coat primer and two coats ' - # 'of Keim Ecosil paint; Brick or ' - # 'block walls; over 300 mm girth', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, - # 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, - # 'prime_material_cost': 0, 'material_cost': 7.3, - # 'labour_cost': 5.62, 'labour_hours_per_unit': 0.3, - # 'plant_cost': 0, 'total_cost': 12.92, - # 'link': 'SPONs', - # 'Notes': 'This work covers the preparation and ' - # 'priming of the wall before insulating'}, - # {'type': 'ewi_wall_redecoration', - # 'description': 'EPS insulation fixed with adhesive to SFS structure (measured ' - # 'separately) with horizontal PVC intermediate track and vertical ' - # 'T-spines; with glassfibre mesh reinforcement embedded in Sto ' - # 'Armat Classic Basecoat Render and Stolit K 1.5 Decorative ' - # 'Topcoat Render (white)', - # 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, - # 'thermal_conductivity_unit': 0, 'prime_material_cost': 0, 'material_cost': 0, - # 'labour_cost': 0, 'labour_hours_per_unit': 0, 'plant_cost': 0, - # 'total_cost': 69.94, 'link': 'SPONs', - # 'Notes': 'This material in SPONs is for 70mm EPS insulation, which comes in at a ' - # 'cost of 99.17 per meter square. This includes the cost of insulation. ' - # 'To get the costing for just the works and not the insulation, ' - # 'we subtract the cost of EPS insulation, using Ravathem 75mm insulation ' - # 'as an example, which costs £29.23 per meter square, giving us the cost ' - # 'of the remaining works without insulation. This material gives us a ' - # 'cost for basecoat, mesh application and a render finish'}] - 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"] @@ -759,5 +593,6 @@ class Costs: "material": materials_costs, "profit": profit_cost, "labour_hours": labour_hours, - "labour_days": labour_days + "labour_days": labour_days, + "labour_cost": labour_costs } diff --git a/recommendations/tests/test_costs.py b/recommendations/tests/test_costs.py index 8e2d76ce..1ba601a8 100644 --- a/recommendations/tests/test_costs.py +++ b/recommendations/tests/test_costs.py @@ -30,7 +30,7 @@ class TestCosts: assert cwi_results == {'total': 1027.0280465530302, 'subtotal': 855.8567054608585, 'vat': 171.1713410921717, 'contingency': 63.396792997100626, 'preliminaries': 63.396792997100626, 'material': 539.0166061175574, 'profit': 95.09518949565093, - 'labour_hours': 6.234177828761786} + 'labour_hours': 6.234177828761786, 'labour_cost': 94.95132385344874} def test_loft_insulation(self): mock_property = Mock() @@ -56,7 +56,8 @@ class TestCosts: 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} + 'material': 198.29923000000002, 'profit': 38.4120045, 'labour_hours': 3.685, + 'labour_cost': 57.7808} def test_internal_wall_insulation(self): mock_property = Mock() @@ -173,4 +174,238 @@ class TestCosts: 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} + 'labour_hours': 88.23759388401297, 'labour_days': 2.757424808875405, + 'labour_cost': 1927.1602026551818} + + def test_suspended_floor_insulation(self): + mock_property = Mock() + mock_property.data = { + "county": "Northamptonshire" + } + + costs = Costs(mock_property) + + sus_floor_material = {'type': 'suspended_floor_insulation', 'description': 'Thermafleece CosyWool Roll', + 'depth': 140.0, + 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.039, + 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 0, + 'material_cost': 11.68, 'labour_cost': 1.78, 'labour_hours_per_unit': 0.1, + 'plant_cost': 0, + 'total_cost': 13.46, 'link': 'SPONs', + 'Notes': 'Spons did not contain labour costs so we use values for similar insulations. ' + 'We use the ' + 'same values as in Crown loft roll 44, since it is also an insulation roll'} + + sus_floor_non_insulation_materials = [ + {'type': 'suspended_floor_demolition', 'description': 'Removal of carpet and underfelt', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11, + 'plant_cost': 0, 'total_cost': 3.32, 'link': 'SPONs', + 'Notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and ' + 'therefore there is no need for a skip'}, + {'type': 'suspended_floor_demolition', + 'description': 'Remove boarding; withdraw nails; set aside for reuse; ground level', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 9.34, 'labour_hours_per_unit': 0.3, + 'plant_cost': 0, 'total_cost': 9.34, 'link': 'SPONs', 'Notes': 0}, + {'type': 'suspended_floor_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, 'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, + 'labour_hours_per_unit': 0.02, 'plant_cost': 0, 'total_cost': 1.69, 'link': 'SPONs', 'Notes': 0}, + {'type': 'suspended_floor_redecoration', 'description': 'refix floorboards previously set aside', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, 'prime_material_cost': 0, 'material_cost': 1.54, 'labour_cost': 24.98, + 'labour_hours_per_unit': 0.74, 'plant_cost': 0, 'total_cost': 26.52, 'link': 'SPONs', 'Notes': 0}, + {'type': 'suspended_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0, 'depth_unit': 0, + 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37, + 'plant_cost': 0, 'total_cost': 6.59, 'link': 'SPONs', + 'Notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; ' + 'Gradus woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, ' + 'therefore we need just labour rates'}] + + sus_floor_results = costs.suspended_floor_insulation( + insulation_floor_area=33.5, + material=sus_floor_material, + non_insulation_materials=sus_floor_non_insulation_materials + ) + + assert sus_floor_results == { + 'total': 3003.366924, 'subtotal': 2502.80577, 'vat': 500.561154, + 'contingency': 185.39302, 'preliminaries': 185.39302, 'material': 483.405, + 'profit': 278.08952999999997, 'labour_hours': 54.940000000000005, + 'labour_days': 2.289166666666667, 'labour_cost': 1370.5252 + } + + def test_solid_floor_insulation(self): + mock_property = Mock() + mock_property.data = { + "county": "Northamptonshire" + } + + costs = Costs(mock_property) + sol_floor_material = { + 'type': 'solid_floor_insulation', 'description': 'Kay-Cel Expanded Polystyrene Board', + 'depth': 100.0, 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.033, + 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 0, + 'material_cost': 12.02, 'labour_cost': 4.4, 'labour_hours_per_unit': 0.19, 'plant_cost': 0, + 'total_cost': 16.42, 'link': 'SPONs', 'Notes': 0 + } + + sol_floor_non_insulation_materials = [ + {'type': 'solid_floor_demolition', 'description': 'Removal of carpet and underfelt', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 3.32, 'labour_hours_per_unit': 0.11, + 'plant_cost': 0, 'total_cost': 3.32, 'link': 'SPONs', + 'Notes': 'We ignore the plant cost that is in SPONs because we assume the carpet is not scrapped and ' + 'therefore there is no need for a skip'}, + {'type': 'solid_floor_preparation', + 'description': 'clean surface of concrete to receive new damp-proof membrane', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 4.36, 'labour_hours_per_unit': 0.14, + 'plant_cost': 0, 'total_cost': 4.36, 'link': 0, 'Notes': 0}, {'type': 'solid_floor_preparation', + 'description': 'Clean out crack to ' + 'form a 20mm×20mm ' + 'groove and fill with ' + 'cement: mortar mixed ' + 'with bonding agent', + 'depth': 0, 'depth_unit': 0, + 'cost_unit': 0, + 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, + 'material_cost': 6.91, + 'labour_cost': 18.99, + 'labour_hours_per_unit': 0.61, + 'plant_cost': 0.16, + 'total_cost': 26.06, 'link': 0, + 'Notes': 'This step is the ' + 'assessment and repair of ' + 'any damage to the concrete ' + 'floor such as filling ' + 'cracks or levelling uneven ' + 'areas'}, + {'type': 'solid_floor_vapour_barrier', 'description': 'Visqueen High Performance Vapour Barrier', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, 'prime_material_cost': 0.58, 'material_cost': 1.21, 'labour_cost': 0.48, + 'labour_hours_per_unit': 0.02, 'plant_cost': 0, 'total_cost': 1.69, 'link': 'SPONs', 'Notes': 0}, + {'type': 'solid_floor_redecoration', + 'description': 'Screeded beds; protection to compressible formwork exceeding 600mm wide', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 9.6, 'material_cost': 9.89, 'labour_cost': 2.67, 'labour_hours_per_unit': 0.15, + 'plant_cost': 0, 'total_cost': 12.56, 'link': 'SPONs', + 'Notes': 'This is the screed layer, placed on top of the insulation'}, + {'type': 'solid_floor_redecoration', 'description': 'Fitting carpet', 'depth': 0, 'depth_unit': 0, + 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.59, 'labour_hours_per_unit': 0.37, + 'plant_cost': 0, 'total_cost': 6.59, 'link': 'SPONs', + 'Notes': 'SPONs does not have data on re-fitting the carpet so we use the data in Fitted carpeting; ' + 'Gradus woven polypropylene tufted loop\n\n as a baseline. We assume re-use of carpets, ' + 'therefore we need just labour rates'}, + {'type': 'solid_floor_redecoration', + 'description': 'Fitting existing softwood skirting or architrave to new frames; 150mm high', 'depth': 0, + 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0.01, 'labour_cost': 4.87, 'labour_hours_per_unit': 0.12, + 'plant_cost': 0, 'total_cost': 4.88, 'link': 'SPONs', 'Notes': 0} + ] + + sol_floor_results = costs.solid_floor_insulation( + insulation_floor_area=33.5, + material=sol_floor_material, + non_insulation_materials=sol_floor_non_insulation_materials + ) + + assert sol_floor_results == { + 'total': 3962.021952, 'subtotal': 3301.68496, 'vat': 660.336992, 'contingency': 353.75196, + 'preliminaries': 235.83464, 'material': 1006.3399999999999, 'profit': 353.75196, 'labour_hours': 57.285, + 'labour_days': 2.386875, 'labour_cost': 1346.6464 + } + + def test_external_wall_insulation(self): + mock_property = Mock() + mock_property.data = { + "county": "Northamptonshire", + "property-type": "House", + "built-form": 'End-Terrace' + } + + costs = Costs(mock_property) + + ewi_material = {'type': 'external_wall_insulation', 'description': 'Ecotherm Eco-Versal PIR Insulation Board', + 'depth': 150.0, 'depth_unit': 'mm', 'cost_unit': 'gbp_per_m2', 'thermal_conductivity': 0.022, + 'thermal_conductivity_unit': 'watt_per_meter_kelvin', 'prime_material_cost': 23.53, + 'material_cost': 34.62, 'labour_cost': 33.06, 'labour_hours_per_unit': 1.4, 'plant_cost': 0, + 'total_cost': 67.68, 'link': 'SPONs', 'Notes': 0} + ewi_non_insulation_materials = [ + {'type': 'ewi_wall_demolition', + 'description': 'Solid & Dry Lined walls: Hack of wall finishes with chipping ' + 'hammer; plaster to walls.', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 'gbp_per_m2', + 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 10.27, + 'labour_hours_per_unit': 0.33, 'plant_cost': 1.28, 'total_cost': 11.55, + 'link': 'SPONs', 'Notes': 0}, {'type': 'ewi_wall_demolition', + 'description': 'Stud walls: Remove wall linings ' + 'including battening behind; ' + 'plasterboard and skim', + 'depth': 0, 'depth_unit': 0, + 'cost_unit': 'gbp_per_m2', + 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, + 'labour_cost': 6.23, 'labour_hours_per_unit': 0.2, + 'plant_cost': 1.25, 'total_cost': 7.48, + 'link': 'SPONs', 'Notes': 0}, + {'type': 'ewi_wall_demolition', + 'description': 'Lathe and Plaster walls: Remove wall linings including battening ' + 'behind; wood lath and plaster', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 'gbp_per_m2', + 'thermal_conductivity': 0, 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 0, 'labour_cost': 6.85, + 'labour_hours_per_unit': 0.22, 'plant_cost': 2.09, 'total_cost': 8.94, + 'link': 'SPONs', 'Notes': 0}, {'type': 'ewi_wall_preparation', + 'description': 'Clean and prepare surfaces, ' + 'one coat Keim dilution, ' + 'one coat primer and two coats ' + 'of Keim Ecosil paint; Brick or ' + 'block walls; over 300 mm girth', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, + 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, + 'prime_material_cost': 0, 'material_cost': 7.3, + 'labour_cost': 5.62, 'labour_hours_per_unit': 0.3, + 'plant_cost': 0, 'total_cost': 12.92, + 'link': 'SPONs', + 'Notes': 'This work covers the preparation and ' + 'priming of the wall before insulating'}, + {'type': 'ewi_wall_redecoration', + 'description': 'EPS insulation fixed with adhesive to SFS structure (measured ' + 'separately) with horizontal PVC intermediate track and vertical ' + 'T-spines; with glassfibre mesh reinforcement embedded in Sto ' + 'Armat Classic Basecoat Render and Stolit K 1.5 Decorative ' + 'Topcoat Render (white)', + 'depth': 0, 'depth_unit': 0, 'cost_unit': 0, 'thermal_conductivity': 0, + 'thermal_conductivity_unit': 0, 'prime_material_cost': 0, 'material_cost': 0, + 'labour_cost': 0, 'labour_hours_per_unit': 0, 'plant_cost': 0, + 'total_cost': 69.94, 'link': 'SPONs', + 'Notes': 'This material in SPONs is for 70mm EPS insulation, which comes in at a ' + 'cost of 99.17 per meter square. This includes the cost of insulation. ' + 'To get the costing for just the works and not the insulation, ' + 'we subtract the cost of EPS insulation, using Ravathem 75mm insulation ' + 'as an example, which costs £29.23 per meter square, giving us the cost ' + 'of the remaining works without insulation. This material gives us a ' + 'cost for basecoat, mesh application and a render finish'}] + + ewi_results = costs.external_wall_insulation( + wall_area=95.9104281347967, + material=ewi_material, + non_insulation_materials=ewi_non_insulation_materials + ) + + assert ewi_results == { + 'total': 13590.909723215433, 'subtotal': 11325.758102679527, 'vat': 2265.1516205359053, + 'contingency': 808.9827216199662, 'preliminaries': 1213.4740824299492, + 'material': 4020.565147410677, 'profit': 1213.4740824299492, + 'labour_hours': 187.02533486285358, 'labour_days': 5.8445417144641745, + 'labour_cost': 3921.5600094613983 + }