implementing database call for funding

This commit is contained in:
Khalim Conn-Kowlessar 2025-08-20 19:26:05 +01:00
parent b715402999
commit 529830ee0f
5 changed files with 121 additions and 34 deletions

View file

@ -218,7 +218,7 @@ class Property:
# self.whlg_eligibility = None
self.scheme = None
self.funded_measures = None
self.full_project_funding = None
self.project_funding = None
self.total_uplift = None
self.full_project_score = None
self.partial_project_score = None
@ -1347,7 +1347,7 @@ class Property:
self,
scheme,
funded_measures,
full_project_funding,
project_funding,
total_uplift,
full_project_score,
partial_project_score,
@ -1357,11 +1357,11 @@ class Property:
This method inserts the funding into the property object
"""
self.scheme = scheme
self.funded_measures = funded_measures,
self.full_project_funding = full_project_funding,
self.total_uplift = total_uplift,
self.full_project_score = full_project_score,
self.partial_project_score = partial_project_score,
self.funded_measures = funded_measures
self.project_funding = project_funding
self.total_uplift = total_uplift
self.full_project_score = full_project_score
self.partial_project_score = partial_project_score
self.uplift_project_score = uplift_project_score
def identify_ventilation(self):

View file

@ -0,0 +1,60 @@
from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
from backend.app.db.models.funding import FundingPackage, FundingPackageMeasures
def upload_funding(session: Session, p, plan_id, property_recommendations):
try:
# Prepare data for bulk insert for Recommendation
funding_package_data = {
"plan_id": plan_id,
"scheme": p.scheme,
"full_project_funding": p.full_project_funding,
"total_uplift": p.total_uplift,
"full_project_score": p.full_project_score,
"partial_project_score": p.partial_project_score,
"uplift_project_score": p.uplift_project_score
}
# upload the funding package data and get back the ID
new_funding_package = FundingPackage(**funding_package_data)
session.add(new_funding_package)
session.flush()
session.commit()
funding_package_id = new_funding_package.id
# We now prepare the list of funding measures to be uploaded
funding_measures_data = []
for part in p.funded_measures:
recommendation_id = part["id"]
recommendation = next(
(x for x in property_recommendations if x["recommendation_id"] == recommendation_id), {}
)
material_id = None
if recommendation["parts"]:
material_id = recommendation["parts"][0]["id"]
funding_measures_data.append({
"funding_package_id": funding_package_id,
"measure": part["type"],
"material_id": material_id,
"innovation_uplift": float(part["innovation_uplift"]),
"partial_project_score": float(part["partial_project_score"]),
"uplift_project_score": float(part["uplift_project_score"])
})
session.bulk_insert_mappings(FundingPackageMeasures, funding_measures_data)
# flush the changes to get the newly created IDs
session.flush()
# Commit the transaction
session.commit()
return True
except SQLAlchemyError as e:
# Rollback the transaction in case of an error
session.rollback()
print(f"An error occurred: {e}")
return False

View file

@ -0,0 +1,45 @@
import enum
from sqlalchemy import Column, Integer, String, Float, Enum, TIMESTAMP, BigInteger, ForeignKey
from sqlalchemy.orm import declarative_base
from sqlalchemy.sql import func
from backend.app.db.models.recommendations import Plan
from backend.app.db.models.materials import MaterialType, Material
Base = declarative_base()
class SchemeEnum(enum.Enum):
eco4 = "eco4"
gbis = "gbis"
whlg = "whlg"
none = "none"
class FundingPackage(Base):
__tablename__ = 'funding_package'
id = Column(Integer, primary_key=True, autoincrement=True)
plan_id = Column(BigInteger, ForeignKey(Plan.id), nullable=False)
scheme = Column(String, nullable=False) # Assuming Scheme is a string representation
created_at = Column(TIMESTAMP, nullable=False, server_default=func.now())
project_funding = Column(Float)
total_uplift = Column(Float)
full_project_score = Column(Float)
partial_project_score = Column(Float)
uplift_project_score = Column(Float)
class FundingPackageMeasures(Base):
__tablename__ = 'funding_package_measures'
id = Column(Integer, primary_key=True, autoincrement=True)
funding_package_id = Column(BigInteger, ForeignKey(FundingPackage.id), nullable=False)
measure = Column(
Enum(MaterialType, values_callable=lambda x: [e.value for e in x], create_constraint=False),
nullable=False
)
material_id = Column(BigInteger, ForeignKey(Material.id), nullable=False) # Assuming material table exists
innovation_uplift = Column(Float)
partial_project_score = Column(Float)
uplift_project_score = Column(Float)

View file

@ -934,8 +934,8 @@ async def model_engine(body: PlanTriggerRequest):
# This is the list of measures that we will recommend
funded_measures = optimal_solution["items"]
solution = funded_measures + optimal_solution["unfunded_items"]
# This is the total amount of funding that the project will product (£)
full_project_funding = optimal_solution["full_project_funding"]
# This is the total amount of funding that the project will produce (including uplifts) (£)
project_funding = optimal_solution["full_project_funding"]
# This is the total amount of funding associated to the uplift (£)
total_uplift = optimal_solution["total_uplift"]
# This is the funding scheme selected
@ -998,7 +998,7 @@ async def model_engine(body: PlanTriggerRequest):
scheme = "gbis"
funded_measures = solution if scheme in ["gbis", "eco4"] else []
full_project_funding = 0 if funding.full_project_abs is not None else funding.full_project_abs
project_funding = 0 if funding.full_project_abs is not None else funding.full_project_abs
total_uplift = funding.eco4_uplift
full_project_score = 0 if funding.full_project_abs is not None else funding.full_project_abs
partial_project_score = funding.partial_project_abs
@ -1022,7 +1022,7 @@ async def model_engine(body: PlanTriggerRequest):
p.insert_funding(
scheme=scheme,
funded_measures=funded_measures,
full_project_funding=full_project_funding,
project_funding=project_funding,
total_uplift=total_uplift,
full_project_score=full_project_score,
partial_project_score=partial_project_score,
@ -1055,28 +1055,6 @@ async def model_engine(body: PlanTriggerRequest):
# need to be updated
rec["default"] = True
# ~~~~~~~~~~~~~~~~
# Funding
# ~~~~~~~~~~~~~~~~
# for p in input_properties:
# funding_calulator = Funding(
# tenure=body.housing_type,
# starting_epc=p.data["current-energy-rating"],
# starting_sap=int(p.data["current-energy-efficiency"]),
# postcode=p.postcode,
# floor_area=p.floor_area,
# council_tax_band=None, # This is seemingly always None at the moment
# property_recommendations=recommendations[p.id],
# project_scores_matrix=eco_project_scores_matrix,
# whlg_eligible_postcodes=whlg_eligible_postcodes,
# gbis_abs_rate=15,
# eco4_abs_rate=15,
# )
# funding_calulator.check_eligibiltiy()
# # Insert finding
# p.insert_funding(funding_calulator)
logger.info("Uploading recommendations to the database")
# If we have any work to do, we create a new scenario
if body.scenario_id:
@ -1165,6 +1143,10 @@ async def model_engine(body: PlanTriggerRequest):
session, recommendations_to_upload, p.id, new_plan_id
)
upload_funding(
session,
)
property_valuation_increases.append(
valuations["average_increased_value"] - valuations["current_value"]
)

View file

@ -276,7 +276,7 @@ class SolarPvRecommendations:
self.recommendation.append(
{
"phase": phase,
"parts": [],
"parts": [solar_pv_product],
"type": "solar_pv",
"measure_type": "solar_pv",
"description": description,