| @@ -361,8 +361,37 @@ | ||
| 361 | 361 | return $bookingRepository->getBookingCountsByAvailabilityIds($availabilityIds); |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | 364 | /** |
| 365 | + * Booked travellers for a date/time, counted from the bookings themselves. | |
| 366 | + * | |
| 367 | + * The `availability_id` join used by getBookingCountsByAvailabilityIds only | |
| 368 | + * counts bookings whose availability_id was set to this exact row — a stored | |
| 369 | + * link that the booking paths don't reliably set, and that rule-generated | |
| 370 | + * dates never have. That made the "Booked" column read 0 for real bookings. | |
| 371 | + * | |
| 372 | + * This counts by the booking's own identity — (trip, date, time) — via the | |
| 373 | + * booking_departures link both checkout and manual booking always create, so | |
| 374 | + * it can't desync. It is the same method the recurring-rule availability path | |
| 375 | + * already uses. Pass the row's own departure_time so a date with several | |
| 376 | + * departures reports each slot separately rather than the day's total. | |
| 377 | + */ | |
| 378 | + public function getBookedCountForSlot(int $tripId, string $date, ?string $departureTime = null): int | |
| 379 | + { | |
| 380 | + if ($tripId <= 0 || $date === '') { | |
| 381 | + return 0; | |
| 382 | + } | |
| 383 | + | |
| 384 | + // Dates are stored DATE-only; a datetime input would never string-match. | |
| 385 | + if (preg_match('/^(\d{4}-\d{2}-\d{2})/', $date, $m)) { | |
| 386 | + $date = $m[1]; | |
| 387 | + } | |
| 388 | + | |
| 389 | + $bookingRepository = new \Yatra\Repositories\BookingRepository(); | |
| 390 | + return $bookingRepository->countActiveSeatsForSlot($tripId, $date, $departureTime); | |
| 391 | + } | |
| 392 | + | |
| 393 | + /** | |
| 365 | 394 | * Update availability status based on booking counts |
| 366 | 395 | */ |
| 367 | 396 | public function updateAvailabilityStatusBasedOnBookings(int $availabilityId): bool |
| 368 | 397 | { |