diff --git a/backend/api/public.py b/backend/api/public.py index 41e2387..86bc6f1 100644 --- a/backend/api/public.py +++ b/backend/api/public.py @@ -386,6 +386,24 @@ async def get_revenue_forecast( logger.warning(f"Covers forecast failed: {e}") covers_by_date = {} + # DOW averages from recent 8 weeks — fallback when covers gives zero for future dates + dow_result = await db.execute( + text(""" + SELECT EXTRACT(ISODOW FROM date)::int AS dow, + AVG(dry) FILTER (WHERE dry > 0) AS avg_dry, + AVG(wet) FILTER (WHERE wet > 0) AS avg_wet + FROM newbook_net_revenue_data + WHERE date >= :cutoff AND date < :today + GROUP BY dow + """), + {"cutoff": today - timedelta(days=56), "today": today} + ) + dow_dry = {} + dow_wet = {} + for row in dow_result.fetchall(): + dow_dry[int(row.dow)] = float(row.avg_dry) if row.avg_dry else 0 + dow_wet[int(row.dow)] = float(row.avg_wet) if row.avg_wet else 0 + data = [] current = start while current <= end: @@ -461,7 +479,12 @@ async def get_revenue_forecast( dinner_forecast * get_spend_by_period('dinner', 'wet') ) else: - dry_otb = dry_forecast = wet_otb = wet_forecast = 0 + # No covers data — fall back to DOW average from recent 8 weeks + dow = current.isoweekday() # 1=Mon … 7=Sun + dry_otb = 0 + dry_forecast = dow_dry.get(dow, 0) + wet_otb = 0 + wet_forecast = dow_wet.get(dow, 0) day_data = { "date": current.isoformat(),