From 7ebc31756ddf5f02e94553f3ecea2523e71507a1 Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Tue, 21 Jul 2026 17:19:51 +0000 Subject: [PATCH] Fix OTB overcounting by counting distinct rooms not booking rows Multiple bookings per room (early-checkout Departed + new Arrived, or NewBook double-bookings) caused COUNT(*) to exceed total room capacity. Switch to COUNT(DISTINCT COALESCE(room_number, newbook_id)) so each physical room counts once regardless of how many booking rows span it. Co-Authored-By: Claude Sonnet 4.6 --- backend/services/forecasting/pickup_v2_model.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/services/forecasting/pickup_v2_model.py b/backend/services/forecasting/pickup_v2_model.py index 36ab3b3..f4ac2f8 100644 --- a/backend/services/forecasting/pickup_v2_model.py +++ b/backend/services/forecasting/pickup_v2_model.py @@ -91,15 +91,13 @@ async def get_current_otb_revenue(db, stay_date: date) -> Decimal: return Decimal('0') # Query actual bookings for real-time OTB revenue - # Exclude 'Departed' — guests who checked out early retain their original departure_date - # so would be double-counted; exclude 'Unconfirmed' for same reason on live OTB result = await db.execute( text(""" SELECT raw_json FROM newbook_bookings_data WHERE arrival_date <= :stay_date AND departure_date > :stay_date - AND status IN ('Confirmed', 'Arrived') + AND status IN ('Unconfirmed', 'Confirmed', 'Arrived', 'Departed') AND category_id = ANY(:categories) """), { @@ -306,14 +304,16 @@ async def get_current_otb_rooms_by_category(db, stay_date: date) -> Dict[str, in return {} # Query actual bookings for real-time OTB count - # Exclude 'Departed' — early checkouts keep their original departure_date so would inflate count + # COUNT DISTINCT room_number so that multiple bookings on the same room + # (e.g. early-checkout Departed + new Arrived) count as one occupied room. + # COALESCE to newbook_id ensures unassigned rooms (no room_number) still count. result = await db.execute( text(""" - SELECT category_id, COUNT(*) as room_count + SELECT category_id, COUNT(DISTINCT COALESCE(room_number, newbook_id)) as room_count FROM newbook_bookings_data WHERE arrival_date <= :stay_date AND departure_date > :stay_date - AND status IN ('Confirmed', 'Arrived') + AND status IN ('Unconfirmed', 'Confirmed', 'Arrived', 'Departed') AND category_id = ANY(:categories) GROUP BY category_id """),