PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | app/Controllers/TripController.php +25 -3 3.0.8 → 3.0.16 View file →
@@ -1515,13 +1515,15 @@
1515 1515
1516 1516 // Fetch availability dates using centralized resolution service
1517 1517 $resolutionService = new \Yatra\Services\AvailabilityResolutionService();
1518 1518
1519 - // Always show all dates from today onwards (selected_date is only for highlighting)
1519 + // Always show all dates from today onwards (selected_date is only for
1520 + // highlighting), up to the configurable booking horizon (Settings →
1521 + // Booking; 12 months unless changed — the previous hard-coded value).
1520 1522 $fromDate = date('Y-m-d');
1521 - $toDate = date('Y-m-d', strtotime('+12 months'));
1523 + $toDate = yatra_get_availability_horizon_date($fromDate);
1522 1524
1523 - $availability_dates = $resolutionService->getAllAvailabilityDates($id, $fromDate, $toDate);
1525 + $availability_dates = $resolutionService->getAllAvailabilityDates($id, $fromDate, $toDate, \Yatra\Services\SettingsService::isEnabled('show_sold_out'));
1524 1526
1525 1527 // Determine if this is a day trip
1526 1528 $is_single_day = ($trip->duration_days ?? 1) <= 1;
1527 1529
@@ -1593,8 +1595,11 @@
1593 1595 'discounted_price' => isset($trip->discounted_price) ? (float) $trip->discounted_price : 0,
1594 1596 'sale_price' => isset($trip->sale_price) ? (float) $trip->sale_price : 0,
1595 1597 'currency' => SettingsService::getCurrency(),
1596 1598 'duration_days' => isset($trip->duration_days) ? (int) $trip->duration_days : 1,
1599 + // Hour-based day tours show "8 Hours" instead of "1 Day" on the
1600 + // availability cards. 0 for every existing (day-based) trip.
1601 + 'duration_hours' => isset($trip->duration_hours) ? (int) $trip->duration_hours : 0,
1597 1602 'max_travelers' => isset($trip->max_travelers) ? (int) $trip->max_travelers : 20,
1598 1603 'min_travelers' => isset($trip->min_travelers) ? (int) $trip->min_travelers : 1,
1599 1604 'pricing_type' => $trip->pricing_type ?? 'regular',
1600 1605 'price_types' => $trip->price_types ?? [], // Include price_types for traveler-based pricing
@@ -2035,8 +2040,22 @@
2035 2040 $from_label = __('Departure', 'yatra');
2036 2041 $to_label = __('Return', 'yatra');
2037 2042 }
2038 2043
2044 + // Per-card duration: derive from THIS card's departure→return span
2045 + // so the displayed "X Days" always matches the departure/return
2046 + // dates shown on the same card. When no custom arrival is stored,
2047 + // $return_date is departure + (duration_days - 1), so the span
2048 + // equals the trip's duration_days (no visible change). Only when an
2049 + // operator stored an arrival that disagrees with the trip default
2050 + // does this diverge — and then the customer sees a self-consistent
2051 + // card (e.g. "10 Days" over a Jun 25 → Jul 04 span) instead of a
2052 + // "9 Days" badge contradicting the dates. round() (not floor())
2053 + // absorbs any ±1h DST drift between two local-midnight timestamps.
2054 + $card_duration_days = $is_single_day
2055 + ? max(1, (int) ($trip_data->duration_days ?? 1))
2056 + : max(1, (int) round(($return_date - $departure_date) / DAY_IN_SECONDS) + 1);
2057 +
2039 2058 // Use month-based keys for filtering for both day trips and multi-day trips
2040 2059 $filter_key = strtolower(date('M-Y', $departure_date));
2041 2060
2042 2061 // Must match {@see TripPricingService::resolveCardPricing}: trip-level mode wins; do not
@@ -2056,8 +2075,9 @@
2056 2075 'to_label' => $to_label,
2057 2076 'to_date' => $to_display,
2058 2077 'to_location' => $to_location,
2059 2078 'date_display' => $date_display, // For day trips: "Saturday, 30 Nov 2025"
2079 + 'duration_days' => $card_duration_days, // Inclusive span of THIS card's dates
2060 2080 'date' => $avail->departure_date, // Raw date for dynamic pricing
2061 2081 'spots_remaining' => $seats, // For dynamic pricing
2062 2082 'seats' => $seats > 10 ? '10+' : (string) $seats,
2063 2083 'seats_available' => $seats,
@@ -2080,8 +2100,10 @@
2080 2100 'is_sold_out' => $is_sold_out,
2081 2101 // Card-specific pricing
2082 2102 'pricing_type' => $card_pricing_type,
2083 2103 'traveler_pricing' => $card_traveler_pricing,
2104 + 'price_unit' => $cardPricing['price_unit'] ?? 'per_person',
2105 + 'price_unit_label' => $cardPricing['price_unit_label'] ?? __('per person', 'yatra'),
2084 2106 'is_recurring' => !empty($avail->is_recurring),
2085 2107 'rule_id' => $avail->rule_id ?? null,
2086 2108 ] + $dp_card_fields;
2087 2109 }