feat: implement forecast trending retrieval with fallback logic for completed simulations

main
Cizz22 1 week ago
parent 0d7010aff7
commit dd8fe1ecd7

@ -1048,11 +1048,17 @@ async def get_forecast_trending(
"""
Return EAF/EFOR/SOF/EDH for the last `limit` completed weekly or monthly
forecast simulations, oldest first (for chronological chart rendering).
Strategy:
1. Try simulations named Simulation_weekly_* / Simulation_monthly_* (scheduled forecasts).
2. If fewer than `limit` found, fall back to any completed simulation, grouped
by week or month bucket (latest sim per bucket), so the chart is populated
even before automated forecast simulations exist.
"""
name_prefix = f"Simulation_{time_range}_"
plant_node_name = "- TJB - Unit 3 -"
name_prefix = f"Simulation_{time_range}_"
query = (
base_join = (
select(AerosSimulation, AerosSimulationCalcResult)
.join(
AerosSimulationCalcResult,
@ -1060,15 +1066,20 @@ async def get_forecast_trending(
)
.join(AerosNode, AerosNode.id == AerosSimulationCalcResult.aeros_node_id)
.where(AerosSimulation.status == "completed")
.where(AerosSimulation.simulation_name.like(f"{name_prefix}%"))
.where(AerosNode.node_name == plant_node_name)
)
# First pass: named forecast simulations
named_q = (
base_join
.where(AerosSimulation.simulation_name.like(f"{name_prefix}%"))
.order_by(AerosSimulation.completed_at.desc())
.limit(limit)
)
result = await db_session.execute(named_q)
named_rows = result.all()
result = await db_session.execute(query)
rows = result.all()
def _format(rows):
return [
{
"date": sim.completed_at,
@ -1079,5 +1090,32 @@ async def get_forecast_trending(
"sof": calc.sof,
"edh": calc.derating_hours,
}
for sim, calc in reversed(rows) # oldest → newest for chart x-axis
for sim, calc in rows
]
if len(named_rows) >= limit:
return _format(reversed(named_rows))
# Fallback: any completed sim, group by week/month bucket (latest per bucket)
fallback_q = (
base_join
.order_by(AerosSimulation.completed_at.desc())
.limit(limit * 20)
)
result = await db_session.execute(fallback_q)
all_rows = result.all()
buckets: dict = {}
for sim, calc in all_rows:
ts = sim.completed_at
if ts is None:
continue
if time_range == "weekly":
bucket = ts.strftime("%G-W%V") # ISO week
else:
bucket = ts.strftime("%Y-%m")
if bucket not in buckets:
buckets[bucket] = (sim, calc)
sorted_items = sorted(buckets.items(), key=lambda x: x[0])[-limit:]
return _format((sim, calc) for _, (sim, calc) in sorted_items)

Loading…
Cancel
Save