mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge pull request #602 from Hestia-Homes/eco-eligiblity-bug
added additional fields to db and fixed flat roof recommendations bug
This commit is contained in:
commit
81ce9fd4de
5 changed files with 74 additions and 29 deletions
|
|
@ -833,9 +833,29 @@ class Property:
|
||||||
if self.current_energy_bill is None:
|
if self.current_energy_bill is None:
|
||||||
raise ValueError("Current energy bill has not been set")
|
raise ValueError("Current energy bill has not been set")
|
||||||
|
|
||||||
|
# IF we have a SAP05 overwrite, we pull out the relevant information
|
||||||
|
sap_05_overwritten = self.data.get("sap_05_overwritten", False)
|
||||||
|
|
||||||
|
sap_05_score, sap_05_epc_rating = None, None
|
||||||
|
if sap_05_overwritten:
|
||||||
|
if not self.old_data:
|
||||||
|
# Trying to fetch SAP05 EPC but no data
|
||||||
|
raise ValueError("Trying to fetch SAP05 EPC but no old data available")
|
||||||
|
# We get the last rating from the old data
|
||||||
|
newest_old_epc = max(self.old_data, key=lambda d: pd.to_datetime(d["lodgement-date"]))
|
||||||
|
# Get the rating and score
|
||||||
|
sap_05_score = int(newest_old_epc["current-energy-efficiency"])
|
||||||
|
sap_05_epc_rating = newest_old_epc["current-energy-rating"]
|
||||||
|
|
||||||
|
lodgement_date = self.data["lodgement-date"]
|
||||||
|
# We check if the lodgement date is more than 10 years old
|
||||||
|
is_expired = (datetime.now() - pd.to_datetime(lodgement_date)) > timedelta(days=3650)
|
||||||
|
|
||||||
property_details_epc = {
|
property_details_epc = {
|
||||||
"property_id": self.id,
|
"property_id": self.id,
|
||||||
"portfolio_id": portfolio_id,
|
"portfolio_id": portfolio_id,
|
||||||
|
"lodgement_date": datetime.fromisoformat(lodgement_date),
|
||||||
|
"is_expired": is_expired,
|
||||||
"full_address": self.data["address"],
|
"full_address": self.data["address"],
|
||||||
"total_floor_area": float(self.data["total-floor-area"]),
|
"total_floor_area": float(self.data["total-floor-area"]),
|
||||||
"walls": self.walls["clean_description"],
|
"walls": self.walls["clean_description"],
|
||||||
|
|
@ -891,7 +911,9 @@ class Property:
|
||||||
"current_energy_demand_heating_hotwater": self.current_energy_consumption_heating_hotwater,
|
"current_energy_demand_heating_hotwater": self.current_energy_consumption_heating_hotwater,
|
||||||
"estimated": self.data.get("estimated", False),
|
"estimated": self.data.get("estimated", False),
|
||||||
# We indicate if we've overwritten a SAP 05 EPC
|
# We indicate if we've overwritten a SAP 05 EPC
|
||||||
"sap_05_overwritten": self.data.get("sap_05_overwritten", False),
|
"sap_05_overwritten": sap_05_overwritten,
|
||||||
|
"sap_05_score": sap_05_score,
|
||||||
|
"sap_05_epc_rating": sap_05_epc_rating,
|
||||||
**self.current_energy_bill
|
**self.current_energy_bill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@ def prepare_plan_data(
|
||||||
valuation_increase = valuations["average_increase"]
|
valuation_increase = valuations["average_increase"]
|
||||||
valuation_post_retrofit = valuations["average_increased_value"]
|
valuation_post_retrofit = valuations["average_increased_value"]
|
||||||
|
|
||||||
|
# plan costing data
|
||||||
|
cost_of_works = sum([r["total"] for r in default_recommendations])
|
||||||
|
contingency_cost = sum([r["contingency"] for r in default_recommendations])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"portfolio_id": body.portfolio_id,
|
"portfolio_id": body.portfolio_id,
|
||||||
"property_id": p.id,
|
"property_id": p.id,
|
||||||
|
|
@ -69,6 +73,8 @@ def prepare_plan_data(
|
||||||
"energy_consumption_savings": float(energy_consumption_savings),
|
"energy_consumption_savings": float(energy_consumption_savings),
|
||||||
"valuation_post_retrofit": valuation_post_retrofit,
|
"valuation_post_retrofit": valuation_post_retrofit,
|
||||||
"valuation_increase": valuation_increase,
|
"valuation_increase": valuation_increase,
|
||||||
|
"cost_of_works": cost_of_works,
|
||||||
|
"contingency_cost": contingency_cost,
|
||||||
"plan_type": eco_packages.get(p.id, (None, None, None))[2]
|
"plan_type": eco_packages.get(p.id, (None, None, None))[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,8 @@ class PropertyDetailsEpcModel(Base):
|
||||||
property_id = Column(Integer, ForeignKey('property.id'), nullable=False)
|
property_id = Column(Integer, ForeignKey('property.id'), nullable=False)
|
||||||
portfolio_id = Column(Integer, ForeignKey('portfolio.id'), nullable=False)
|
portfolio_id = Column(Integer, ForeignKey('portfolio.id'), nullable=False)
|
||||||
full_address = Column(Text)
|
full_address = Column(Text)
|
||||||
|
lodgement_date = Column(DateTime)
|
||||||
|
is_expired = Column(Boolean)
|
||||||
total_floor_area = Column(Float)
|
total_floor_area = Column(Float)
|
||||||
walls = Column(Text)
|
walls = Column(Text)
|
||||||
walls_rating = Column(Integer, CheckConstraint('walls_rating>=1 AND walls_rating<=5'))
|
walls_rating = Column(Integer, CheckConstraint('walls_rating>=1 AND walls_rating<=5'))
|
||||||
|
|
@ -176,6 +178,8 @@ class PropertyDetailsEpcModel(Base):
|
||||||
current_energy_demand_heating_hotwater = Column(Float)
|
current_energy_demand_heating_hotwater = Column(Float)
|
||||||
estimated = Column(Boolean, default=False)
|
estimated = Column(Boolean, default=False)
|
||||||
sap_05_overwritten = Column(Boolean, default=False)
|
sap_05_overwritten = Column(Boolean, default=False)
|
||||||
|
sap_05_score = Column(Integer)
|
||||||
|
sap_05_epc_rating = Column(Enum(Epc))
|
||||||
# Include estimates for energy bills, across the different types of energy
|
# Include estimates for energy bills, across the different types of energy
|
||||||
heating_cost_current = Column(Float)
|
heating_cost_current = Column(Float)
|
||||||
hot_water_cost_current = Column(Float)
|
hot_water_cost_current = Column(Float)
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,9 @@ class Plan(Base):
|
||||||
energy_consumption_savings = Column(Float)
|
energy_consumption_savings = Column(Float)
|
||||||
valuation_post_retrofit = Column(Float)
|
valuation_post_retrofit = Column(Float)
|
||||||
valuation_increase = Column(Float)
|
valuation_increase = Column(Float)
|
||||||
|
# Financial metrics, excluding funding
|
||||||
|
cost_of_works = Column(Float)
|
||||||
|
contingency_cost = Column(Float)
|
||||||
|
|
||||||
|
|
||||||
class PlanRecommendations(Base):
|
class PlanRecommendations(Base):
|
||||||
|
|
|
||||||
|
|
@ -239,42 +239,52 @@ def get_wall_u_value(
|
||||||
return float(mapped_value)
|
return float(mapped_value)
|
||||||
|
|
||||||
|
|
||||||
|
def _try_convert_to_int(value):
|
||||||
|
try:
|
||||||
|
return int(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def extract_thickness(thickness, is_roof_room, is_at_rafters, is_loft, is_flat):
|
def extract_thickness(thickness, is_roof_room, is_at_rafters, is_loft, is_flat):
|
||||||
|
thickness_map = {
|
||||||
|
"below average": "50",
|
||||||
|
"average": "100",
|
||||||
|
"above average": "150",
|
||||||
|
"none": "0",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Normalise none value early
|
||||||
|
if thickness is None:
|
||||||
|
thickness = "none"
|
||||||
|
|
||||||
if is_roof_room or is_at_rafters:
|
if is_roof_room or is_at_rafters:
|
||||||
# TODO: We get None instead of a string none, this should be fixed
|
|
||||||
if thickness is None:
|
int_thickness = _try_convert_to_int(thickness)
|
||||||
thickness = "none"
|
if int_thickness is not None:
|
||||||
|
return int_thickness
|
||||||
# We re-map the thickness
|
# We re-map the thickness
|
||||||
thickness_map = {
|
|
||||||
"below average": "50",
|
thickness = thickness_map.get(thickness)
|
||||||
"average": "100",
|
if thickness is None:
|
||||||
"above average": "150",
|
return None
|
||||||
"none": "0",
|
|
||||||
}
|
return int(thickness)
|
||||||
thickness = thickness_map[thickness]
|
|
||||||
|
|
||||||
if is_flat:
|
if is_flat:
|
||||||
try:
|
return _try_convert_to_int(thickness)
|
||||||
thickness = int(thickness)
|
|
||||||
return thickness
|
|
||||||
except (TypeError, ValueError):
|
|
||||||
# If thickness is not a valid number (could be a string or None), return None
|
|
||||||
return None
|
|
||||||
|
|
||||||
if thickness in ["below average", "average", "above average", "none", None] or (
|
# Thicknes will never be none
|
||||||
not is_loft and not is_roof_room and not is_at_rafters
|
if thickness in thickness_map or (
|
||||||
|
not (is_loft or is_roof_room or is_at_rafters)
|
||||||
):
|
):
|
||||||
return None
|
return None
|
||||||
elif thickness.endswith("+"):
|
|
||||||
thickness = int(thickness[:-1])
|
if isinstance(thickness, str) and str(thickness).endswith("+"):
|
||||||
return thickness
|
return _try_convert_to_int(thickness[:-1])
|
||||||
else:
|
|
||||||
try:
|
# final attempt
|
||||||
thickness = int(thickness)
|
return _try_convert_to_int(thickness)
|
||||||
return thickness
|
|
||||||
except ValueError:
|
|
||||||
# If thickness is not a valid number (could be a string or None), return None
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_u_value_from_s9(
|
def get_u_value_from_s9(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue