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 / Migrations / TourDateMigration.php

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

232 lines 10.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\Migration;
4
5 use Yatra\Migration\MigrationProgress;
6 use Yatra\Utils\Logger;
7 use Yatra\Database\Tables\TripAvailabilityDatesTable;
8
9 class TourDateMigration extends BaseMigration
10 {
11 public function __construct(MigrationProgress $service)
12 {
13 parent::__construct($service);
14 }
15
16 public function run(): array
17 {
18 global $wpdb;
19
20 $migrated = 0;
21 $skipped = 0;
22 $failed = 0;
23
24 $oldTable = $wpdb->prefix . 'yatra_tour_dates';
25
26 if ($wpdb->get_var("SHOW TABLES LIKE '{$oldTable}'") !== $oldTable) {
27 Logger::info("No old yatra_tour_dates table found", ['source' => 'migration']);
28 return [
29 'migrated' => 0,
30 'skipped' => 0,
31 'failed' => 0,
32 ];
33 }
34
35 $oldTourDates = $wpdb->get_results("SELECT * FROM {$oldTable}");
36 $total = count($oldTourDates);
37
38 Logger::info("Found {$total} tour dates to migrate", [
39 'source' => 'migration',
40 'count' => $total
41 ]);
42
43 foreach ($oldTourDates as $oldDate) {
44 try {
45 // Check if already migrated (only for regular migration)
46 $existsInAvailability = null;
47
48 $newTripId = $this->getMigratedTripId($oldDate->tour_id);
49
50 if (!$this->isForceMigration()) {
51 // Duplicate check: use the resolved newTripId directly so we
52 // do not need a subquery that carried the wrong outer tour_id.
53 if ($newTripId) {
54 $existsInAvailability = $wpdb->get_var($wpdb->prepare(
55 "SELECT id FROM " . TripAvailabilityDatesTable::getTableName() . "
56 WHERE trip_id = %d AND departure_date = %s",
57 $newTripId,
58 $oldDate->start_date
59 ));
60
61 if ($existsInAvailability) {
62 $skipped++;
63 $this->updateProgress('tour_dates', 'running', $migrated, $skipped, $failed, $total, null, null);
64 continue;
65 }
66 }
67 }
68
69 if (!$newTripId) {
70 $failed++;
71 Logger::debug("Skipping tour date - trip not migrated yet", [
72 'source' => 'migration',
73 'old_tour_id' => $oldDate->tour_id,
74 'tour_date_id' => $oldDate->id
75 ]);
76 $this->updateProgress('tour_dates', 'running', $migrated, $skipped, $failed, $total, null, null);
77 continue;
78 }
79
80 // Parse pricing if available
81 $pricing = !empty($oldDate->pricing) ? maybe_unserialize($oldDate->pricing) : null;
82 $originalPrice = null;
83 $discountedPrice = null;
84 $pricingType = 'regular';
85 $priceTypes = null;
86
87 if (is_array($pricing)) {
88 // Check various formats for traveler-based pricing
89 $hasTravelerPricing = false;
90
91 // Format 1: pricing_per = 'person' with price_per_person array
92 if (isset($pricing['pricing_per']) && $pricing['pricing_per'] === 'person' && isset($pricing['price_per_person'])) {
93 $pricingType = 'regular';
94 $priceTypesArray = [];
95 $pricePerPerson = is_array($pricing['price_per_person']) ? $pricing['price_per_person'] : [];
96
97 foreach ($pricePerPerson as $categoryId => $categoryPricing) {
98 if (is_array($categoryPricing)) {
99 $origPrice = floatval($categoryPricing['regular_price'] ?? $categoryPricing['price'] ?? 0);
100 $discPrice = floatval($categoryPricing['sale_price'] ?? $categoryPricing['discounted_price'] ?? 0);
101
102 // Only add if has valid price
103 if ($origPrice > 0) {
104 $priceTypesArray[] = [
105 'category_id' => $categoryId,
106 'original_price' => $origPrice,
107 'discounted_price' => ($discPrice > 0 && $discPrice < $origPrice) ? $discPrice : null,
108 ];
109 }
110 }
111 }
112
113 if (!empty($priceTypesArray)) {
114 $priceTypes = json_encode($priceTypesArray);
115 $originalPrice = $priceTypesArray[0]['original_price'] ?? null;
116 $discountedPrice = $priceTypesArray[0]['discounted_price'] ?? null;
117 $hasTravelerPricing = true;
118 }
119 }
120
121 // Format 2: Direct traveler_categories array
122 if (!$hasTravelerPricing && isset($pricing['traveler_categories']) && is_array($pricing['traveler_categories'])) {
123 $pricingType = 'regular';
124 $priceTypesArray = [];
125
126 foreach ($pricing['traveler_categories'] as $category) {
127 if (is_array($category)) {
128 $origPrice = floatval($category['regular_price'] ?? $category['price'] ?? 0);
129 $discPrice = floatval($category['sale_price'] ?? $category['discounted_price'] ?? 0);
130
131 if ($origPrice > 0) {
132 $priceTypesArray[] = [
133 'category_id' => $category['category_id'] ?? $category['id'] ?? 0,
134 'original_price' => $origPrice,
135 'discounted_price' => ($discPrice > 0 && $discPrice < $origPrice) ? $discPrice : null,
136 ];
137 }
138 }
139 }
140
141 if (!empty($priceTypesArray)) {
142 $priceTypes = json_encode($priceTypesArray);
143 $originalPrice = $priceTypesArray[0]['original_price'] ?? null;
144 $discountedPrice = $priceTypesArray[0]['discounted_price'] ?? null;
145 $hasTravelerPricing = true;
146 }
147 }
148
149 // Format 3: Regular pricing (single price for all)
150 if (!$hasTravelerPricing) {
151 $pricingType = 'regular';
152 $originalPrice = floatval($pricing['regular_price'] ?? $pricing['price'] ?? 0);
153 $discountedPrice = floatval($pricing['sale_price'] ?? $pricing['discounted_price'] ?? 0);
154
155 // If discounted price is 0 or >= original, set to null
156 if ($discountedPrice <= 0 || ($originalPrice > 0 && $discountedPrice >= $originalPrice)) {
157 $discountedPrice = null;
158 }
159 }
160 }
161
162 // Migrate to yatra_trip_availability_dates.
163 // Reaching here means: no duplicate found (or force migration).
164 $maxTravelers = intval($oldDate->max_travellers ?? 0);
165 if ($maxTravelers <= 0) {
166 $maxTravelers = 10; // Default
167 }
168
169 // Determine status based on active flag
170 $availabilityStatus = $oldDate->active ? 'available' : 'cancelled';
171
172 $availabilityData = [
173 'trip_id' => $newTripId,
174 'departure_date' => $oldDate->start_date,
175 'return_date' => $oldDate->end_date,
176 'seats_total' => $maxTravelers,
177 'seats_available' => $maxTravelers,
178 'seats_reserved' => 0,
179 'seats_waitlist' => 0,
180 'pricing_type' => $pricingType,
181 'original_price' => $originalPrice,
182 'discounted_price' => $discountedPrice,
183 'price_types' => $priceTypes,
184 'status' => $availabilityStatus,
185 'special_notes' => $oldDate->note_to_customer ?? null,
186 'created_at' => $oldDate->created_at ?? current_time('mysql'),
187 'updated_at' => $oldDate->updated_at ?? current_time('mysql'),
188 ];
189
190 $wpdb->insert(TripAvailabilityDatesTable::getTableName(), $availabilityData);
191 $insertedId = $wpdb->insert_id;
192
193 if (!$insertedId) {
194 $failed++;
195 Logger::error("Failed to insert availability date", [
196 'source' => 'migration',
197 'tour_date_id' => $oldDate->id,
198 'error' => $wpdb->last_error,
199 ]);
200 $this->updateProgress('tour_dates', 'running', $migrated, $skipped, $failed, $total, null, null);
201 continue;
202 }
203
204 $migrated++;
205 Logger::info("Migrated tour date to availability", [
206 'source' => 'migration',
207 'old_tour_date_id' => $oldDate->id,
208 'new_trip_id' => $newTripId,
209 'departure_date' => $oldDate->start_date,
210 'return_date' => $oldDate->end_date
211 ]);
212
213 $this->updateProgress('tour_dates', 'running', $migrated, $skipped, $failed, $total, null, null);
214 } catch (\Exception $e) {
215 $failed++;
216 Logger::error("Tour date migration exception", [
217 'source' => 'migration',
218 'tour_date_id' => $oldDate->id,
219 'error' => $e->getMessage()
220 ]);
221 $this->updateProgress('tour_dates', 'running', $migrated, $skipped, $failed, $total, null, null);
222 }
223 }
224
225 return [
226 'migrated' => $migrated,
227 'skipped' => $skipped,
228 'failed' => $failed,
229 ];
230 }
231 }
232