diff --git a/backend/api/public.py b/backend/api/public.py index 330860c..9faef9a 100644 --- a/backend/api/public.py +++ b/backend/api/public.py @@ -384,8 +384,11 @@ async def get_revenue_forecast( covers_by_date = {c["date"]: c for c in covers_data.get("data", [])} except Exception as e: logger.warning(f"Covers forecast failed: {e}") - await db.rollback() covers_by_date = {} + finally: + # covers_model catches exceptions internally and may leave the transaction + # aborted without raising — always rollback so subsequent queries succeed + await db.rollback() # DOW averages from recent 8 weeks — fallback when covers gives zero for future dates dow_result = await db.execute( diff --git a/backend/services/forecasting/covers_model.py b/backend/services/forecasting/covers_model.py index 9f26646..2ca615b 100644 --- a/backend/services/forecasting/covers_model.py +++ b/backend/services/forecasting/covers_model.py @@ -619,6 +619,7 @@ async def forecast_covers_for_date( } except Exception as e: logger.warning(f"Pickupv2 forecast failed for {night_before}: {e}") + await db.rollback() # Fallback to prior year pattern breakfast_pickup = max(0, hotel_guests_prior - hotel_guests_otb) breakfast_forecast = breakfast_otb + breakfast_pickup @@ -748,6 +749,7 @@ async def forecast_covers_for_date( pickup_rooms = pickupv2_dinner.get('pickup_rooms_total', 0) except Exception as e: logger.warning(f"Pickupv2 forecast failed for dinner {target_date}: {e}") + await db.rollback() # Calculate forecasted hotel guests (OTB + pickup) pickup_guests = pickup_rooms * guests_per_room @@ -840,6 +842,7 @@ async def forecast_covers_range( forecasts.append(day_forecast) except Exception as e: logger.warning(f"Failed to forecast covers for {current}: {e}") + await db.rollback() current += timedelta(days=1)