PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.7
Yatra – Travel Booking & Tour Operator Software v3.0.7
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 / Models / Departure.php

Departure.php in Yatra – Travel Booking & Tour Operator Software 3.0.7, at app/Models/Departure.php

144 lines 5.6 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\Models;
6
7 /**
8 * Departure Model
9 * Represents a single trip departure date/time with capacity and booking tracking
10 *
11 * Status rules:
12 * - past: if date < today
13 * - full: if booked_count >= max_capacity
14 * - upcoming: otherwise
15 * - cancelled: explicitly cancelled
16 */
17 class Departure
18 {
19 public int $id = 0;
20 public int $trip_id = 0;
21 public string $date = ''; // YYYY-MM-DD format (kept for backward compatibility)
22 public string $start_date = ''; // YYYY-MM-DD format - When trip starts
23 public string $end_date = ''; // YYYY-MM-DD format - When trip ends
24 public ?string $time = null; // HH:MM:SS format (optional)
25 public int $max_capacity = 0;
26 public int $booked_count = 0;
27 public string $status = 'upcoming'; // upcoming | full | past | cancelled
28 public string $source = 'booking_created'; // booking_created | manual (for admin edits)
29 public ?float $price_override = null; // Optional price override per person
30 public array $price_by_traveler_type = []; // Optional pricing per traveler category
31 public float $total_revenue = 0.00; // Total revenue from all bookings (static snapshot)
32 public ?string $notes = null;
33 public string $created_at = '';
34 public string $updated_at = '';
35
36 /**
37 * Create from array (database row)
38 */
39 public static function fromArray(array $data): self
40 {
41 $departure = new self();
42
43 $departure->id = (int) ($data['id'] ?? 0);
44 $departure->trip_id = (int) ($data['trip_id'] ?? 0);
45 // Handle date fields - support both old 'date' and new 'start_date'/'end_date'
46 $departure->date = sanitize_text_field($data['date'] ?? $data['start_date'] ?? '');
47 $departure->start_date = sanitize_text_field($data['start_date'] ?? $data['date'] ?? '');
48 $departure->end_date = sanitize_text_field($data['end_date'] ?? '');
49 $departure->time = !empty($data['time']) ? sanitize_text_field($data['time']) : null;
50 $departure->max_capacity = (int) ($data['max_capacity'] ?? 0);
51 $departure->booked_count = (int) ($data['booked_count'] ?? 0);
52 $departure->status = sanitize_text_field($data['status'] ?? 'upcoming');
53 $departure->source = sanitize_text_field($data['source'] ?? 'booking_created');
54 $departure->price_override = !empty($data['price_override']) ? (float) $data['price_override'] : null;
55 $departure->total_revenue = !empty($data['total_revenue']) ? (float) $data['total_revenue'] : 0.00;
56 $departure->notes = !empty($data['notes']) ? sanitize_textarea_field($data['notes']) : null;
57 $departure->created_at = $data['created_at'] ?? '';
58 $departure->updated_at = $data['updated_at'] ?? '';
59
60 // Handle price_by_traveler_type as JSON
61 if (isset($data['price_by_traveler_type'])) {
62 if (is_string($data['price_by_traveler_type'])) {
63 $departure->price_by_traveler_type = json_decode($data['price_by_traveler_type'], true) ?: [];
64 } elseif (is_array($data['price_by_traveler_type'])) {
65 $departure->price_by_traveler_type = $data['price_by_traveler_type'];
66 } else {
67 $departure->price_by_traveler_type = [];
68 }
69 }
70
71 return $departure;
72 }
73
74 /**
75 * Convert to array
76 */
77 public function toArray(): array
78 {
79 return [
80 'id' => $this->id,
81 'trip_id' => $this->trip_id,
82 'date' => $this->date ?: $this->start_date, // Backward compatibility
83 'start_date' => $this->start_date,
84 'end_date' => $this->end_date,
85 'time' => $this->time,
86 'max_capacity' => $this->max_capacity,
87 'booked_count' => $this->booked_count,
88 'available_capacity' => max(0, $this->max_capacity - $this->booked_count),
89 'status' => $this->status,
90 'source' => $this->source,
91 'price_override' => $this->price_override,
92 'price_by_traveler_type' => $this->price_by_traveler_type,
93 'total_revenue' => $this->total_revenue,
94 'notes' => $this->notes,
95 'created_at' => $this->created_at,
96 'updated_at' => $this->updated_at,
97 ];
98 }
99
100 /**
101 * Calculate status based on date and capacity
102 *
103 * @return string Status: past | full | upcoming | cancelled
104 */
105 public function calculateStatus(): string
106 {
107 // Empty auto-cancelled departures stay cancelled; reopen when bookings exist again
108 if ($this->status === 'cancelled' && $this->booked_count <= 0) {
109 return 'cancelled';
110 }
111
112 // Check if end_date is in the past (use end_date to determine if trip is complete)
113 $today = date('Y-m-d');
114 $checkDate = !empty($this->end_date) ? $this->end_date : $this->start_date;
115 if (empty($checkDate)) {
116 $checkDate = $this->date; // Fallback to old date field
117 }
118
119 if ($checkDate < $today) {
120 return 'past';
121 }
122
123 // Check if full
124 if ($this->booked_count >= $this->max_capacity && $this->max_capacity > 0) {
125 return 'full';
126 }
127
128 // Otherwise upcoming
129 return 'upcoming';
130 }
131
132 /**
133 * Check if departure is available for booking
134 */
135 public function isAvailable(): bool
136 {
137 $checkDate = !empty($this->start_date) ? $this->start_date : $this->date;
138 return $this->status === 'upcoming' &&
139 $this->booked_count < $this->max_capacity &&
140 $checkDate >= date('Y-m-d');
141 }
142 }
143
144