travel_date ?? '')); $booking_date_formatted = \Yatra\Helpers\FormatHelper::formatDateTime((string) ($booking->created_at ?? '')); // "Balance just paid" context detection. // A `?balance=paid` query arg is appended by the remaining-payment flows // (see PaymentGatewayController::create_remaining_balance_intent and // BookingSessionController::process_remaining_payment). We only render the // "balance paid" copy when BOTH the flag is present AND the booking actually // reports a paid status — that way a stale bookmarked URL or a tampered // query string can't show misleading content if a balance is still due. $is_balance_paid_request = isset($_GET['balance']) && sanitize_key((string) $_GET['balance']) === 'paid'; $booking_payment_status = (string) ($booking->payment_status ?? ''); $booking_amount_due = (float) ($booking->amount_due ?? 0); $booking_is_fully_paid = $booking_payment_status === 'paid' || $booking_amount_due <= 0.01; $show_balance_paid_banner = $is_balance_paid_request && $booking_is_fully_paid; // Resolve the most recent gateway used on this booking. // `$booking->payment_gateway` is the *initial* method chosen at booking time // (e.g. Pay Later), which is misleading when the customer later settled the // balance via a different gateway (e.g. Stripe). Show the latest payment's // gateway in the Payment Method line; fall back to the booking's stored // gateway when no payment row exists yet. $display_payment_gateway = (string) ($booking->payment_gateway ?? ''); if (!empty($booking->id)) { try { $latest_payment = (new \Yatra\Repositories\PaymentRepository())->findLatestByBookingId((int) $booking->id); if ($latest_payment) { $latest_gateway = (string) ($latest_payment->payment_gateway ?? $latest_payment->gateway ?? ''); if ($latest_gateway !== '') { $display_payment_gateway = $latest_gateway; } } } catch (\Throwable $e) { // Repository unavailable for some reason — keep the booking's stored gateway. } } // Resolved customer account URL (configurable via Settings → Permalink → Account base). $yatra_account_url = home_url('/' . \Yatra\Services\SettingsService::getAccountBase()); // Get status color $status_colors = [ 'pending' => ['bg' => '#fef3c7', 'text' => '#d97706', 'label' => 'Pending'], 'confirmed' => ['bg' => '#d1fae5', 'text' => '#059669', 'label' => 'Confirmed'], 'processing' => ['bg' => '#dbeafe', 'text' => '#2563eb', 'label' => 'Processing'], 'completed' => ['bg' => '#d1fae5', 'text' => '#059669', 'label' => 'Completed'], 'cancelled' => ['bg' => '#fee2e2', 'text' => '#dc2626', 'label' => 'Cancelled'], 'refunded' => ['bg' => '#fce7f3', 'text' => '#db2777', 'label' => 'Refunded'], 'on_hold' => ['bg' => '#e5e7eb', 'text' => '#6b7280', 'label' => 'On Hold'], ]; $status_style = $status_colors[$booking->status] ?? $status_colors['pending']; // Ensure Font Awesome CSS is available for icon-picker rendered icons (fa-solid/fa-regular). // This template can be displayed outside normal "trip page" contexts, so we explicitly // register/enqueue the shared stylesheet dependencies before printing the header. if (class_exists(\Yatra\Providers\FrontendAssetsProvider::class)) { \Yatra\Providers\FrontendAssetsProvider::registerCoreFrontendStylesheets(); if (wp_style_is('yatra-fontawesome-6', 'registered')) { wp_enqueue_style('yatra-fontawesome-6'); } if (wp_style_is('yatra-common', 'registered')) { wp_enqueue_style('yatra-common'); } } yatra_get_header(); // Hook for Pro modules to add custom scripts (Facebook Pixel, etc.) do_action('yatra_booking_confirmation_header', $booking); ?>

status === 'confirmed') { esc_html_e('Booking Confirmed!', 'yatra'); } elseif ($booking->status === 'pending') { esc_html_e('Booking Received!', 'yatra'); } elseif ($booking->status === 'cancelled') { esc_html_e('Booking Cancelled', 'yatra'); } else { esc_html_e('Booking Submitted!', 'yatra'); } ?>

status === 'confirmed') { esc_html_e('Thank you for your booking. We look forward to hosting you!', 'yatra'); } elseif ($booking->status === 'pending') { esc_html_e('Thank you for your booking. Your booking is pending confirmation.', 'yatra'); } elseif ($booking->status === 'cancelled') { esc_html_e('This booking has been cancelled.', 'yatra'); } else { esc_html_e('Thank you for your booking submission.', 'yatra'); } ?>

reference); ?>
featured_image)) { if (is_numeric($booking->featured_image)) { $featured_image_url = wp_get_attachment_url((int) $booking->featured_image) ?: ''; } else { $featured_image_url = $booking->featured_image; } } if ($featured_image_url === '') { $featured_image_url = YATRA_PLUGIN_URL . 'assets/images/trip-placeholder.svg'; $featured_image_is_placeholder = true; } else { $featured_image_is_placeholder = false; } ?>
<?php echo esc_attr($booking->trip_title); ?>

trip_title); ?>

trip_average_rating) && $booking->trip_review_count >= 0) : ?>
trip_average_rating); $has_half = ($booking->trip_average_rating - $filled_stars) >= 0.5; for ($i = 1; $i <= 5; $i++) : $class = $i <= $filled_stars ? 'yatra-star-filled' : ($has_half && $i === $filled_stars + 1 ? 'yatra-star-half' : ''); ?>
trip_average_rating, 1)); ?> trip_review_count, 'yatra') ), (int) $booking->trip_review_count ); ?>
duration_days)) : ?> duration_days ?? 0); $nights = (int) ($booking->duration_nights ?? 0); if ($days > 0 && $nights > 0) { printf( /* translators: 1: number of days, 2: number of nights. */ esc_html__('%1$d Days / %2$d Nights', 'yatra'), $days, $nights ); } elseif ($days > 0) { printf( esc_html( /* translators: %d: number of days. */ _n('%d Day', '%d Days', $days, 'yatra') ), $days ); } elseif ($nights > 0) { printf( esc_html( /* translators: %d: number of nights. */ _n('%d Night', '%d Nights', $nights, 'yatra') ), $nights ); } ?> difficulty_level)) : ?> difficulty_level ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo yatra_stored_picker_icon_markup( $difficulty['icon_picker'] ?? null, '', 'yatra-icon-sm' ); echo esc_html($difficulty['level'] ?? (string) $booking->difficulty_level); ?>
starting_location)) : ?>

starting_location); ?> ending_location) && $booking->ending_location !== $booking->starting_location) : ?> → ending_location); ?>

trip_destinations_list)) : ?>
trip_destinations_list as $destination) : ?>
trip_activities_list)) : ?>
trip_activities_list as $activity) : ?>
trip_categories_list)) : ?>
trip_categories_list as $category) : ?>

travelers_count); ?>
travelers)) : ?>

travelers as $index => $traveler) : $traveler_name = trim(($traveler['first_name'] ?? '') . ' ' . ($traveler['last_name'] ?? '')); ?>

subtotal ?? $booking->total_amount); $discount_amount = (float) ($booking->discount_amount ?? 0); $itinerary_costs_total = (float) ($booking->itinerary_costs_total ?? 0); $tax_amount = (float) ($booking->tax_amount ?? 0); $tax_inclusive = !empty($booking->tax_inclusive); $total_amount = (float) $booking->total_amount; $amount_paid = (float) ($booking->amount_paid ?? 0); $amount_due = (float) ($booking->amount_due ?? 0); // ── Tax breakdown (built first so it can gate later rows) ─ $tax_breakdown = []; if (!empty($booking->tax_details)) { $taxes = json_decode($booking->tax_details, true) ?: []; foreach ($taxes as $tax) { $tax_breakdown[] = [ 'name' => $tax['name'] ?? __('Tax', 'yatra'), 'rate' => (float) ($tax['rate'] ?? 0), 'amount' => (float) ($tax['amount'] ?? 0), ]; } } elseif ($tax_amount > 0) { $tax_breakdown[] = [ 'name' => __('Tax', 'yatra'), 'rate' => (float) ($booking->tax_rate ?? 0), 'amount' => $tax_amount, ]; } // ── Itinerary costs ─────────────────────────────────────── $itinerary_costs = []; if (!empty($booking->itinerary_costs)) { $itinerary_costs = json_decode($booking->itinerary_costs, true) ?: []; } // ── Additional services ─────────────────────────────────── $raw_services = apply_filters('yatra_booking_get_services', [], (int) ($booking->id ?? 0)); $selected_services = []; if (!empty($raw_services) && is_array($raw_services)) { foreach ($raw_services as $s) { $arr = is_array($s) ? $s : (array) $s; if (!isset($arr['selected']) || !empty($arr['selected'])) { $selected_services[] = $arr; } } } $services_total = 0.0; foreach ($selected_services as $s) { $services_total += (float) ($s['total_price'] ?? $s['calculated_price'] ?? $s['total_cost'] ?? $s['amount'] ?? $s['unit_price'] ?? $s['price'] ?? 0); } // ── Derived amounts ─────────────────────────────────────── // base_trip_cost: the trip price without services (services are embedded in db_subtotal by Pro) $base_trip_cost = $db_subtotal - $services_total; // taxable_amount: what tax is calculated on $taxable_amount = max(0.0, $db_subtotal - $discount_amount) + $itinerary_costs_total; $has_services = !empty($selected_services); $has_discount = $discount_amount > 0; $has_itinerary = !empty($itinerary_costs) && $itinerary_costs_total > 0; $has_tax = !empty($tax_breakdown); $show_taxable_row = $has_tax && ($has_discount || $has_itinerary); ?>
currency)); ?>
+
currency, false)); ?>
currency)); ?>
-currency)); ?>
currency)); ?>
currency)); ?>
+
0): ?> (%) +currency)); ?>
currency)); ?>
0 ? ' (' . esc_html($tax['rate']) . '%)' : '', esc_html(yatra_format_price($tax['amount'], $booking->currency)) ); ?>
0): ?>
currency)); ?>
0): ?> payment_method ?? 'full'); $remaining_balance = max(0.0, $total_amount - $amount_paid - $amount_due); if ($payment_method_type === 'deposit') { $due_now_label = __('Deposit Due Now', 'yatra'); } elseif ($payment_method_type === 'partial') { $due_now_label = __('Partial Payment Due Now', 'yatra'); } else { $due_now_label = __('Due Now', 'yatra'); } ?>
currency)); ?>
0.01): ?>
currency)); ?>

contact_data)) { $contact_data = json_decode($booking->contact_data, true) ?: []; } $contact_name = trim(( $contact_data['first_name'] ?? $booking->contact_first_name ?? ($booking->contact['first_name'] ?? '') ) . ' ' . ( $contact_data['last_name'] ?? $booking->contact_last_name ?? ($booking->contact['last_name'] ?? '') )); $contact_email = $contact_data['email'] ?? $booking->contact_email ?? ($booking->contact['email'] ?? ''); $contact_phone = $contact_data['phone'] ?? $booking->contact_phone ?? ($booking->contact['phone'] ?? ''); ?>

1

2

3

findLatestByBookingId((int) $booking->id); if ($latestPayment && in_array($latestPayment->status, ['completed', 'paid'], true)) : $invoiceToken = \Yatra\Controllers\PaymentGatewayController::issueInvoiceToken( (int) $latestPayment->id, (int) ($latestPayment->booking_id ?? $booking->id) ); $invoiceUrl = add_query_arg( [ 'download' => '1', 'invoice_token' => $invoiceToken, ], rest_url('yatra/v1/payment/' . (int) $latestPayment->id . '/invoice') ); ?>