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/PaymentGatewayController.php +40 -11 3.0.14.2 → 3.0.16 View file →
@@ -812,11 +812,11 @@
812 812 }
813 813
814 814 $previousBookingStatus = (string) ($booking->status ?? 'pending');
815 815
816 - // Only auto-confirm when the operator allows it (or the booking is now
817 - // fully paid). A deposit / partial payment leaves the booking pending
818 - // when "Auto-Confirm Bookings" is off, for the operator to confirm.
816 + // Only auto-confirm when "Auto-Confirm Bookings" is on; otherwise the
817 + // booking stays pending for the operator to confirm manually, regardless
818 + // of a successful (full or partial) payment.
819 819 $should_confirm = \yatra_should_confirm_booking_on_payment($new_amount_due <= 0, $bookingId);
820 820
821 821 // Update booking
822 822 $booking_update = [
@@ -829,9 +829,9 @@
829 829 }
830 830 $this->bookingRepository->update($bookingId, $booking_update);
831 831
832 832 if ($should_confirm) {
833 - \yatra_trigger_booking_confirmed($bookingId, $previousBookingStatus);
833 + \yatra_trigger_booking_confirmed($bookingId, $previousBookingStatus, true);
834 834 }
835 835
836 836 // Clear remaining payment session if this was a remaining payment
837 837 if (function_exists('yatra_has_remaining_session') && yatra_has_remaining_session()) {
@@ -868,9 +868,11 @@
868 868 return new WP_Error('payment_not_found', __('Payment not found.', 'yatra'), ['status' => 404]);
869 869 }
870 870
871 871 // Authorisation:
872 - // 1. Administrators can always access (no further checks).
872 + // 1. Staff can always access (no further checks): a WP administrator,
873 + // or a user holding Yatra's yatra_view_bookings capability, which is
874 + // the same audience that already sees every booking in the list.
873 875 // 2. Logged-in owner of the booking can access.
874 876 // 3. Anyone with a valid signed `invoice_token` (HMAC) can access — used on the
875 877 // booking-confirmation page so guest checkouts and post-session views work.
876 878 // 4. Legacy guest path: `booking_token` (active checkout transient) — kept for BC.
@@ -876,9 +878,9 @@
876 878 // 4. Legacy guest path: `booking_token` (active checkout transient) — kept for BC.
877 879 $currentUserId = (int) get_current_user_id();
878 880 $bookingUserId = (int) ($payment->booking_user_id ?? $payment->user_id ?? 0);
879 881 $paymentBookingId = (int) ($payment->booking_id ?? 0);
880 - $isAdmin = current_user_can('manage_options');
882 + $isAdmin = current_user_can('manage_options') || current_user_can('yatra_view_bookings');
881 883 $authorised = false;
882 884
883 885 if ($isAdmin) {
884 886 $authorised = true;
@@ -995,9 +997,12 @@
995 997 'payment_date' => $paymentDate,
996 998 'payment_status' => ucfirst($payment->status ?? 'paid'),
997 999 'status_class' => in_array(strtolower((string) ($payment->status ?? '')), ['paid', 'completed', 'success'], true) ? 'paid' : 'pending',
998 1000 'trip_title' => $trip->title ?? $payment->trip_title ?? __('Trip Booking', 'yatra'),
999 - 'payment_method' => ucfirst($payment->gateway ?? $payment->payment_method ?? 'Online'),
1001 + 'payment_method' => $this->gatewayLabel(
1002 + $payment->gateway ?? $payment->payment_method ?? null,
1003 + __('Online', 'yatra')
1004 + ),
1000 1005 // Booking-only fallback chain (never a payment identifier) so the
1001 1006 // invoice number always resolves to the booking reference.
1002 1007 'booking_ref' => $payment->booking_reference ?? $payment->booking_number ?? (string) ($payment->booking_id ?? ''),
1003 1008 'travel_date' => $travelDate,
@@ -1031,8 +1036,23 @@
1031 1036 }
1032 1037 }
1033 1038
1034 1039 /**
1040 + * Customer-facing label for a gateway id on a document.
1041 + *
1042 + * Uses the same title the checkout shows (operator's custom title, else the
1043 + * gateway's translated one). Falls back to the prettified id — the previous
1044 + * behaviour — when the gateway is not registered any more, so an invoice for
1045 + * a payment taken through a since-removed gateway still reads sensibly.
1046 + */
1047 + private function gatewayLabel(?string $gatewayId, string $fallback = 'Online'): string
1048 + {
1049 + return function_exists('yatra_payment_gateway_label')
1050 + ? yatra_payment_gateway_label($gatewayId, $fallback)
1051 + : ($gatewayId ? ucwords(str_replace(['_', '-'], ' ', $gatewayId)) : $fallback);
1052 + }
1053 +
1054 + /**
1035 1055 * Download a PRO-FORMA invoice for a booking that has no payment yet
1036 1056 * (offline gateways such as Bank Transfer). Shows the amount due and any
1037 1057 * gateway-supplied payment instructions (via yatra_invoice_payment_instructions)
1038 1058 * so the customer knows how to pay. Renders the same pdf/invoice.php template.
@@ -1053,14 +1073,17 @@
1053 1073 if (!$booking) {
1054 1074 return new WP_Error('booking_not_found', __('Booking not found.', 'yatra'), ['status' => 404]);
1055 1075 }
1056 1076
1057 - // Authorisation mirrors download_invoice: admin -> owner -> signed
1077 + // Authorisation mirrors download_invoice: staff -> owner -> signed
1058 1078 // booking-scoped invoice_token (paymentId 0) -> guest booking_token.
1079 + // Staff means a WP admin OR a user holding Yatra's booking-view
1080 + // capability, so Pro Team roles (which deliberately don't carry
1081 + // manage_options) can use the admin "Download invoice" action.
1059 1082 $currentUserId = (int) get_current_user_id();
1060 1083 $bookingUserId = (int) ($booking->user_id ?? 0);
1061 1084 $authorised = false;
1062 - if (current_user_can('manage_options')) {
1085 + if (current_user_can('manage_options') || current_user_can('yatra_view_bookings')) {
1063 1086 $authorised = true;
1064 1087 } elseif ($currentUserId && $bookingUserId && $currentUserId === $bookingUserId) {
1065 1088 $authorised = true;
1066 1089 } elseif ($invoiceToken !== '' && self::verifyInvoiceToken($invoiceToken, 0, $bookingId)) {
@@ -1114,9 +1137,12 @@
1114 1137 ? __('Paid', 'yatra')
1115 1138 : ($paid > 0.0 ? __('Partially Paid', 'yatra') : __('Payment Pending', 'yatra')),
1116 1139 'status_class' => $due <= 0.0 ? 'paid' : ($paid > 0.0 ? 'partial' : 'pending'),
1117 1140 'trip_title' => $trip->title ?? $booking->trip_title ?? __('Trip Booking', 'yatra'),
1118 - 'payment_method' => ucwords(str_replace('_', ' ', (string) ($booking->payment_gateway ?? 'offline'))),
1141 + 'payment_method' => $this->gatewayLabel(
1142 + $booking->payment_gateway ?? null,
1143 + __('Offline', 'yatra')
1144 + ),
1119 1145 'booking_ref' => $bookingRef,
1120 1146 'travel_date' => $travelDate,
1121 1147 'currency_symbol' => $currencySymbol,
1122 1148 'amount' => yatra_format_price((float) $due, $currency, false),
@@ -1252,9 +1278,12 @@
1252 1278 'trip_duration' => yatra_format_duration(
1253 1279 (int) ($payment->trip_duration_days ?? ($trip->duration_days ?? 0)),
1254 1280 isset($payment->trip_duration_nights)
1255 1281 ? (int) $payment->trip_duration_nights
1256 - : (isset($trip->duration_nights) ? (int) $trip->duration_nights : null)
1282 + : (isset($trip->duration_nights) ? (int) $trip->duration_nights : null),
1283 + // Hour-based day tours: hours come from the loaded trip (the payment
1284 + // join carries only days/nights); a soft-deleted trip falls back to days.
1285 + (int) ($trip->duration_hours ?? 0)
1257 1286 ),
1258 1287 'trip_difficulty' => $trip ? ($trip->difficulty_name ?? '') : '',
1259 1288 'departure_location' => $trip ? ($trip->departure_location ?? '') : '',
1260 1289 'destination' => $trip ? ($trip->destination ?? $payment->destination ?? '') : ($payment->destination ?? ''),