| @@ -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 |
| @@ -1835,8 +1840,9 @@ | ||
| 1835 | 1840 | 'age_min' => isset($meta['age_min']) ? (int) $meta['age_min'] : null, |
| 1836 | 1841 | 'age_max' => isset($meta['age_max']) ? (int) $meta['age_max'] : null, |
| 1837 | 1842 | 'min_pax' => isset($meta['min_pax']) ? (int) $meta['min_pax'] : null, |
| 1838 | 1843 | 'max_pax' => isset($meta['max_pax']) ? (int) $meta['max_pax'] : null, |
| 1844 | + 'group_overflow' => isset($meta['group_overflow']) && in_array($meta['group_overflow'], ['block', 'per_block'], true) ? $meta['group_overflow'] : 'block', | |
| 1839 | 1845 | ]; |
| 1840 | 1846 | } |
| 1841 | 1847 | } |
| 1842 | 1848 | |
| @@ -1886,8 +1892,9 @@ | ||
| 1886 | 1892 | if (!isset($pt['age_min'])) $pt['age_min'] = $meta['age_min']; |
| 1887 | 1893 | if (!isset($pt['age_max'])) $pt['age_max'] = $meta['age_max']; |
| 1888 | 1894 | if (!isset($pt['min_pax'])) $pt['min_pax'] = $meta['min_pax']; |
| 1889 | 1895 | if (!isset($pt['max_pax'])) $pt['max_pax'] = $meta['max_pax']; |
| 1896 | + $pt['group_overflow'] = $meta['group_overflow'] ?? 'block'; | |
| 1890 | 1897 | } |
| 1891 | 1898 | |
| 1892 | 1899 | // Payable amount (honors price / sale_price / discounted_price like TripPricingService) |
| 1893 | 1900 | if (!isset($pt['effective_price'])) { |
| @@ -2033,8 +2040,22 @@ | ||
| 2033 | 2040 | $from_label = __('Departure', 'yatra'); |
| 2034 | 2041 | $to_label = __('Return', 'yatra'); |
| 2035 | 2042 | } |
| 2036 | 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 | + | |
| 2037 | 2058 | // Use month-based keys for filtering for both day trips and multi-day trips |
| 2038 | 2059 | $filter_key = strtolower(date('M-Y', $departure_date)); |
| 2039 | 2060 | |
| 2040 | 2061 | // Must match {@see TripPricingService::resolveCardPricing}: trip-level mode wins; do not |
| @@ -2054,8 +2075,9 @@ | ||
| 2054 | 2075 | 'to_label' => $to_label, |
| 2055 | 2076 | 'to_date' => $to_display, |
| 2056 | 2077 | 'to_location' => $to_location, |
| 2057 | 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 | |
| 2058 | 2080 | 'date' => $avail->departure_date, // Raw date for dynamic pricing |
| 2059 | 2081 | 'spots_remaining' => $seats, // For dynamic pricing |
| 2060 | 2082 | 'seats' => $seats > 10 ? '10+' : (string) $seats, |
| 2061 | 2083 | 'seats_available' => $seats, |
| @@ -2078,8 +2100,10 @@ | ||
| 2078 | 2100 | 'is_sold_out' => $is_sold_out, |
| 2079 | 2101 | // Card-specific pricing |
| 2080 | 2102 | 'pricing_type' => $card_pricing_type, |
| 2081 | 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'), | |
| 2082 | 2106 | 'is_recurring' => !empty($avail->is_recurring), |
| 2083 | 2107 | 'rule_id' => $avail->rule_id ?? null, |
| 2084 | 2108 | ] + $dp_card_fields; |
| 2085 | 2109 | } |