PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.6
Yatra – Travel Booking & Tour Operator Software v3.0.2.6
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
yatra / app / Services / ItineraryCostService.php

ItineraryCostService.php in Yatra – Travel Booking & Tour Operator Software 3.0.2.6, at app/Services/ItineraryCostService.php

208 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Yatra\Services;
6
7 use Yatra\Repositories\ItineraryRepository;
8
9 /**
10 * Itinerary Cost Service
11 *
12 * Handles calculation and retrieval of itinerary costs for booking
13 * This is a free feature that calculates costs from itinerary activities
14 *
15 * @package Yatra\Services
16 * @since 3.0.0
17 */
18 class ItineraryCostService
19 {
20 private ItineraryRepository $itineraryRepository;
21 private static ?self $instance = null;
22
23 public function __construct()
24 {
25 $this->itineraryRepository = new ItineraryRepository();
26 }
27
28 /**
29 * Initialize the service (singleton pattern)
30 */
31 public static function init(): void
32 {
33 if (self::$instance === null) {
34 self::$instance = new self();
35
36 // Register the filter hooks only once
37 add_filter('yatra_booking_itinerary_costs', [self::$instance, 'getItineraryCosts'], 10, 5);
38 add_filter('yatra_booking_details', [self::$instance, 'addItineraryCostsToBookingDetails'], 10, 2);
39 add_filter('yatra_booking_get_services', [self::$instance, 'getItineraryCostsAsServices'], 10, 2);
40 }
41 }
42
43 /**
44 * Get itinerary costs for a trip booking
45 *
46 * @param array $costs Empty array (filter default)
47 * @param int $tripId Trip ID
48 * @param int $totalTravelers Total number of travelers
49 * @param array $travelerCounts Traveler counts by category
50 * @param string $travelDate Travel date
51 * @return array Array of itinerary costs with pricing
52 */
53 public function getItineraryCosts(array $costs, int $tripId, int $totalTravelers, array $travelerCounts, string $travelDate): array
54 {
55 try {
56 $itineraryEntries = $this->itineraryRepository->getByTripId($tripId);
57 $itineraryCosts = [];
58
59 foreach ($itineraryEntries as $entry) {
60 // Only include entries that have a cost
61 if (empty($entry->cost) || $entry->cost <= 0) {
62 continue;
63 }
64
65 // Skip day entries (item_type_id = 0) - only include actual activities
66 if (empty($entry->item_type_id) || $entry->item_type_id == 0) {
67 continue;
68 }
69
70 $costPerPerson = !empty($entry->cost_per_person);
71 $basePrice = (float) $entry->cost;
72
73 // Calculate total cost based on pricing type
74 if ($costPerPerson) {
75 $totalCost = $basePrice * $totalTravelers;
76 $pricePer = 'person';
77 } else {
78 $totalCost = $basePrice;
79 $pricePer = 'group';
80 }
81
82 $itineraryCosts[] = [
83 'id' => $entry->id,
84 'name' => $entry->title ?: $entry->item_type ?: $entry->item_name ?: 'Itinerary Activity',
85 'description' => $entry->description ?? '',
86 'price' => $basePrice,
87 'price_per' => $pricePer,
88 'total_cost' => $totalCost,
89 'cost_per_person' => $costPerPerson,
90 'item_type' => $entry->item_type,
91 'day_number' => $entry->day_number,
92 ];
93 }
94
95 // error_log('ItineraryCostService - Found ' . count($itineraryCosts) . ' itinerary costs for trip ' . $tripId);
96
97 return $itineraryCosts;
98
99 } catch (\Exception $e) {
100 error_log('ItineraryCostService - Error: ' . $e->getMessage());
101 return [];
102 }
103 }
104
105 /**
106 * Add itinerary costs to booking details for admin display
107 *
108 * @param array $bookingDetails Booking details array
109 * @param int $bookingId Booking ID
110 * @return array Updated booking details
111 */
112 public function addItineraryCostsToBookingDetails(array $bookingDetails, int $bookingId): array
113 {
114 try {
115 $tripId = (int) ($bookingDetails['trip_id'] ?? 0);
116 $travelersCount = (int) ($bookingDetails['travelers_count'] ?? 1);
117
118 if ($tripId <= 0) {
119 return $bookingDetails;
120 }
121
122 // Get itinerary costs for this booking
123 $itineraryCosts = $this->getItineraryCosts([], $tripId, $travelersCount, [], $bookingDetails['travel_date'] ?? '');
124
125 // Calculate total
126 $itineraryCostsTotal = array_sum(array_column($itineraryCosts, 'total_cost'));
127
128 // Add to booking details
129 $bookingDetails['itinerary_costs'] = $itineraryCosts;
130 $bookingDetails['itinerary_costs_total'] = $itineraryCostsTotal;
131
132 // error_log('ItineraryCostService - Added ' . count($itineraryCosts) . ' itinerary costs to booking details for booking ' . $bookingId);
133
134 } catch (\Exception $e) {
135 error_log('ItineraryCostService - Error adding to booking details: ' . $e->getMessage());
136 }
137
138 return $bookingDetails;
139 }
140
141 /**
142 * Get itinerary costs formatted as services for admin display
143 *
144 * @param array $services Existing services array
145 * @param int $bookingId Booking ID
146 * @return array Updated services array with itinerary costs
147 */
148 public function getItineraryCostsAsServices(array $services, int $bookingId): array
149 {
150 try {
151 // Get booking details directly from database to avoid potential loops
152 global $wpdb;
153 $table_name = $wpdb->prefix . 'yatra_new_bookings';
154
155 $booking = $wpdb->get_row($wpdb->prepare(
156 "SELECT trip_id, travelers_count, travel_date, itinerary_costs FROM {$table_name} WHERE id = %d",
157 $bookingId
158 ));
159
160 if (!$booking) {
161 return $services;
162 }
163
164 $tripId = (int) $booking->trip_id;
165 $travelersCount = (int) $booking->travelers_count;
166
167 if ($tripId <= 0) {
168 return $services;
169 }
170
171 // Try to get itinerary costs from stored data first
172 $itineraryCosts = [];
173 if (!empty($booking->itinerary_costs)) {
174 $itineraryCosts = json_decode($booking->itinerary_costs, true) ?: [];
175 }
176
177 // If no stored costs, calculate them
178 if (empty($itineraryCosts)) {
179 $itineraryCosts = $this->getItineraryCosts([], $tripId, $travelersCount, [], $booking->travel_date ?? '');
180 }
181
182 // Format as services for admin display
183 foreach ($itineraryCosts as $cost) {
184 $services[] = [
185 'id' => $cost['id'],
186 'name' => $cost['name'],
187 'type' => 'itinerary_cost',
188 'price' => $cost['price'],
189 'price_per' => $cost['price_per'],
190 'total_cost' => $cost['total_cost'],
191 'quantity' => $cost['price_per'] === 'person' ? $travelersCount : 1,
192 'calculated_price' => $cost['total_cost'],
193 'description' => $cost['description'] ?? '',
194 'day_number' => $cost['day_number'] ?? null,
195 'item_type' => $cost['item_type'] ?? '',
196 ];
197 }
198
199 // error_log('ItineraryCostService - Added ' . count($itineraryCosts) . ' itinerary costs as services for booking ' . $bookingId);
200
201 } catch (\Exception $e) {
202 error_log('ItineraryCostService - Error getting services: ' . $e->getMessage());
203 }
204
205 return $services;
206 }
207 }
208