PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
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 2.0.11 All 82 releases
yatra / app / Services / AvailabilitySpecificDatesService.php

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

407 lines 12.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Yatra\Services;
4
5 use Yatra\Repositories\AvailabilityRepository;
6 use Yatra\Helpers\FormatHelper;
7 use Yatra\Helpers\ValidationHelper;
8
9 /**
10 * Availability Specific Dates Service Class
11 *
12 * Handles business logic for specific date availability management.
13 * Provides high-level operations for managing trip availability on specific dates.
14 *
15 * @package Yatra\Services
16 * @since 2.0.0
17 */
18 class AvailabilitySpecificDatesService
19 {
20 /**
21 * @var AvailabilityRepository Repository instance
22 */
23 private $repository;
24
25 /**
26 * Constructor
27 */
28 public function __construct()
29 {
30 $this->repository = new AvailabilityRepository();
31 }
32
33 /**
34 * Create a new specific date availability record
35 *
36 * @param array $data Date availability data
37 * @return int|false Created record ID or false on failure
38 */
39 public function create(array $data)
40 {
41 // Validate required fields
42 $required = ['trip_id', 'date', 'status'];
43 if (!ValidationHelper::validateRequired($data, $required)) {
44 throw new \InvalidArgumentException('Missing required fields: ' . implode(', ', $required));
45 }
46
47 // Validate date format
48 if (!ValidationHelper::validateDate($data['date'])) {
49 throw new \InvalidArgumentException('Invalid date format. Use Y-m-d format.');
50 }
51
52 // Validate status
53 $validStatuses = ['available', 'unavailable', 'limited'];
54 if (!in_array($data['status'], $validStatuses)) {
55 throw new \InvalidArgumentException('Invalid status. Must be one of: ' . implode(', ', $validStatuses));
56 }
57
58 // Process data before create
59 $processedData = $this->processBeforeCreate($data);
60
61 // Create record
62 $id = $this->repository->create($processedData);
63
64 if ($id) {
65 // Post-process after successful create
66 $this->processAfterCreate($id, $processedData);
67 }
68
69 return $id;
70 }
71
72 /**
73 * Update an existing specific date availability record
74 *
75 * @param int $id Record ID
76 * @param array $data Update data
77 * @return bool Success status
78 */
79 public function update(int $id, array $data): bool
80 {
81 // Get existing record
82 $existing = $this->repository->getById($id);
83 if (!$existing) {
84 throw new \InvalidArgumentException('Specific date record not found.');
85 }
86
87 // Validate date format if provided
88 if (isset($data['date']) && !ValidationHelper::validateDate($data['date'])) {
89 throw new \InvalidArgumentException('Invalid date format. Use Y-m-d format.');
90 }
91
92 // Validate status if provided
93 if (isset($data['status'])) {
94 $validStatuses = ['available', 'unavailable', 'limited'];
95 if (!in_array($data['status'], $validStatuses)) {
96 throw new \InvalidArgumentException('Invalid status. Must be one of: ' . implode(', ', $validStatuses));
97 }
98 }
99
100 // Process data before update
101 $processedData = $this->processBeforeUpdate($data, $existing);
102
103 // Update record
104 $success = $this->repository->update($id, $processedData);
105
106 if ($success) {
107 // Post-process after successful update
108 $this->processAfterUpdate($id, $processedData, $existing);
109 }
110
111 return $success;
112 }
113
114 /**
115 * Delete a specific date availability record
116 *
117 * @param int $id Record ID
118 * @return bool Success status
119 */
120 public function delete(int $id): bool
121 {
122 $existing = $this->repository->getById($id);
123 if (!$existing) {
124 throw new \InvalidArgumentException('Specific date record not found.');
125 }
126
127 // Pre-delete processing
128 $this->processBeforeDelete($existing);
129
130 // Delete record
131 $success = $this->repository->delete($id);
132
133 if ($success) {
134 // Post-delete processing
135 $this->processAfterDelete($existing);
136 }
137
138 return $success;
139 }
140
141 /**
142 * Get specific dates for a trip within a date range
143 *
144 * @param int $tripId Trip ID
145 * @param string $startDate Start date (Y-m-d)
146 * @param string $endDate End date (Y-m-d)
147 * @return array Array of specific date records
148 */
149 public function getDatesForTrip(int $tripId, string $startDate, string $endDate): array
150 {
151 return $this->repository->getDatesForTrip($tripId, $startDate, $endDate);
152 }
153
154 /**
155 * Get available dates for a trip within a date range
156 *
157 * @param int $tripId Trip ID
158 * @param string $startDate Start date (Y-m-d)
159 * @param string $endDate End date (Y-m-d)
160 * @return array Array of available dates
161 */
162 public function getAvailableDates(int $tripId, string $startDate, string $endDate): array
163 {
164 return $this->repository->getAvailableDates($tripId, $startDate, $endDate);
165 }
166
167 /**
168 * Check if a date is available for booking
169 *
170 * @param int $tripId Trip ID
171 * @param string $date Date (Y-m-d)
172 * @return bool True if available, false otherwise
173 */
174 public function isDateAvailable(int $tripId, string $date): bool
175 {
176 return $this->repository->isDateAvailable($tripId, $date);
177 }
178
179 /**
180 * Get available slots for a specific date
181 *
182 * @param int $tripId Trip ID
183 * @param string $date Date (Y-m-d)
184 * @return int Available slots (0 if unlimited or unavailable)
185 */
186 public function getAvailableSlots(int $tripId, string $date): int
187 {
188 return $this->repository->getAvailableSlots($tripId, $date);
189 }
190
191 /**
192 * Update booking count for a specific date
193 *
194 * @param int $tripId Trip ID
195 * @param string $date Date (Y-m-d)
196 * @param int $bookingCount New booking count
197 * @return bool Success status
198 */
199 public function updateBookingCount(int $tripId, string $date, int $bookingCount): bool
200 {
201 $record = $this->repository->getDateForTrip($tripId, $date);
202 if (!$record) {
203 throw new \InvalidArgumentException('Specific date record not found for the given trip and date.');
204 }
205
206 return $this->repository->updateBookingCount($record->id, $bookingCount);
207 }
208
209 /**
210 * Increment booking count for a specific date
211 *
212 * @param int $tripId Trip ID
213 * @param string $date Date (Y-m-d)
214 * @param int $increment Number to increment by (default: 1)
215 * @return bool Success status
216 */
217 public function incrementBookingCount(int $tripId, string $date, int $increment = 1): bool
218 {
219 $record = $this->repository->getDateForTrip($tripId, $date);
220 if (!$record) {
221 throw new \InvalidArgumentException('Specific date record not found for the given trip and date.');
222 }
223
224 return $this->repository->incrementBookingCount($record->id, $increment);
225 }
226
227 /**
228 * Decrement booking count for a specific date
229 *
230 * @param int $tripId Trip ID
231 * @param string $date Date (Y-m-d)
232 * @param int $decrement Number to decrement by (default: 1)
233 * @return bool Success status
234 */
235 public function decrementBookingCount(int $tripId, string $date, int $decrement = 1): bool
236 {
237 $record = $this->repository->getDateForTrip($tripId, $date);
238 if (!$record) {
239 throw new \InvalidArgumentException('Specific date record not found for the given trip and date.');
240 }
241
242 return $this->repository->decrementBookingCount($record->id, $decrement);
243 }
244
245 /**
246 * Get dates with price overrides for a trip
247 *
248 * @param int $tripId Trip ID
249 * @param string $startDate Start date (Y-m-d)
250 * @param string $endDate End date (Y-m-d)
251 * @return array Array of dates with price overrides
252 */
253 public function getDatesWithPriceOverrides(int $tripId, string $startDate, string $endDate): array
254 {
255 return $this->repository->getDatesWithPriceOverrides($tripId, $startDate, $endDate);
256 }
257
258 /**
259 * Delete specific dates for a trip within a date range
260 *
261 * @param int $tripId Trip ID
262 * @param string $startDate Start date (Y-m-d)
263 * @param string $endDate End date (Y-m-d)
264 * @return int Number of deleted records
265 */
266 public function deleteDatesInRange(int $tripId, string $startDate, string $endDate): int
267 {
268 return $this->repository->deleteDatesInRange($tripId, $startDate, $endDate);
269 }
270
271 /**
272 * Process data before create
273 *
274 * @param array $data Input data
275 * @return array Processed data
276 */
277 private function processBeforeCreate(array $data): array
278 {
279 $processed = $data;
280
281 // Set created by user if not provided
282 if (!isset($processed['created_by'])) {
283 $processed['created_by'] = get_current_user_id();
284 }
285
286 // Sanitize text fields
287 if (isset($processed['notes'])) {
288 $processed['notes'] = sanitize_textarea_field($processed['notes']);
289 }
290
291 // Validate and sanitize numeric fields
292 if (isset($processed['max_bookings'])) {
293 $processed['max_bookings'] = max(0, (int) $processed['max_bookings']);
294 }
295
296 if (isset($processed['current_bookings'])) {
297 $processed['current_bookings'] = max(0, (int) $processed['current_bookings']);
298 }
299
300 if (isset($processed['price_override'])) {
301 $processed['price_override'] = max(0, (float) $processed['price_override']);
302 }
303
304 // Validate price type
305 if (isset($processed['price_type'])) {
306 $validTypes = ['fixed', 'percentage'];
307 if (!in_array($processed['price_type'], $validTypes)) {
308 $processed['price_type'] = 'fixed';
309 }
310 }
311
312 return $processed;
313 }
314
315 /**
316 * Process data before update
317 *
318 * @param array $data Input data
319 * @param object $existing Existing record
320 * @return array Processed data
321 */
322 private function processBeforeUpdate(array $data, object $existing): array
323 {
324 $processed = $data;
325
326 // Set updated by user if not provided
327 if (!isset($processed['updated_by'])) {
328 $processed['updated_by'] = get_current_user_id();
329 }
330
331 // Sanitize text fields
332 if (isset($processed['notes'])) {
333 $processed['notes'] = sanitize_textarea_field($processed['notes']);
334 }
335
336 // Validate and sanitize numeric fields
337 if (isset($processed['max_bookings'])) {
338 $processed['max_bookings'] = max(0, (int) $processed['max_bookings']);
339 }
340
341 if (isset($processed['current_bookings'])) {
342 $processed['current_bookings'] = max(0, (int) $processed['current_bookings']);
343 }
344
345 if (isset($processed['price_override'])) {
346 $processed['price_override'] = max(0, (float) $processed['price_override']);
347 }
348
349 // Validate price type
350 if (isset($processed['price_type'])) {
351 $validTypes = ['fixed', 'percentage'];
352 if (!in_array($processed['price_type'], $validTypes)) {
353 $processed['price_type'] = 'fixed';
354 }
355 }
356
357 return $processed;
358 }
359
360 /**
361 * Process after create
362 *
363 * @param int $id Created record ID
364 * @param array $data Processed data
365 */
366 private function processAfterCreate(int $id, array $data): void
367 {
368 // Log activity, trigger hooks, etc.
369 do_action('yatra_availability_specific_date_created', $id, $data);
370 }
371
372 /**
373 * Process after update
374 *
375 * @param int $id Updated record ID
376 * @param array $data Processed data
377 * @param object $existing Original record
378 */
379 private function processAfterUpdate(int $id, array $data, object $existing): void
380 {
381 // Log activity, trigger hooks, etc.
382 do_action('yatra_availability_specific_date_updated', $id, $data, $existing);
383 }
384
385 /**
386 * Process before delete
387 *
388 * @param object $existing Record to be deleted
389 */
390 private function processBeforeDelete(object $existing): void
391 {
392 // Check dependencies, trigger hooks, etc.
393 do_action('yatra_availability_specific_date_before_delete', $existing);
394 }
395
396 /**
397 * Process after delete
398 *
399 * @param object $deleted Deleted record
400 */
401 private function processAfterDelete(object $deleted): void
402 {
403 // Log activity, trigger hooks, etc.
404 do_action('yatra_availability_specific_date_deleted', $deleted);
405 }
406 }
407