mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
working on costing for led installation
This commit is contained in:
parent
e441e5f018
commit
96b49aa680
6 changed files with 92 additions and 2 deletions
|
|
@ -83,6 +83,7 @@ class Property(Definitions):
|
||||||
self.floor_area = None
|
self.floor_area = None
|
||||||
self.pitched_roof_area = None
|
self.pitched_roof_area = None
|
||||||
self.insulation_floor_area = None
|
self.insulation_floor_area = None
|
||||||
|
self.number_lighting_outlets = None
|
||||||
|
|
||||||
if epc_client:
|
if epc_client:
|
||||||
self.epc_client = epc_client
|
self.epc_client = epc_client
|
||||||
|
|
@ -703,7 +704,6 @@ class Property(Definitions):
|
||||||
'PROPERTY_TYPE',
|
'PROPERTY_TYPE',
|
||||||
'UPRN',
|
'UPRN',
|
||||||
'NUMBER_OPEN_FIREPLACES',
|
'NUMBER_OPEN_FIREPLACES',
|
||||||
'FIXED_LIGHTING_OUTLETS_COUNT',
|
|
||||||
'MULTI_GLAZE_PROPORTION',
|
'MULTI_GLAZE_PROPORTION',
|
||||||
'MECHANICAL_VENTILATION',
|
'MECHANICAL_VENTILATION',
|
||||||
'PHOTO_SUPPLY',
|
'PHOTO_SUPPLY',
|
||||||
|
|
@ -752,9 +752,21 @@ class Property(Definitions):
|
||||||
"FLOOR_HEIGHT": self.floor_height,
|
"FLOOR_HEIGHT": self.floor_height,
|
||||||
"NUMBER_HABITABLE_ROOMS": self.number_of_rooms,
|
"NUMBER_HABITABLE_ROOMS": self.number_of_rooms,
|
||||||
"TOTAL_FLOOR_AREA": self.floor_area,
|
"TOTAL_FLOOR_AREA": self.floor_area,
|
||||||
|
"FIXED_LIGHTING_OUTLETS_COUNT": self.number_lighting_outlets,
|
||||||
**epc_raw_data,
|
**epc_raw_data,
|
||||||
"BUILT_FORM": built_form,
|
"BUILT_FORM": built_form,
|
||||||
"POSTCODE": self.data["postcode"],
|
"POSTCODE": self.data["postcode"],
|
||||||
}
|
}
|
||||||
|
|
||||||
return property_data
|
return property_data
|
||||||
|
|
||||||
|
def set_number_lighting_outlets(self, cleaned_property_data):
|
||||||
|
"""
|
||||||
|
Extracts and cleans the estimated number of lighting outlets
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.data["fixed-lighting-outlets-count"] == "":
|
||||||
|
self.number_lighting_outlets = round(cleaned_property_data["FIXED_LIGHTING_OUTLETS_COUNT"].values[0])
|
||||||
|
else:
|
||||||
|
self.number_lighting_outlets = float(self.data["fixed-lighting-outlets-count"])
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ class MaterialType(enum.Enum):
|
||||||
ewi_wall_demolition = "ewi_wall_demolition"
|
ewi_wall_demolition = "ewi_wall_demolition"
|
||||||
ewi_wall_preparation = "ewi_wall_preparation"
|
ewi_wall_preparation = "ewi_wall_preparation"
|
||||||
ewi_wall_redecoration = "ewi_wall_redecoration"
|
ewi_wall_redecoration = "ewi_wall_redecoration"
|
||||||
|
low_energy_lighting_installation = "low_energy_lighting_installation"
|
||||||
|
|
||||||
|
|
||||||
class DepthUnit(enum.Enum):
|
class DepthUnit(enum.Enum):
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,14 @@ async def trigger_plan(body: PlanTriggerRequest):
|
||||||
# Property recommendations
|
# Property recommendations
|
||||||
p.get_components(cleaned)
|
p.get_components(cleaned)
|
||||||
|
|
||||||
|
# This is temp - this should happen after scoring
|
||||||
|
cleaned_property_data = DataProcessor.apply_averages_cleaning(
|
||||||
|
data_to_clean=pd.DataFrame([dict(**p.get_model_data(), LOCAL_AUTHORITY=p.data["local-authority"])]),
|
||||||
|
cleaning_data=cleaning_data,
|
||||||
|
cols_to_merge_on=['PROPERTY_TYPE', 'BUILT_FORM', 'CONSTRUCTION_AGE_BAND', 'LOCAL_AUTHORITY'],
|
||||||
|
)
|
||||||
|
p.set_number_lighting_outlets(cleaned_property_data)
|
||||||
|
|
||||||
recommender = Recommendations(property_instance=p, materials=materials)
|
recommender = Recommendations(property_instance=p, materials=materials)
|
||||||
property_recommendations = recommender.recommend()
|
property_recommendations = recommender.recommend()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -595,3 +595,33 @@ class Costs:
|
||||||
contingency = self.HIGH_RISK_CONTINGENCY
|
contingency = self.HIGH_RISK_CONTINGENCY
|
||||||
else:
|
else:
|
||||||
contingency = self.CONTINGENCY
|
contingency = self.CONTINGENCY
|
||||||
|
|
||||||
|
material_cost = material["material_cost"] * number_of_lights
|
||||||
|
labour_cost = material["labour_cost"] * number_of_lights * self.labour_adjustment_factor
|
||||||
|
|
||||||
|
subtotal_before_profit = material_cost + labour_cost
|
||||||
|
|
||||||
|
contingency_cost = subtotal_before_profit * 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_per_unit"] * number_of_lights
|
||||||
|
# Assume a single electrician installing
|
||||||
|
labour_days = (labour_hours / 8)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"total": total_cost,
|
||||||
|
"subtotal": subtotal_before_vat,
|
||||||
|
"vat": vat_cost,
|
||||||
|
"contingency": contingency_cost,
|
||||||
|
"preliminaries": preliminaries_cost,
|
||||||
|
"material": material_cost,
|
||||||
|
"profit": profit_cost,
|
||||||
|
"labour_hours": labour_hours,
|
||||||
|
"labour_days": labour_days,
|
||||||
|
"labour_cost": labour_cost
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from backend.Property import Property
|
from backend.Property import Property
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from recommendations.Costs import Costs
|
||||||
|
|
||||||
|
|
||||||
class LightingRecommendations:
|
class LightingRecommendations:
|
||||||
|
|
@ -11,7 +12,16 @@ class LightingRecommendations:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.property = property_instance
|
self.property = property_instance
|
||||||
self.materials = materials
|
self.costs = Costs(self.property)
|
||||||
|
|
||||||
|
material = [
|
||||||
|
material for material in materials if material["type"] == "low_energy_lighting_installation"
|
||||||
|
]
|
||||||
|
if len(material) != 1:
|
||||||
|
raise ValueError("Incorrect number of low energy lighting materials specified")
|
||||||
|
|
||||||
|
self.material = material[0]
|
||||||
|
self.recommendation = []
|
||||||
|
|
||||||
def recommend(self):
|
def recommend(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -32,3 +42,25 @@ class LightingRecommendations:
|
||||||
)
|
)
|
||||||
|
|
||||||
number_non_lel_outlets = round(number_non_lel_outlets)
|
number_non_lel_outlets = round(number_non_lel_outlets)
|
||||||
|
|
||||||
|
if number_non_lel_outlets == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the cost of the fittings
|
||||||
|
cost_result = self.costs.low_energy_lighting(
|
||||||
|
number_of_lights=number_non_lel_outlets,
|
||||||
|
number_current_lel_lights=number_lighting_outlets - number_non_lel_outlets,
|
||||||
|
material=self.material
|
||||||
|
)
|
||||||
|
|
||||||
|
self.recommendation = [
|
||||||
|
{
|
||||||
|
"parts": [],
|
||||||
|
"type": "sealing_open_fireplace",
|
||||||
|
"description": "Install low energy lighting in %s outlets" % str(number_non_lel_outlets),
|
||||||
|
"starting_u_value": None,
|
||||||
|
"new_u_value": None,
|
||||||
|
"sap_points": None,
|
||||||
|
**cost_result
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ from recommendations.WallRecommendations import WallRecommendations
|
||||||
from recommendations.RoofRecommendations import RoofRecommendations
|
from recommendations.RoofRecommendations import RoofRecommendations
|
||||||
from recommendations.VentilationRecommendations import VentilationRecommendations
|
from recommendations.VentilationRecommendations import VentilationRecommendations
|
||||||
from recommendations.FireplaceRecommendations import FireplaceRecommendations
|
from recommendations.FireplaceRecommendations import FireplaceRecommendations
|
||||||
|
from recommendations.LightingRecommendations import LightingRecommendations
|
||||||
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
|
from backend.ml_models.AnnualBillSavings import AnnualBillSavings
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -34,6 +35,7 @@ class Recommendations:
|
||||||
materials=[part for part in materials if part["type"] == "mechanical_ventilation"]
|
materials=[part for part in materials if part["type"] == "mechanical_ventilation"]
|
||||||
)
|
)
|
||||||
self.fireplace_recommender = FireplaceRecommendations(property_instance=property_instance)
|
self.fireplace_recommender = FireplaceRecommendations(property_instance=property_instance)
|
||||||
|
self.lighting_recommender = LightingRecommendations(property_instance=property_instance, materials=materials)
|
||||||
|
|
||||||
def recommend(self):
|
def recommend(self):
|
||||||
|
|
||||||
|
|
@ -69,6 +71,11 @@ class Recommendations:
|
||||||
if self.fireplace_recommender.recommendation:
|
if self.fireplace_recommender.recommendation:
|
||||||
property_recommendations.append(self.fireplace_recommender.recommendation)
|
property_recommendations.append(self.fireplace_recommender.recommendation)
|
||||||
|
|
||||||
|
# Lighting recommendations
|
||||||
|
self.lighting_recommender.recommend()
|
||||||
|
if self.lighting_recommender.recommendation:
|
||||||
|
property_recommendations.append(self.lighting_recommender.recommendation)
|
||||||
|
|
||||||
# We insert temporary ids into the recommendations which is important for the optimiser later
|
# We insert temporary ids into the recommendations which is important for the optimiser later
|
||||||
property_recommendations = self.insert_temp_recommendation_id(property_recommendations)
|
property_recommendations = self.insert_temp_recommendation_id(property_recommendations)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue