Model/backend/app/db/functions/funding_functions.py
2025-12-22 18:46:19 +08:00

141 lines
4.9 KiB
Python

from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import insert
from backend.app.db.models.funding import FundingPackage, FundingPackageMeasures
def upload_funding(session: Session, p, plan_id, recommendations_to_upload):
try:
# Prepare data for bulk insert for Recommendation
funding_package_data = {
"plan_id": plan_id,
"scheme": p.scheme,
"project_funding": float(p.project_funding),
"total_uplift": float(p.total_uplift),
"full_project_score": float(p.full_project_score),
"partial_project_score": float(p.partial_project_score),
"uplift_project_score": float(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 recommendations_to_upload if x["recommendation_id"] == recommendation_id), {}
)
material_id = None
if recommendation["parts"]:
material_id = recommendation["parts"][0]["id"]
part_type = part["type"]
if part_type == "extension_cavity_wall_insulation":
part_type = "cavity_wall_insulation"
if part_type == "sealing_open_fireplace":
part_type = "sealing_fireplace"
if part == "low_energy_lighting":
part_type = "low_energy_lighting_installation"
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"])
})
# Bulk insert the funding measures data
if funding_measures_data:
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
def bulk_upload_funding_packages(
session: Session,
funding_payload: list[dict],
):
"""
Bulk upload:
- funding_package
- funding_package_measures
Assumes caller manages the transaction.
"""
if not funding_payload:
return
# ---------------------------------------------------------
# 1. Prepare funding package rows
# ---------------------------------------------------------
funding_rows = []
measures_by_index = []
for f in funding_payload:
funding_rows.append({
"plan_id": f["plan_id"],
"scheme": f["scheme"],
"project_funding": f["project_funding"],
"total_uplift": f["total_uplift"],
"full_project_score": f["full_project_score"],
"partial_project_score": f["partial_project_score"],
"uplift_project_score": f["uplift_project_score"],
})
measures_by_index.append(f.get("measures", []))
# ---------------------------------------------------------
# 2. Insert funding packages and get IDs
# ---------------------------------------------------------
result = session.execute(
insert(FundingPackage)
.values(funding_rows)
.returning(FundingPackage.id)
)
funding_package_ids = [row[0] for row in result]
# ---------------------------------------------------------
# 3. Insert funding package measures
# ---------------------------------------------------------
measures_rows = []
for funding_package_id, measures in zip(
funding_package_ids, measures_by_index
):
for m in measures:
measures_rows.append({
"funding_package_id": funding_package_id,
"measure": m["measure"],
"material_id": m["material_id"],
"innovation_uplift": m["innovation_uplift"],
"partial_project_score": m["partial_project_score"],
"uplift_project_score": m["uplift_project_score"],
})
if measures_rows:
session.execute(
insert(FundingPackageMeasures).values(measures_rows)
)