| @@ -384,9 +384,9 @@ | ||
| 384 | 384 | $tripTitle = $d['trip']['title'] ?? ($d['trip_title'] ?? ''); |
| 385 | 385 | if ($tripTitle === '') { |
| 386 | 386 | continue; |
| 387 | 387 | } |
| 388 | - $cap = (int) ($d['max_capacity'] ?? $d['total_spots'] ?? 0); | |
| 388 | + $cap = $this->departureAvailabilityCapacity($d); | |
| 389 | 389 | $bkd = (int) ($d['booked_count'] ?? $d['travelers_count'] ?? 0); |
| 390 | 390 | if (!isset($occupancyByTripTitle[$tripTitle])) { |
| 391 | 391 | $occupancyByTripTitle[$tripTitle] = ['booked' => 0, 'capacity' => 0]; |
| 392 | 392 | } |
| @@ -464,13 +464,13 @@ | ||
| 464 | 464 | $upcomingTrips[] = [ |
| 465 | 465 | 'trip' => $d['trip']['title'] ?? ($d['trip_title'] ?? __('Unknown Trip', 'yatra')), |
| 466 | 466 | 'date' => $dateStr, |
| 467 | 467 | 'booked' => (int) ($d['booked_count'] ?? $d['travelers_count'] ?? 0), |
| 468 | - 'capacity' => (int) ($d['max_capacity'] ?? $d['total_spots'] ?? 0), | |
| 468 | + 'capacity' => $this->departureAvailabilityCapacity($d), | |
| 469 | 469 | ]; |
| 470 | 470 | } |
| 471 | 471 | |
| 472 | - $capacity = (int) ($d['max_capacity'] ?? $d['total_spots'] ?? 0); | |
| 472 | + $capacity = $this->departureAvailabilityCapacity($d); | |
| 473 | 473 | $booked = (int) ($d['booked_count'] ?? $d['travelers_count'] ?? 0); |
| 474 | 474 | $totalCapacity += $capacity; |
| 475 | 475 | $bookedCapacity += $booked; |
| 476 | 476 | if ($booked > 0) { |
| @@ -725,9 +725,9 @@ | ||
| 725 | 725 | |
| 726 | 726 | foreach ($departures as $d) { |
| 727 | 727 | $dateStr = $d['start_date'] ?? ($d['date'] ?? null); |
| 728 | 728 | $tripTitle = $d['trip']['title'] ?? ($d['trip_title'] ?? __('Unknown Trip', 'yatra')); |
| 729 | - $capacity = (int) ($d['max_capacity'] ?? $d['total_spots'] ?? 0); | |
| 729 | + $capacity = $this->departureAvailabilityCapacity($d); | |
| 730 | 730 | $booked = (int) ($d['booked_count'] ?? $d['travelers_count'] ?? 0); |
| 731 | 731 | $left = $capacity > 0 ? max(0, $capacity - $booked) : 0; |
| 732 | 732 | $status = strtolower((string) ($d['status'] ?? 'upcoming')); |
| 733 | 733 | |
| @@ -965,8 +965,52 @@ | ||
| 965 | 965 | 'refunds' => $refundsSummary, |
| 966 | 966 | 'top_destinations' => $topDestinations, |
| 967 | 967 | ], |
| 968 | 968 | ]); |
| 969 | + } | |
| 970 | + | |
| 971 | + /** | |
| 972 | + * Resolve a departure's capacity from the Availability configuration — the | |
| 973 | + * same authoritative source the Departures page and the /departures | |
| 974 | + * endpoint use (Availability date > recurring rule > the trip's | |
| 975 | + * max_travelers). The dashboard previously summed each departure's stored | |
| 976 | + * `max_capacity`, which could be a stale trip-settings value or a legacy | |
| 977 | + * "unlimited" default (e.g. 9999/11111), so its capacity and occupancy | |
| 978 | + * disagreed with the Departures page. Reading the live availability figure | |
| 979 | + * keeps them consistent. | |
| 980 | + * | |
| 981 | + * @param array<string,mixed> $d Departure row (from /departures) | |
| 982 | + */ | |
| 983 | + private function departureAvailabilityCapacity(array $d): int | |
| 984 | + { | |
| 985 | + static $capacityService = null; | |
| 986 | + static $memo = []; | |
| 987 | + if ($capacityService === null && class_exists('\\Yatra\\Services\\CapacityService')) { | |
| 988 | + $capacityService = new \Yatra\Services\CapacityService(); | |
| 989 | + } | |
| 990 | + | |
| 991 | + $tripId = (int) ($d['trip_id'] ?? ($d['trip']['id'] ?? 0)); | |
| 992 | + $date = (string) ($d['start_date'] ?? ($d['date'] ?? '')); | |
| 993 | + $time = isset($d['time']) ? (string) $d['time'] : ''; | |
| 994 | + $stored = (int) ($d['max_capacity'] ?? $d['total_spots'] ?? 0); | |
| 995 | + | |
| 996 | + // The same departure is read across several reporting loops, so memoise | |
| 997 | + // the resolution per (trip, date, time, stored) to avoid re-querying. | |
| 998 | + $key = $tripId . '|' . $date . '|' . $time . '|' . $stored; | |
| 999 | + if (isset($memo[$key])) { | |
| 1000 | + return $memo[$key]; | |
| 1001 | + } | |
| 1002 | + | |
| 1003 | + if ($capacityService !== null && $tripId > 0 && $date !== '') { | |
| 1004 | + $cap = $capacityService->getCapacityForDate($tripId, $date, $time !== '' ? $time : null); | |
| 1005 | + if ($cap > 0) { | |
| 1006 | + return $memo[$key] = $cap; | |
| 1007 | + } | |
| 1008 | + } | |
| 1009 | + | |
| 1010 | + // No availability/trip capacity resolved — fall back to the stored value, | |
| 1011 | + // but drop the legacy "unlimited" sentinels that would inflate occupancy. | |
| 1012 | + return $memo[$key] = ($stored >= 9999 ? 0 : $stored); | |
| 969 | 1013 | } |
| 970 | 1014 | |
| 971 | 1015 | /** |
| 972 | 1016 | * Helper to call an internal REST endpoint and return decoded data |