from sqlalchemy import func from backend.app.db.models.recommendations import ( PlanModel, PlanRecommendations, Recommendation, ScenarioModel, ) def aggregate_portfolio_recommendations( session, portfolio_id: int, scenario_id: int, total_valuation_increase: float, labour_days: float, aggregated_data: dict, ): # Aggregate multiple fields aggregates = ( session.query( func.sum(Recommendation.estimated_cost).label("cost"), func.sum(Recommendation.total_work_hours).label("total_work_hours"), func.sum(Recommendation.kwh_savings).label("energy_savings"), func.sum(Recommendation.co2_equivalent_savings).label( "co2_equivalent_savings" ), func.sum(Recommendation.energy_cost_savings).label("energy_cost_savings"), ) .join( PlanRecommendations, PlanRecommendations.recommendation_id == Recommendation.id, ) .join(PlanModel, PlanModel.id == PlanRecommendations.plan_id) .filter( PlanModel.portfolio_id == portfolio_id, PlanModel.scenario_id == scenario_id, Recommendation.default == True, ) .one() ) # Contingeny and funding are in the aggregated data aggregates_dict = { "cost": aggregates.cost or 0, "total_work_hours": aggregates.total_work_hours or 0, "energy_savings": aggregates.energy_savings or 0, "co2_equivalent_savings": aggregates.co2_equivalent_savings or 0, "energy_cost_savings": aggregates.energy_cost_savings or 0, **aggregated_data, } # Get the scenario and update the fields. This data needs to be stored against the scenario, not the portfolio portfolio_scenario = session.query(ScenarioModel).filter_by(id=scenario_id).one() # Update the data for key, value in aggregates_dict.items(): setattr(portfolio_scenario, key, value) # Insert total valuation increase and labour days portfolio_scenario.property_valuation_increase = total_valuation_increase portfolio_scenario.labour_days = labour_days # Merge the updated portfolio plan back into the session session.merge(portfolio_scenario) session.flush()