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/Services/DepartureService.php +63 -4 3.0.13 → 3.0.16 View file →
@@ -156,16 +156,53 @@
156 156 throw new \InvalidArgumentException('A departure already exists for this trip and date');
157 157 }
158 158 }
159 159
160 + // Detect a tour (trip) reassignment: the operator is moving this
161 + // departure from one trip to another. The DB layer already persists
162 + // trip_id, but the move must be validated and kept consistent:
163 + // 1. the target trip must exist,
164 + // 2. it must not collide with an existing departure on the target
165 + // trip for the same date/time, and
166 + // 3. the departure's bookings must move to the new trip too, so a
167 + // booking never ends up pointing at a departure that belongs to a
168 + // different trip (the invariant the booking edit path also keeps).
169 + $newTripId = isset($data['trip_id']) ? (int) $data['trip_id'] : 0;
170 + $tripReassigned = $newTripId > 0 && $newTripId !== (int) $departure->trip_id;
171 +
172 + if ($tripReassigned) {
173 + $targetTrip = $this->tripRepository->find($newTripId);
174 + if (!$targetTrip) {
175 + throw new \InvalidArgumentException('Target tour not found');
176 + }
177 +
178 + $checkDate = $data['start_date'] ?? $data['date'] ?? ($departure->start_date ?: $departure->date);
179 + $checkTime = $data['time'] ?? $departure->time;
180 + $existing = $this->repository->findByTripIdAndStartDate($newTripId, (string) $checkDate, $checkTime);
181 + if ($existing && (int) $existing->id !== $id) {
182 + throw new \InvalidArgumentException(
183 + 'A departure already exists for the selected tour on this date'
184 + );
185 + }
186 + }
187 +
160 188 // Mark as manually edited by admin
161 189 if (!isset($data['source'])) {
162 190 $data['source'] = 'manual'; // Admin edits mark as manual
163 191 }
164 -
192 +
165 193 // Update departure
166 194 $result = $this->repository->update($id, $data);
167 -
195 +
196 + // Move the departure's bookings onto the new trip so booking.trip_id and
197 + // departure.trip_id stay in sync after a manual reassignment.
198 + if ($result && $tripReassigned) {
199 + $bookingIds = $this->bookingDepartureRepository->getBookingIdsForDeparture($id);
200 + foreach ($bookingIds as $bookingId) {
201 + $this->bookingRepository->update((int) $bookingId, ['trip_id' => $newTripId]);
202 + }
203 + }
204 +
168 205 // Trigger hook to sync capacity from availability
169 206 if ($result) {
170 207 do_action('yatra_departure_saved', $id);
171 208 }
@@ -305,8 +342,27 @@
305 342 return $this->repository->findByTripId($tripId, $filters);
306 343 }
307 344
308 345 /**
346 + * Count departures across all trips for the same filters as
347 + * getAllDepartures() (pagination keys ignored) — the true total behind a
348 + * paginated list.
349 + */
350 + public function countAllDepartures(array $filters = []): int
351 + {
352 + return $this->repository->countAll($filters);
353 + }
354 +
355 + /**
356 + * Count departures for one trip for the same filters as getByTripId()
357 + * (pagination keys ignored).
358 + */
359 + public function countByTripId(int $tripId, array $filters = []): int
360 + {
361 + return $this->repository->countByTripId($tripId, $filters);
362 + }
363 +
364 + /**
309 365 * Get past departures by trip ID
310 366 */
311 367 public function getPastByTripId(int $tripId, array $filters = []): array
312 368 {
@@ -326,15 +382,18 @@
326 382 * Combines manual departures and dynamically generated recurring rule dates
327 383 *
328 384 * @param int $tripId Trip ID
329 385 * @param string $fromDate Start date (default: today)
330 - * @param string $toDate End date (default: +12 months)
386 + * @param string $toDate End date (default: today + the configurable booking horizon, 12 months unless changed)
331 387 * @return array Available dates with pricing and capacity info
332 388 */
333 389 public function getAvailableDates(int $tripId, ?string $fromDate = null, ?string $toDate = null): array
334 390 {
335 391 $fromDate = $fromDate ?? date('Y-m-d');
336 - $toDate = $toDate ?? date('Y-m-d', strtotime('+12 months'));
392 + // Default counted from today (not $fromDate), exactly as the previous
393 + // hard-coded '+12 months' was, so callers passing only a start date
394 + // keep the same window.
395 + $toDate = $toDate ?? yatra_get_availability_horizon_date();
337 396
338 397 // Get all manual departures
339 398 $manualDepartures = $this->repository->findByTripId($tripId, [
340 399 'date_from' => $fromDate,