PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.3
Yatra – Travel Booking & Tour Operator Software v3.0.3
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 2.0.10 All 83 releases
yatra / app / Repositories / YatraAvailabilityRepository.php

YatraAvailabilityRepository.php in Yatra – Travel Booking & Tour Operator Software 3.0.3, at app/Repositories/YatraAvailabilityRepository.php

437 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yatra\Repositories;
4
5 use Yatra\Database\Tables\YatraAvailabilityTable;
6
7 /**
8 * Yatra Availability Repository
9 *
10 * Handles database operations for traditional Yatra trip availability dates.
11 * Provides methods for managing departure dates, pricing, capacity, and bookings.
12 *
13 * @package Yatra\Repositories
14 * @since 2.0.0
15 */
16 class YatraAvailabilityRepository extends BaseRepository
17 {
18 /**
19 * Table name
20 */
21 protected string $table;
22
23 /**
24 * Constructor
25 */
26 public function __construct()
27 {
28 global $wpdb;
29 $this->table = YatraAvailabilityTable::getTableName();
30 parent::__construct();
31 }
32
33 /**
34 * Find availability by trip ID and departure date
35 *
36 * @param int $tripId Trip ID
37 * @param string $departureDate Departure date (YYYY-MM-DD)
38 * @return object|null Availability object or null
39 */
40 public function findByTripIdAndDate(int $tripId, string $departureDate): ?object
41 {
42 $table = esc_sql($this->table);
43 $tripId = (int) $tripId;
44 $departureDate = esc_sql($departureDate);
45
46 $query = $this->wpdb->prepare(
47 "SELECT * FROM `{$table}`
48 WHERE trip_id = %d AND departure_date = %s
49 LIMIT 1",
50 $tripId,
51 $departureDate
52 );
53
54 return $this->wpdb->get_row($query) ?: null;
55 }
56
57 /**
58 * Get availability dates for a trip within a date range
59 *
60 * @param int $tripId Trip ID
61 * @param string $startDate Start date (YYYY-MM-DD)
62 * @param string $endDate End date (YYYY-MM-DD)
63 * @param array $args Additional arguments
64 * @return array Array of availability objects
65 */
66 public function getDatesForTrip(int $tripId, string $startDate, string $endDate, array $args = []): array
67 {
68 $table = esc_sql($this->table);
69 $tripId = (int) $tripId;
70 $startDate = esc_sql($startDate);
71 $endDate = esc_sql($endDate);
72
73 $where = ["trip_id = {$tripId}", "departure_date BETWEEN '{$startDate}' AND '{$endDate}'"];
74
75 if (!empty($args['status'])) {
76 $where[] = "status = '" . esc_sql($args['status']) . "'";
77 }
78
79 if (!empty($args['available_only'])) {
80 $where[] = "seats_available > 0";
81 $where[] = "status = 'available'";
82 }
83
84 if (!empty($args['not_blocked'])) {
85 $where[] = "is_blocked = 0";
86 }
87
88 $whereClause = implode(' AND ', $where);
89
90 $order = !empty($args['order']) ? esc_sql($args['order']) : 'departure_date ASC';
91 $limit = !empty($args['limit']) ? (int) $args['limit'] : '';
92
93 $sql = "SELECT * FROM `{$table}`
94 WHERE {$whereClause}
95 ORDER BY {$order}";
96
97 if ($limit) {
98 $sql .= " LIMIT {$limit}";
99 }
100
101 return $this->wpdb->get_results($sql) ?: [];
102 }
103
104 /**
105 * Get available dates for a trip (with seats available)
106 *
107 * @param int $tripId Trip ID
108 * @param string $startDate Start date (YYYY-MM-DD)
109 * @param string $endDate End date (YYYY-MM-DD)
110 * @param int $minSeats Minimum seats required (default: 1)
111 * @return array Array of available dates
112 */
113 public function getAvailableDates(int $tripId, string $startDate, string $endDate, int $minSeats = 1): array
114 {
115 $table = esc_sql($this->table);
116 $tripId = (int) $tripId;
117 $startDate = esc_sql($startDate);
118 $endDate = esc_sql($endDate);
119 $minSeats = (int) $minSeats;
120
121 $sql = "SELECT * FROM `{$table}`
122 WHERE trip_id = {$tripId}
123 AND departure_date BETWEEN '{$startDate}' AND '{$endDate}'
124 AND seats_available >= {$minSeats}
125 AND status = 'available'
126 AND is_blocked = 0
127 AND (cutoff_date IS NULL OR cutoff_date >= CURDATE())
128 ORDER BY departure_date ASC";
129
130 return $this->wpdb->get_results($sql) ?: [];
131 }
132
133 /**
134 * Check if a specific date is available for booking
135 *
136 * @param int $tripId Trip ID
137 * @param string $departureDate Departure date (YYYY-MM-DD)
138 * @param int $requiredSeats Seats required (default: 1)
139 * @return bool True if available, false otherwise
140 */
141 public function isDateAvailable(int $tripId, string $departureDate, int $requiredSeats = 1): bool
142 {
143 $table = esc_sql($this->table);
144 $tripId = (int) $tripId;
145 $departureDate = esc_sql($departureDate);
146 $requiredSeats = (int) $requiredSeats;
147
148 $sql = "SELECT COUNT(*) as count
149 FROM `{$table}`
150 WHERE trip_id = {$tripId}
151 AND departure_date = '{$departureDate}'
152 AND seats_available >= {$requiredSeats}
153 AND status = 'available'
154 AND is_blocked = 0
155 AND (cutoff_date IS NULL OR cutoff_date >= CURDATE())";
156
157 $result = $this->wpdb->get_var($sql);
158 return (int) $result > 0;
159 }
160
161 /**
162 * Update seat counts for a departure date
163 *
164 * @param int $tripId Trip ID
165 * @param string $departureDate Departure date (YYYY-MM-DD)
166 * @param int $totalSeats Total seats
167 * @param int $reservedSeats Reserved seats
168 * @return bool Success status
169 */
170 public function updateSeatCounts(int $tripId, string $departureDate, int $totalSeats, int $reservedSeats): bool
171 {
172 $table = esc_sql($this->table);
173 $tripId = (int) $tripId;
174 $departureDate = esc_sql($departureDate);
175 $totalSeats = (int) $totalSeats;
176 $reservedSeats = (int) $reservedSeats;
177 $availableSeats = max(0, $totalSeats - $reservedSeats);
178
179 $sql = "UPDATE `{$table}`
180 SET seats_total = {$totalSeats},
181 seats_reserved = {$reservedSeats},
182 seats_available = {$availableSeats},
183 updated_at = CURRENT_TIMESTAMP
184 WHERE trip_id = {$tripId} AND departure_date = '{$departureDate}'";
185
186 return $this->wpdb->query($sql) !== false;
187 }
188
189 /**
190 * Reserve seats for a departure date
191 *
192 * @param int $tripId Trip ID
193 * @param string $departureDate Departure date (YYYY-MM-DD)
194 * @param int $seatsToReserve Number of seats to reserve
195 * @return bool Success status
196 */
197 public function reserveSeats(int $tripId, string $departureDate, int $seatsToReserve): bool
198 {
199 $table = esc_sql($this->table);
200 $tripId = (int) $tripId;
201 $departureDate = esc_sql($departureDate);
202 $seatsToReserve = (int) $seatsToReserve;
203
204 // Check if enough seats are available
205 $available = $this->getAvailableSeats($tripId, $departureDate);
206 if ($available < $seatsToReserve) {
207 return false;
208 }
209
210 $sql = "UPDATE `{$table}`
211 SET seats_reserved = seats_reserved + {$seatsToReserve},
212 seats_available = seats_available - {$seatsToReserve},
213 updated_at = CURRENT_TIMESTAMP
214 WHERE trip_id = {$tripId}
215 AND departure_date = '{$departureDate}'
216 AND seats_available >= {$seatsToReserve}";
217
218 return $this->wpdb->query($sql) !== false;
219 }
220
221 /**
222 * Release reserved seats for a departure date
223 *
224 * @param int $tripId Trip ID
225 * @param string $departureDate Departure date (YYYY-MM-DD)
226 * @param int $seatsToRelease Number of seats to release
227 * @return bool Success status
228 */
229 public function releaseSeats(int $tripId, string $departureDate, int $seatsToRelease): bool
230 {
231 $table = esc_sql($this->table);
232 $tripId = (int) $tripId;
233 $departureDate = esc_sql($departureDate);
234 $seatsToRelease = (int) $seatsToRelease;
235
236 $sql = "UPDATE `{$table}`
237 SET seats_reserved = GREATEST(0, seats_reserved - {$seatsToRelease}),
238 seats_available = LEAST(seats_total, seats_available + {$seatsToRelease}),
239 updated_at = CURRENT_TIMESTAMP
240 WHERE trip_id = {$tripId} AND departure_date = '{$departureDate}'";
241
242 return $this->wpdb->query($sql) !== false;
243 }
244
245 /**
246 * Get available seats count for a departure date
247 *
248 * @param int $tripId Trip ID
249 * @param string $departureDate Departure date (YYYY-MM-DD)
250 * @return int Number of available seats
251 */
252 public function getAvailableSeats(int $tripId, string $departureDate): int
253 {
254 $table = esc_sql($this->table);
255 $tripId = (int) $tripId;
256 $departureDate = esc_sql($departureDate);
257
258 $sql = "SELECT seats_available
259 FROM `{$table}`
260 WHERE trip_id = {$tripId} AND departure_date = '{$departureDate}'
261 AND status = 'available' AND is_blocked = 0
262 LIMIT 1";
263
264 $result = $this->wpdb->get_var($sql);
265 return (int) $result ?: 0;
266 }
267
268 /**
269 * Block/unblock a departure date
270 *
271 * @param int $tripId Trip ID
272 * @param string $departureDate Departure date (YYYY-MM-DD)
273 * @param bool $blocked Whether to block
274 * @param string|null $reason Block reason
275 * @return bool Success status
276 */
277 public function blockDate(int $tripId, string $departureDate, bool $blocked = true, ?string $reason = null): bool
278 {
279 $table = esc_sql($this->table);
280 $tripId = (int) $tripId;
281 $departureDate = esc_sql($departureDate);
282 $blockedInt = $blocked ? 1 : 0;
283 $reason = $reason ? "'" . esc_sql($reason) . "'" : 'NULL';
284
285 $sql = "UPDATE `{$table}`
286 SET is_blocked = {$blockedInt},
287 block_reason = {$reason},
288 updated_at = CURRENT_TIMESTAMP
289 WHERE trip_id = {$tripId} AND departure_date = '{$departureDate}'";
290
291 return $this->wpdb->query($sql) !== false;
292 }
293
294 /**
295 * Update status for a departure date
296 *
297 * @param int $tripId Trip ID
298 * @param string $departureDate Departure date (YYYY-MM-DD)
299 * @param string $status New status
300 * @return bool Success status
301 */
302 public function updateStatus(int $tripId, string $departureDate, string $status): bool
303 {
304 $table = esc_sql($this->table);
305 $tripId = (int) $tripId;
306 $departureDate = esc_sql($departureDate);
307 $status = esc_sql($status);
308
309 $sql = "UPDATE `{$table}`
310 SET status = '{$status}',
311 updated_at = CURRENT_TIMESTAMP
312 WHERE trip_id = {$tripId} AND departure_date = '{$departureDate}'";
313
314 return $this->wpdb->query($sql) !== false;
315 }
316
317 /**
318 * Get availability statistics for a trip
319 *
320 * @param int $tripId Trip ID
321 * @param string $startDate Start date (YYYY-MM-DD)
322 * @param string $endDate End date (YYYY-MM-DD)
323 * @return array Statistics array
324 */
325 public function getTripStatistics(int $tripId, string $startDate, string $endDate): array
326 {
327 $table = esc_sql($this->table);
328 $tripId = (int) $tripId;
329 $startDate = esc_sql($startDate);
330 $endDate = esc_sql($endDate);
331
332 $sql = "SELECT
333 COUNT(*) as total_dates,
334 SUM(CASE WHEN status = 'available' AND is_blocked = 0 THEN 1 ELSE 0 END) as available_dates,
335 SUM(CASE WHEN seats_available > 0 THEN 1 ELSE 0 END) as dates_with_seats,
336 SUM(seats_total) as total_capacity,
337 SUM(seats_available) as total_available,
338 SUM(seats_reserved) as total_reserved,
339 AVG(seats_available) as avg_available_seats,
340 MIN(departure_date) as first_date,
341 MAX(departure_date) as last_date
342 FROM `{$table}`
343 WHERE trip_id = {$tripId}
344 AND departure_date BETWEEN '{$startDate}' AND '{$endDate}'";
345
346 $result = $this->wpdb->get_row($sql);
347 return $result ? (array) $result : [];
348 }
349
350 /**
351 * Delete availability dates for a trip within a date range
352 *
353 * @param int $tripId Trip ID
354 * @param string $startDate Start date (YYYY-MM-DD)
355 * @param string $endDate End date (YYYY-MM-DD)
356 * @return int Number of deleted records
357 */
358 public function deleteDateRange(int $tripId, string $startDate, string $endDate): int
359 {
360 $table = esc_sql($this->table);
361 $tripId = (int) $tripId;
362 $startDate = esc_sql($startDate);
363 $endDate = esc_sql($endDate);
364
365 $sql = "DELETE FROM `{$table}`
366 WHERE trip_id = {$tripId}
367 AND departure_date BETWEEN '{$startDate}' AND '{$endDate}'";
368
369 return $this->wpdb->query($sql) ?: 0;
370 }
371
372 /**
373 * Get upcoming departures that need alerts
374 *
375 * @param int $daysAhead Number of days ahead to check
376 * @param int $alertThreshold Alert threshold for seats
377 * @return array Array of departures needing alerts
378 */
379 public function getDeparturesNeedingAlerts(int $daysAhead = 7, int $alertThreshold = 3): array
380 {
381 $table = esc_sql($this->table);
382 $daysAhead = (int) $daysAhead;
383 $alertThreshold = (int) $alertThreshold;
384
385 $sql = "SELECT * FROM `{$table}`
386 WHERE departure_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL {$daysAhead} DAY)
387 AND seats_available > 0
388 AND seats_available <= {$alertThreshold}
389 AND status = 'available'
390 AND is_blocked = 0
391 ORDER BY departure_date ASC";
392
393 return $this->wpdb->get_results($sql) ?: [];
394 }
395
396 /**
397 * Get status counts for availability dates
398 *
399 * @param array $args Arguments including trip_id filtering
400 * @return array Status counts
401 */
402 public function getStatusCounts(array $args = []): array
403 {
404 $table = esc_sql($this->table);
405 $where = $this->buildWhereClause($args);
406
407 $sql = "SELECT status, COUNT(*) as count
408 FROM `{$table}`
409 {$where}
410 GROUP BY status";
411
412 $results = $this->wpdb->get_results($sql) ?: [];
413
414 $counts = [
415 'available' => 0,
416 'unavailable' => 0,
417 'limited' => 0,
418 'sold_out' => 0,
419 'cancelled' => 0,
420 'blocked' => 0,
421 'total' => 0
422 ];
423
424 foreach ($results as $row) {
425 $status = $row->status;
426 $count = (int) $row->count;
427
428 if (isset($counts[$status])) {
429 $counts[$status] = $count;
430 }
431 $counts['total'] += $count;
432 }
433
434 return $counts;
435 }
436 }
437