adding materials to recommender

This commit is contained in:
Khalim Conn-Kowlessar 2025-08-18 18:02:56 +01:00
parent b7c913ec3f
commit 8e5388b1ea
5 changed files with 41 additions and 20 deletions

View file

@ -60,7 +60,7 @@ class GoogleSolarApi:
# Error Messages
ENTITY_NOT_FOUND_ERROR = 'Requested entity was not found.'
def __init__(self, api_key, max_retries=5):
def __init__(self, api_key, solar_materials: list, max_retries=5):
"""
Initialize the GoogleSolarApi class with the provided API key and maximum retries.
@ -87,6 +87,7 @@ class GoogleSolarApi:
# Indicates if we think we have both units attached to a semi-detached property
self.double_property = False
self.solar_materials = solar_materials
def get_building_insights(self, longitude, latitude, required_quality="MEDIUM", max_retries=None):
"""
@ -208,13 +209,13 @@ class GoogleSolarApi:
self.optimise_solar_configuration(
energy_consumption=energy_consumption,
is_building=is_building,
property_instance=property_instance
property_instance=property_instance,
)
# Finally, if we have a double property, we half the data we stored area
if self.double_property:
self.roof_area = self.roof_area / 2
self.floor_area = self.floor_area / 2
self.floor_area = float(self.floor_area) / 2
def save_to_db(self, session, uprns_to_location, scenario_type):
if self.insights_data is None:
@ -279,7 +280,9 @@ class GoogleSolarApi:
installation_life_span)) /
(1 - efficiency_depreciation_factor))
def optimise_solar_configuration(self, energy_consumption, is_building=False, property_instance=None):
def optimise_solar_configuration(
self, energy_consumption, is_building=False, property_instance=None
):
"""
Optimise the solar panel configuration for the building.
:return:
@ -321,9 +324,25 @@ class GoogleSolarApi:
if roi_summary["n_panels"].sum() < min_panels:
continue
total_panels = roi_summary["n_panels"].sum()
# find a product which is suitable for the ROI calc, without a battery. 400 Watts for the baseline
solar_product = next(
(m for m in self.solar_materials if m["type"] == "solar_pv" and
abs(m["size"] - (400 * total_panels) / 1000) < 0.1 and not m["includes_battery"]),
None
)
if solar_product is None:
logger.info("No suitable solar product found for the configuration with %d panels.", total_panels)
continue
total_cost = Costs.solar_pv(
n_panels=roi_summary["n_panels"].sum(),
has_battery=False,
solar_product=solar_product,
# We don't actually need scaffolding for the ROI calc
scaffolding_options=[
{"total_cost": 1000, "size": property_instance.number_of_floors},
{"total_cost": 1000, "size": 3}
],
# Assume the most amount of scaffolding
n_floors=3 if property_instance is None else property_instance.number_of_floors
)["total"]
@ -805,7 +824,8 @@ class GoogleSolarApi:
@classmethod
def unit_solar_analysis(
cls, unit_solar_config: List, input_properties: List[Property], session, body, google_solar_api_key: str
cls, unit_solar_config: List, input_properties: List[Property], session, body, google_solar_api_key: str,
solar_materials: list
):
if not unit_solar_config:
@ -844,7 +864,7 @@ class GoogleSolarApi:
)
continue
solar_api_client = cls(api_key=google_solar_api_key)
solar_api_client = cls(api_key=google_solar_api_key, solar_materials=solar_materials)
solar_api_client.get(
longitude=unit["longitude"],
latitude=unit["latitude"],
@ -852,7 +872,7 @@ class GoogleSolarApi:
is_building=False,
session=session,
uprn=unit["uprn"],
property_instance=property_instance
property_instance=property_instance,
)
# Store the data in the database

View file

@ -689,7 +689,7 @@ async def model_engine(body: PlanTriggerRequest):
building_solar_config=building_solar_config,
input_properties=input_properties,
session=session,
google_solar_api_key=get_settings().GOOGLE_SOLAR_API_KEY
google_solar_api_key=get_settings().GOOGLE_SOLAR_API_KEY,
)
input_properties = GoogleSolarApi.unit_solar_analysis(
@ -697,7 +697,8 @@ async def model_engine(body: PlanTriggerRequest):
input_properties=input_properties,
session=session,
body=body,
google_solar_api_key=get_settings().GOOGLE_SOLAR_API_KEY
solar_materials=[m for m in materials if m["type"] == "solar_pv"],
google_solar_api_key=get_settings().GOOGLE_SOLAR_API_KEY,
)
logger.info("Identifying property recommendations")

View file

@ -11,7 +11,7 @@ class FireplaceRecommendations(Definitions):
def __init__(
self,
property_instance: Property,
materials: list = None,
materials: list,
):
self.property = property_instance

View file

@ -1,11 +1,11 @@
import re
import backend.app.assumptions as assumptions
from recommendations.Costs import Costs, BOILER_UPGRADE_SCHEME_ASHP_VALUE
from recommendations.recommendation_utils import (
check_simulation_difference, override_costs, combine_recommendation_configs
)
from backend.Property import Property
from backend.app.plan.schemas import MEASURE_MAP
from recommendations.Costs import Costs
from etl.epc_clean.epc_attributes.MainheatAttributes import MainHeatAttributes
from etl.epc_clean.epc_attributes.HotWaterAttributes import HotWaterAttributes
from etl.epc_clean.epc_attributes.MainFuelAttributes import MainFuelAttributes
@ -85,7 +85,7 @@ class HeatingRecommender:
}
}
def __init__(self, property_instance: Property, materials: list = None):
def __init__(self, property_instance: Property, materials: list):
self.property = property_instance
self.costs = Costs(self.property)
@ -573,12 +573,12 @@ class HeatingRecommender:
if has_cavity_or_loft_recommendations:
description = description + (
f" You must ensure that the property has an insulated cavity and "
f"270mm+ loft insulation to qualify for the grant, to claim £"
f"{BOILER_UPGRADE_SCHEME_ASHP_VALUE} of funding from the boiler upgrade scheme grant. "
f"270mm+ loft insulation to qualify for the grant, to claim £7,500"
f" of funding from the boiler upgrade scheme grant. "
)
else:
description = description + (
f" £{BOILER_UPGRADE_SCHEME_ASHP_VALUE} of funding can be claimed from the boiler upgrade scheme"
f" £7,500 of funding can be claimed from the boiler upgrade scheme"
)
simulation_config = {

View file

@ -65,11 +65,11 @@ class Recommendations:
property_instance=property_instance, materials=materials
)
self.draught_proofing_recommender = DraughtProofingRecommendations(property_instance=property_instance)
self.fireplace_recommender = FireplaceRecommendations(property_instance=property_instance)
self.fireplace_recommender = FireplaceRecommendations(property_instance=property_instance, materials=materials)
self.lighting_recommender = LightingRecommendations(property_instance=property_instance, materials=materials)
self.windows_recommender = WindowsRecommendations(property_instance=property_instance, materials=materials)
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance)
self.heating_recommender = HeatingRecommender(property_instance=property_instance)
self.solar_recommender = SolarPvRecommendations(property_instance=property_instance, materials=materials)
self.heating_recommender = HeatingRecommender(property_instance=property_instance, materials=materials)
self.hotwater_recommender = HotwaterRecommendations(property_instance=property_instance)
self.secondary_heating_recommender = SecondaryHeating(property_instance=property_instance)