@fleetbase/fleetops-engine 0.6.28 → 0.6.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/addon/components/customer/create-order-form.hbs +1 -1
  2. package/addon/components/customer/order-form.hbs +34 -34
  3. package/addon/components/customer/orders.hbs +2 -2
  4. package/addon/components/display-place.hbs +1 -1
  5. package/addon/components/driver/pill.hbs +16 -17
  6. package/addon/components/driver/pill.js +5 -1
  7. package/addon/components/map/leaflet-live-map.js +35 -3
  8. package/addon/components/map/order-list-overlay/order.hbs +1 -0
  9. package/addon/components/map/order-list-overlay/order.js +42 -0
  10. package/addon/components/modals/bulk-assign-driver.hbs +2 -2
  11. package/addon/components/order/details/detail.hbs +6 -6
  12. package/addon/components/order/details/notes.js +1 -1
  13. package/addon/components/order/route-editor.hbs +3 -3
  14. package/addon/components/order-tracking-lookup.hbs +1 -1
  15. package/addon/components/service-rate/details.hbs +117 -75
  16. package/addon/components/service-rate/form.hbs +7 -4
  17. package/addon/components/service-rate/form.js +6 -0
  18. package/addon/components/vehicle/pill.hbs +32 -33
  19. package/addon/components/vehicle/pill.js +5 -1
  20. package/addon/controllers/operations/orders/index.js +1 -1
  21. package/addon/controllers/operations/scheduler/index.js +17 -2
  22. package/addon/controllers/operations/service-rates/index/edit.js +1 -7
  23. package/addon/controllers/operations/service-rates/index/new.js +0 -7
  24. package/addon/controllers/operations/service-rates/index.js +10 -2
  25. package/addon/routes/operations/orders/index/details.js +7 -0
  26. package/addon/routes/operations/scheduler/index.js +3 -3
  27. package/addon/services/driver-actions.js +20 -4
  28. package/addon/services/leaflet-routing-control.js +7 -1
  29. package/addon/services/order-list-overlay.js +0 -1
  30. package/addon/services/place-actions.js +20 -4
  31. package/addon/services/service-rate-actions.js +31 -0
  32. package/addon/services/vehicle-actions.js +20 -4
  33. package/addon/templates/operations/scheduler/index.hbs +2 -2
  34. package/addon/utils/create-full-calendar-event-from-order.js +6 -0
  35. package/composer.json +1 -1
  36. package/extension.json +1 -1
  37. package/index.js +0 -11
  38. package/package.json +4 -4
  39. package/server/migrations/2025_12_16_000001_add_subject_created_at_index_to_positions.php +40 -0
  40. package/server/migrations/2025_12_16_000003_add_performance_indexes_to_fleetops_core_tables.php +442 -0
  41. package/server/src/Console/Commands/DispatchAdhocOrders.php +7 -2
  42. package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -0
  43. package/server/src/Http/Controllers/Api/v1/OrderController.php +30 -0
  44. package/server/src/Http/Controllers/Internal/v1/LiveController.php +184 -86
  45. package/server/src/Http/Controllers/Internal/v1/OrderController.php +14 -1
  46. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +5 -0
  47. package/server/src/Http/Filter/DriverFilter.php +10 -0
  48. package/server/src/Http/Filter/OrderFilter.php +8 -1
  49. package/server/src/Http/Resources/v1/Contact.php +2 -2
  50. package/server/src/Http/Resources/v1/Entity.php +1 -1
  51. package/server/src/Http/Resources/v1/Index/Customer.php +33 -0
  52. package/server/src/Http/Resources/v1/Index/Driver.php +45 -0
  53. package/server/src/Http/Resources/v1/Index/Facilitator.php +33 -0
  54. package/server/src/Http/Resources/v1/Index/Order.php +127 -0
  55. package/server/src/Http/Resources/v1/Index/Payload.php +57 -0
  56. package/server/src/Http/Resources/v1/Index/Place.php +45 -0
  57. package/server/src/Http/Resources/v1/Index/TrackingNumber.php +25 -0
  58. package/server/src/Http/Resources/v1/Index/Vehicle.php +50 -0
  59. package/server/src/Http/Resources/v1/Order.php +41 -14
  60. package/server/src/Http/Resources/v1/Place.php +1 -1
  61. package/server/src/Http/Resources/v1/Position.php +2 -1
  62. package/server/src/Http/Resources/v1/ServiceRate.php +4 -4
  63. package/server/src/Http/Resources/v1/ServiceRateFee.php +12 -12
  64. package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +14 -7
  65. package/server/src/Http/Resources/v1/TrackingNumber.php +1 -1
  66. package/server/src/Http/Resources/v1/Waypoint.php +1 -1
  67. package/server/src/Listeners/HandleOrderDispatched.php +5 -0
  68. package/server/src/Models/Contact.php +2 -0
  69. package/server/src/Models/Device.php +2 -0
  70. package/server/src/Models/DeviceEvent.php +2 -0
  71. package/server/src/Models/Driver.php +2 -0
  72. package/server/src/Models/FuelReport.php +2 -0
  73. package/server/src/Models/Issue.php +2 -0
  74. package/server/src/Models/Order.php +12 -5
  75. package/server/src/Models/Place.php +2 -0
  76. package/server/src/Models/Position.php +2 -0
  77. package/server/src/Models/ServiceArea.php +2 -0
  78. package/server/src/Models/ServiceRate.php +5 -1
  79. package/server/src/Models/ServiceRateFee.php +3 -17
  80. package/server/src/Models/ServiceRateParcelFee.php +1 -12
  81. package/server/src/Models/Vehicle.php +2 -0
  82. package/server/src/Models/Vendor.php +2 -0
  83. package/server/src/Models/Zone.php +2 -0
  84. package/server/src/Observers/DriverObserver.php +23 -0
  85. package/server/src/Observers/OrderObserver.php +31 -0
  86. package/server/src/Observers/PlaceObserver.php +31 -0
  87. package/server/src/Observers/ServiceRateObserver.php +0 -18
  88. package/server/src/Observers/VehicleObserver.php +7 -0
  89. package/server/src/Support/LiveCacheService.php +165 -0
  90. package/server/src/Support/OSRM.php +49 -22
  91. package/server/src/Support/OrderTracker.php +100 -28
  92. package/translations/en-us.yaml +3 -1
@@ -0,0 +1,442 @@
1
+ <?php
2
+
3
+ use Illuminate\Database\Migrations\Migration;
4
+ use Illuminate\Database\Schema\Blueprint;
5
+ use Illuminate\Support\Facades\Schema;
6
+
7
+ return new class extends Migration {
8
+ /**
9
+ * Run the migrations.
10
+ *
11
+ * Performance-optimized composite indexes for core FleetOps tables.
12
+ * These indexes are specifically designed to optimize the most common and heaviest query patterns:
13
+ *
14
+ * 1. orders?unassigned=1
15
+ * - Filters: company_uuid, driver_assigned_uuid IS NULL, status NOT IN (...)
16
+ * - Needs: (company_uuid, driver_assigned_uuid, status)
17
+ *
18
+ * 2. orders?active=1&with_tracker_data=1
19
+ * - Filters: company_uuid, driver_assigned_uuid IS NOT NULL, status NOT IN (...)
20
+ * - Needs: (company_uuid, driver_assigned_uuid, status)
21
+ * - Also needs efficient joins with tracking_numbers, payloads, places, waypoints
22
+ *
23
+ * 3. General order queries with sorting by created_at
24
+ * - Needs: (company_uuid, created_at)
25
+ *
26
+ * 4. Relationship lookups (payload -> waypoints, places, entities)
27
+ * - Needs: Foreign key indexes on relationship columns
28
+ */
29
+ public function up(): void
30
+ {
31
+ // ========================================
32
+ // ORDERS TABLE - Critical for performance
33
+ // ========================================
34
+ Schema::table('orders', function (Blueprint $table) {
35
+ // CRITICAL: Optimize unassigned and active filters
36
+ // This index supports both unassigned=1 and active=1 queries
37
+ if (!$this->indexExists('orders', 'orders_company_driver_status_idx')) {
38
+ $table->index(['company_uuid', 'driver_assigned_uuid', 'status'], 'orders_company_driver_status_idx');
39
+ }
40
+
41
+ // Optimize general queries with sorting
42
+ if (!$this->indexExists('orders', 'orders_company_created_idx')) {
43
+ $table->index(['company_uuid', 'created_at'], 'orders_company_created_idx');
44
+ }
45
+
46
+ // Optimize scheduled_at queries (for scheduled orders)
47
+ if (!$this->indexExists('orders', 'orders_company_scheduled_idx')) {
48
+ $table->index(['company_uuid', 'scheduled_at'], 'orders_company_scheduled_idx');
49
+ }
50
+
51
+ // Optimize dispatched queries
52
+ if (!$this->indexExists('orders', 'orders_company_dispatched_idx')) {
53
+ $table->index(['company_uuid', 'dispatched', 'dispatched_at'], 'orders_company_dispatched_idx');
54
+ }
55
+
56
+ // Optimize payload lookups (for eager loading)
57
+ if (!$this->indexExists('orders', 'orders_payload_uuid_idx')) {
58
+ $table->index('payload_uuid', 'orders_payload_uuid_idx');
59
+ }
60
+
61
+ // Optimize tracking number lookups
62
+ if (!$this->indexExists('orders', 'orders_tracking_number_uuid_idx')) {
63
+ $table->index('tracking_number_uuid', 'orders_tracking_number_uuid_idx');
64
+ }
65
+
66
+ // Optimize driver/vehicle assignment lookups
67
+ if (!$this->indexExists('orders', 'orders_vehicle_assigned_uuid_idx')) {
68
+ $table->index('vehicle_assigned_uuid', 'orders_vehicle_assigned_uuid_idx');
69
+ }
70
+ });
71
+
72
+ // ========================================
73
+ // PAYLOADS TABLE
74
+ // ========================================
75
+ Schema::table('payloads', function (Blueprint $table) {
76
+ // Optimize company queries
77
+ if (!$this->indexExists('payloads', 'payloads_company_created_idx')) {
78
+ $table->index(['company_uuid', 'created_at'], 'payloads_company_created_idx');
79
+ }
80
+
81
+ // Optimize pickup/dropoff/return lookups (for order queries)
82
+ if (!$this->indexExists('payloads', 'payloads_pickup_uuid_idx')) {
83
+ $table->index('pickup_uuid', 'payloads_pickup_uuid_idx');
84
+ }
85
+ if (!$this->indexExists('payloads', 'payloads_dropoff_uuid_idx')) {
86
+ $table->index('dropoff_uuid', 'payloads_dropoff_uuid_idx');
87
+ }
88
+ if (!$this->indexExists('payloads', 'payloads_return_uuid_idx')) {
89
+ $table->index('return_uuid', 'payloads_return_uuid_idx');
90
+ }
91
+ });
92
+
93
+ // ========================================
94
+ // WAYPOINTS TABLE
95
+ // ========================================
96
+ Schema::table('waypoints', function (Blueprint $table) {
97
+ // Optimize payload -> waypoints relationship queries
98
+ if (!$this->indexExists('waypoints', 'waypoints_payload_created_idx')) {
99
+ $table->index(['payload_uuid', 'created_at'], 'waypoints_payload_created_idx');
100
+ }
101
+
102
+ // Optimize company queries
103
+ if (!$this->indexExists('waypoints', 'waypoints_company_created_idx')) {
104
+ $table->index(['company_uuid', 'created_at'], 'waypoints_company_created_idx');
105
+ }
106
+
107
+ // Optimize place lookups
108
+ if (!$this->indexExists('waypoints', 'waypoints_place_uuid_idx')) {
109
+ $table->index('place_uuid', 'waypoints_place_uuid_idx');
110
+ }
111
+ });
112
+
113
+ // ========================================
114
+ // ENTITIES TABLE
115
+ // ========================================
116
+ Schema::table('entities', function (Blueprint $table) {
117
+ // Optimize payload -> entities relationship queries
118
+ if (!$this->indexExists('entities', 'entities_payload_created_idx')) {
119
+ $table->index(['payload_uuid', 'created_at'], 'entities_payload_created_idx');
120
+ }
121
+
122
+ // Optimize company queries
123
+ if (!$this->indexExists('entities', 'entities_company_created_idx')) {
124
+ $table->index(['company_uuid', 'created_at'], 'entities_company_created_idx');
125
+ }
126
+
127
+ // Optimize destination lookups
128
+ if (!$this->indexExists('entities', 'entities_destination_uuid_idx')) {
129
+ $table->index('destination_uuid', 'entities_destination_uuid_idx');
130
+ }
131
+ });
132
+
133
+ // ========================================
134
+ // PLACES TABLE
135
+ // ========================================
136
+ Schema::table('places', function (Blueprint $table) {
137
+ // Optimize company queries
138
+ if (!$this->indexExists('places', 'places_company_created_idx')) {
139
+ $table->index(['company_uuid', 'created_at'], 'places_company_created_idx');
140
+ }
141
+
142
+ // Optimize owner lookups (polymorphic)
143
+ if (!$this->indexExists('places', 'places_owner_idx')) {
144
+ $table->index(['owner_uuid', 'owner_type'], 'places_owner_idx');
145
+ }
146
+ });
147
+
148
+ // ========================================
149
+ // DRIVERS TABLE
150
+ // ========================================
151
+ Schema::table('drivers', function (Blueprint $table) {
152
+ // Optimize company queries with status filter
153
+ if (!$this->indexExists('drivers', 'drivers_company_status_online_idx')) {
154
+ $table->index(['company_uuid', 'status', 'online'], 'drivers_company_status_online_idx');
155
+ }
156
+
157
+ // Optimize general queries
158
+ if (!$this->indexExists('drivers', 'drivers_company_created_idx')) {
159
+ $table->index(['company_uuid', 'created_at'], 'drivers_company_created_idx');
160
+ }
161
+
162
+ // Optimize user lookups
163
+ if (!$this->indexExists('drivers', 'drivers_user_uuid_idx')) {
164
+ $table->index('user_uuid', 'drivers_user_uuid_idx');
165
+ }
166
+
167
+ // Optimize vendor lookups
168
+ if (!$this->indexExists('drivers', 'drivers_vendor_uuid_idx')) {
169
+ $table->index('vendor_uuid', 'drivers_vendor_uuid_idx');
170
+ }
171
+ });
172
+
173
+ // ========================================
174
+ // VEHICLES TABLE
175
+ // ========================================
176
+ Schema::table('vehicles', function (Blueprint $table) {
177
+ // Optimize company queries with status filter
178
+ if (!$this->indexExists('vehicles', 'vehicles_company_status_online_idx')) {
179
+ $table->index(['company_uuid', 'status', 'online'], 'vehicles_company_status_online_idx');
180
+ }
181
+
182
+ // Optimize general queries
183
+ if (!$this->indexExists('vehicles', 'vehicles_company_created_idx')) {
184
+ $table->index(['company_uuid', 'created_at'], 'vehicles_company_created_idx');
185
+ }
186
+
187
+ // Optimize vendor lookups
188
+ if (!$this->indexExists('vehicles', 'vehicles_vendor_uuid_idx')) {
189
+ $table->index('vendor_uuid', 'vehicles_vendor_uuid_idx');
190
+ }
191
+ });
192
+
193
+ // ========================================
194
+ // VENDORS TABLE
195
+ // ========================================
196
+ Schema::table('vendors', function (Blueprint $table) {
197
+ // Optimize company queries with status filter
198
+ if (!$this->indexExists('vendors', 'vendors_company_status_idx')) {
199
+ $table->index(['company_uuid', 'status'], 'vendors_company_status_idx');
200
+ }
201
+
202
+ // Already has company_uuid and created_at indexes
203
+ });
204
+
205
+ // ========================================
206
+ // CONTACTS TABLE
207
+ // ========================================
208
+ Schema::table('contacts', function (Blueprint $table) {
209
+ // Optimize company queries
210
+ if (!$this->indexExists('contacts', 'contacts_company_created_idx')) {
211
+ $table->index(['company_uuid', 'created_at'], 'contacts_company_created_idx');
212
+ }
213
+
214
+ // Optimize company queries with type filter
215
+ if (!$this->indexExists('contacts', 'contacts_company_type_idx')) {
216
+ $table->index(['company_uuid', 'type'], 'contacts_company_type_idx');
217
+ }
218
+ });
219
+
220
+ // ========================================
221
+ // ROUTES TABLE
222
+ // ========================================
223
+ Schema::table('routes', function (Blueprint $table) {
224
+ // Optimize company queries
225
+ if (!$this->indexExists('routes', 'routes_company_created_idx')) {
226
+ $table->index(['company_uuid', 'created_at'], 'routes_company_created_idx');
227
+ }
228
+
229
+ // Note: routes table doesn't have a status column in this schema
230
+ });
231
+
232
+ // ========================================
233
+ // TRACKING_NUMBERS TABLE
234
+ // ========================================
235
+ Schema::table('tracking_numbers', function (Blueprint $table) {
236
+ // Optimize company queries
237
+ if (!$this->indexExists('tracking_numbers', 'tracking_numbers_company_created_idx')) {
238
+ $table->index(['company_uuid', 'created_at'], 'tracking_numbers_company_created_idx');
239
+ }
240
+
241
+ // Optimize tracking_number lookups (for public tracking)
242
+ if (!$this->indexExists('tracking_numbers', 'tracking_numbers_tracking_number_idx')) {
243
+ $table->index('tracking_number', 'tracking_numbers_tracking_number_idx');
244
+ }
245
+
246
+ // Optimize owner lookups (polymorphic)
247
+ if (!$this->indexExists('tracking_numbers', 'tracking_numbers_owner_idx')) {
248
+ $table->index(['owner_uuid', 'owner_type'], 'tracking_numbers_owner_idx');
249
+ }
250
+ });
251
+
252
+ // ========================================
253
+ // TRACKING_STATUSES TABLE
254
+ // ========================================
255
+ Schema::table('tracking_statuses', function (Blueprint $table) {
256
+ // Optimize tracking_number_uuid lookups (for order tracking history)
257
+ if (!$this->indexExists('tracking_statuses', 'tracking_statuses_tracking_created_idx')) {
258
+ $table->index(['tracking_number_uuid', 'created_at'], 'tracking_statuses_tracking_created_idx');
259
+ }
260
+
261
+ // Optimize company queries
262
+ if (!$this->indexExists('tracking_statuses', 'tracking_statuses_company_created_idx')) {
263
+ $table->index(['company_uuid', 'created_at'], 'tracking_statuses_company_created_idx');
264
+ }
265
+ });
266
+ }
267
+
268
+ /**
269
+ * Reverse the migrations.
270
+ */
271
+ public function down(): void
272
+ {
273
+ // ORDERS
274
+ Schema::table('orders', function (Blueprint $table) {
275
+ if ($this->indexExists('orders', 'orders_company_driver_status_idx')) {
276
+ $table->dropIndex('orders_company_driver_status_idx');
277
+ }
278
+ if ($this->indexExists('orders', 'orders_company_created_idx')) {
279
+ $table->dropIndex('orders_company_created_idx');
280
+ }
281
+ if ($this->indexExists('orders', 'orders_company_scheduled_idx')) {
282
+ $table->dropIndex('orders_company_scheduled_idx');
283
+ }
284
+ if ($this->indexExists('orders', 'orders_company_dispatched_idx')) {
285
+ $table->dropIndex('orders_company_dispatched_idx');
286
+ }
287
+ if ($this->indexExists('orders', 'orders_payload_uuid_idx')) {
288
+ $table->dropIndex('orders_payload_uuid_idx');
289
+ }
290
+ if ($this->indexExists('orders', 'orders_tracking_number_uuid_idx')) {
291
+ $table->dropIndex('orders_tracking_number_uuid_idx');
292
+ }
293
+ if ($this->indexExists('orders', 'orders_vehicle_assigned_uuid_idx')) {
294
+ $table->dropIndex('orders_vehicle_assigned_uuid_idx');
295
+ }
296
+ });
297
+
298
+ // PAYLOADS
299
+ Schema::table('payloads', function (Blueprint $table) {
300
+ if ($this->indexExists('payloads', 'payloads_company_created_idx')) {
301
+ $table->dropIndex('payloads_company_created_idx');
302
+ }
303
+ if ($this->indexExists('payloads', 'payloads_pickup_uuid_idx')) {
304
+ $table->dropIndex('payloads_pickup_uuid_idx');
305
+ }
306
+ if ($this->indexExists('payloads', 'payloads_dropoff_uuid_idx')) {
307
+ $table->dropIndex('payloads_dropoff_uuid_idx');
308
+ }
309
+ if ($this->indexExists('payloads', 'payloads_return_uuid_idx')) {
310
+ $table->dropIndex('payloads_return_uuid_idx');
311
+ }
312
+ });
313
+
314
+ // WAYPOINTS
315
+ Schema::table('waypoints', function (Blueprint $table) {
316
+ if ($this->indexExists('waypoints', 'waypoints_payload_created_idx')) {
317
+ $table->dropIndex('waypoints_payload_created_idx');
318
+ }
319
+ if ($this->indexExists('waypoints', 'waypoints_company_created_idx')) {
320
+ $table->dropIndex('waypoints_company_created_idx');
321
+ }
322
+ if ($this->indexExists('waypoints', 'waypoints_place_uuid_idx')) {
323
+ $table->dropIndex('waypoints_place_uuid_idx');
324
+ }
325
+ });
326
+
327
+ // ENTITIES
328
+ Schema::table('entities', function (Blueprint $table) {
329
+ if ($this->indexExists('entities', 'entities_payload_created_idx')) {
330
+ $table->dropIndex('entities_payload_created_idx');
331
+ }
332
+ if ($this->indexExists('entities', 'entities_company_created_idx')) {
333
+ $table->dropIndex('entities_company_created_idx');
334
+ }
335
+ if ($this->indexExists('entities', 'entities_destination_uuid_idx')) {
336
+ $table->dropIndex('entities_destination_uuid_idx');
337
+ }
338
+ });
339
+
340
+ // PLACES
341
+ Schema::table('places', function (Blueprint $table) {
342
+ if ($this->indexExists('places', 'places_company_created_idx')) {
343
+ $table->dropIndex('places_company_created_idx');
344
+ }
345
+ if ($this->indexExists('places', 'places_owner_idx')) {
346
+ $table->dropIndex('places_owner_idx');
347
+ }
348
+ });
349
+
350
+ // DRIVERS
351
+ Schema::table('drivers', function (Blueprint $table) {
352
+ if ($this->indexExists('drivers', 'drivers_company_status_online_idx')) {
353
+ $table->dropIndex('drivers_company_status_online_idx');
354
+ }
355
+ if ($this->indexExists('drivers', 'drivers_company_created_idx')) {
356
+ $table->dropIndex('drivers_company_created_idx');
357
+ }
358
+ if ($this->indexExists('drivers', 'drivers_user_uuid_idx')) {
359
+ $table->dropIndex('drivers_user_uuid_idx');
360
+ }
361
+ if ($this->indexExists('drivers', 'drivers_vendor_uuid_idx')) {
362
+ $table->dropIndex('drivers_vendor_uuid_idx');
363
+ }
364
+ });
365
+
366
+ // VEHICLES
367
+ Schema::table('vehicles', function (Blueprint $table) {
368
+ if ($this->indexExists('vehicles', 'vehicles_company_status_online_idx')) {
369
+ $table->dropIndex('vehicles_company_status_online_idx');
370
+ }
371
+ if ($this->indexExists('vehicles', 'vehicles_company_created_idx')) {
372
+ $table->dropIndex('vehicles_company_created_idx');
373
+ }
374
+ if ($this->indexExists('vehicles', 'vehicles_vendor_uuid_idx')) {
375
+ $table->dropIndex('vehicles_vendor_uuid_idx');
376
+ }
377
+ });
378
+
379
+ // VENDORS
380
+ Schema::table('vendors', function (Blueprint $table) {
381
+ if ($this->indexExists('vendors', 'vendors_company_status_idx')) {
382
+ $table->dropIndex('vendors_company_status_idx');
383
+ }
384
+ });
385
+
386
+ // CONTACTS
387
+ Schema::table('contacts', function (Blueprint $table) {
388
+ if ($this->indexExists('contacts', 'contacts_company_created_idx')) {
389
+ $table->dropIndex('contacts_company_created_idx');
390
+ }
391
+ if ($this->indexExists('contacts', 'contacts_company_type_idx')) {
392
+ $table->dropIndex('contacts_company_type_idx');
393
+ }
394
+ });
395
+
396
+ // ROUTES
397
+ Schema::table('routes', function (Blueprint $table) {
398
+ if ($this->indexExists('routes', 'routes_company_created_idx')) {
399
+ $table->dropIndex('routes_company_created_idx');
400
+ }
401
+ });
402
+
403
+ // TRACKING_NUMBERS
404
+ Schema::table('tracking_numbers', function (Blueprint $table) {
405
+ if ($this->indexExists('tracking_numbers', 'tracking_numbers_company_created_idx')) {
406
+ $table->dropIndex('tracking_numbers_company_created_idx');
407
+ }
408
+ if ($this->indexExists('tracking_numbers', 'tracking_numbers_tracking_number_idx')) {
409
+ $table->dropIndex('tracking_numbers_tracking_number_idx');
410
+ }
411
+ if ($this->indexExists('tracking_numbers', 'tracking_numbers_owner_idx')) {
412
+ $table->dropIndex('tracking_numbers_owner_idx');
413
+ }
414
+ });
415
+
416
+ // TRACKING_STATUSES
417
+ Schema::table('tracking_statuses', function (Blueprint $table) {
418
+ if ($this->indexExists('tracking_statuses', 'tracking_statuses_tracking_created_idx')) {
419
+ $table->dropIndex('tracking_statuses_tracking_created_idx');
420
+ }
421
+ if ($this->indexExists('tracking_statuses', 'tracking_statuses_company_created_idx')) {
422
+ $table->dropIndex('tracking_statuses_company_created_idx');
423
+ }
424
+ });
425
+ }
426
+
427
+ /**
428
+ * Check if an index exists on a table.
429
+ */
430
+ protected function indexExists(string $table, string $index): bool
431
+ {
432
+ try {
433
+ $connection = Schema::getConnection();
434
+ $doctrineSchemaManager = $connection->getDoctrineSchemaManager();
435
+ $indexes = $doctrineSchemaManager->listTableIndexes($table);
436
+
437
+ return isset($indexes[$index]);
438
+ } catch (Exception $e) {
439
+ return false;
440
+ }
441
+ }
442
+ };
@@ -135,8 +135,13 @@ class DispatchAdhocOrders extends Command
135
135
  ->withoutGlobalScopes();
136
136
 
137
137
  if (!$testing) {
138
- $driverQuery->distanceSphere('location', $pickup, $distance)
139
- ->distanceSphereValue('location', $pickup);
138
+ $driverQuery->whereNotNull('location')->whereRaw('
139
+ ST_Y(location) BETWEEN -90 AND 90
140
+ AND ST_X(location) BETWEEN -180 AND 180
141
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
142
+ ');
143
+ $driverQuery->distanceSphere('location', $pickup, $distance);
144
+ $driverQuery->distanceSphereValue('location', $pickup);
140
145
  }
141
146
 
142
147
  return $driverQuery->get();
@@ -551,6 +551,7 @@ class DriverController extends Controller
551
551
  // generate verification token
552
552
  try {
553
553
  VerificationCode::generateSmsVerificationFor($user, 'driver_login', [
554
+ 'company_uuid' => $company->uuid,
554
555
  'messageCallback' => function ($verification) use ($company) {
555
556
  return 'Your ' . data_get($company, 'name', config('app.name')) . ' verification code is ' . $verification->code;
556
557
  },
@@ -566,6 +567,7 @@ class DriverController extends Controller
566
567
  if ($user->email) {
567
568
  try {
568
569
  VerificationCode::generateEmailVerificationFor($user, 'driver_login', [
570
+ 'company_uuid' => $company->uuid,
569
571
  'messageCallback' => function ($verification) use ($company) {
570
572
  return 'Your ' . data_get($company, 'name', config('app.name')) . ' verification code is ' . $verification->code;
571
573
  },
@@ -629,9 +629,19 @@ class OrderController extends Controller
629
629
 
630
630
  $query->whereHas('payload', function ($q) use ($location, $distance) {
631
631
  $q->whereHas('pickup', function ($q) use ($location, $distance) {
632
+ $q->whereNotNull('location')->whereRaw('
633
+ ST_Y(location) BETWEEN -90 AND 90
634
+ AND ST_X(location) BETWEEN -180 AND 180
635
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
636
+ ');
632
637
  $q->distanceSphere('location', $location, $distance);
633
638
  $q->distanceSphereValue('location', $location);
634
639
  })->orWhereHas('waypoints', function ($q) use ($location, $distance) {
640
+ $q->whereNotNull('location')->whereRaw('
641
+ ST_Y(location) BETWEEN -90 AND 90
642
+ AND ST_X(location) BETWEEN -180 AND 180
643
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
644
+ ');
635
645
  $q->distanceSphere('location', $location, $distance);
636
646
  $q->distanceSphereValue('location', $location);
637
647
  });
@@ -648,9 +658,19 @@ class OrderController extends Controller
648
658
  if ($driver) {
649
659
  $query->whereHas('payload', function ($q) use ($driver, $distance) {
650
660
  $q->whereHas('pickup', function ($q) use ($driver, $distance) {
661
+ $q->whereNotNull('location')->whereRaw('
662
+ ST_Y(location) BETWEEN -90 AND 90
663
+ AND ST_X(location) BETWEEN -180 AND 180
664
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
665
+ ');
651
666
  $q->distanceSphere('location', $driver->location, $distance);
652
667
  $q->distanceSphereValue('location', $driver->location);
653
668
  })->orWhereHas('waypoints', function ($q) use ($driver, $distance) {
669
+ $q->whereNotNull('location')->whereRaw('
670
+ ST_Y(location) BETWEEN -90 AND 90
671
+ AND ST_X(location) BETWEEN -180 AND 180
672
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
673
+ ');
654
674
  $q->distanceSphere('location', $driver->location, $distance);
655
675
  $q->distanceSphereValue('location', $driver->location);
656
676
  });
@@ -668,9 +688,19 @@ class OrderController extends Controller
668
688
  if ($nearby instanceof Place) {
669
689
  $query->whereHas('payload', function ($q) use ($nearby, $distance) {
670
690
  $q->whereHas('pickup', function ($q) use ($nearby, $distance) {
691
+ $q->whereNotNull('location')->whereRaw('
692
+ ST_Y(location) BETWEEN -90 AND 90
693
+ AND ST_X(location) BETWEEN -180 AND 180
694
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
695
+ ');
671
696
  $q->distanceSphere('location', $nearby->location, $distance);
672
697
  $q->distanceSphereValue('location', $nearby->location);
673
698
  })->orWhereHas('waypoints', function ($q) use ($nearby, $distance) {
699
+ $q->whereNotNull('location')->whereRaw('
700
+ ST_Y(location) BETWEEN -90 AND 90
701
+ AND ST_X(location) BETWEEN -180 AND 180
702
+ AND NOT (ST_X(location) = 0 AND ST_Y(location) = 0)
703
+ ');
674
704
  $q->distanceSphere('location', $nearby->location, $distance);
675
705
  $q->distanceSphereValue('location', $nearby->location);
676
706
  });