@fleetbase/fleetops-engine 0.6.52 → 0.6.54

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 (151) hide show
  1. package/addon/components/device/details.hbs +106 -135
  2. package/addon/components/device/details.js +174 -1
  3. package/addon/components/device/panel-header.hbs +2 -2
  4. package/addon/components/layout/fleet-ops-sidebar/operations-monitor.hbs +201 -0
  5. package/addon/components/layout/fleet-ops-sidebar/operations-monitor.js +654 -0
  6. package/addon/components/layout/fleet-ops-sidebar.hbs +19 -233
  7. package/addon/components/layout/fleet-ops-sidebar.js +364 -395
  8. package/addon/components/maintenance-schedule/form.js +1 -0
  9. package/addon/components/order/form/details.hbs +1 -43
  10. package/addon/components/order/form/details.js +18 -53
  11. package/addon/components/order/form/orchestrator-constraints.hbs +40 -0
  12. package/addon/components/order/form/orchestrator-constraints.js +61 -0
  13. package/addon/components/order/form/payload.js +50 -2
  14. package/addon/components/order/form/route.js +15 -0
  15. package/addon/components/order/form/service-rate.hbs +62 -11
  16. package/addon/components/order/form/service-rate.js +124 -2
  17. package/addon/components/order/form.hbs +2 -0
  18. package/addon/components/telematic/details.hbs +7 -1
  19. package/addon/components/telematic/form.js +16 -8
  20. package/addon/components/work-order/details.hbs +5 -1
  21. package/addon/components/work-order/form.hbs +26 -4
  22. package/addon/components/work-order/form.js +5 -1
  23. package/addon/controllers/connectivity/devices/index/details/events.js +244 -1
  24. package/addon/controllers/connectivity/devices/index/details/sensors.js +199 -0
  25. package/addon/controllers/connectivity/devices/index/details/vehicle.js +74 -0
  26. package/addon/controllers/connectivity/devices/index/details.js +12 -0
  27. package/addon/controllers/connectivity/devices/index.js +4 -1
  28. package/addon/controllers/connectivity/telematics/details/attachments.js +220 -54
  29. package/addon/controllers/connectivity/telematics/details/devices.js +90 -41
  30. package/addon/controllers/connectivity/telematics/details/events.js +39 -11
  31. package/addon/controllers/connectivity/telematics/details/sensors.js +39 -19
  32. package/addon/controllers/maintenance/index.js +100 -0
  33. package/addon/controllers/maintenance/work-orders/index.js +18 -1
  34. package/addon/controllers/management/fuel-transactions/index.js +1 -1
  35. package/addon/controllers/management/index.js +88 -0
  36. package/addon/controllers/settings/index.js +142 -0
  37. package/addon/extension.js +21 -0
  38. package/addon/routes/analytics/index.js +3 -0
  39. package/addon/routes/connectivity/devices/index/details/events.js +37 -1
  40. package/addon/routes/connectivity/devices/index/details/sensors.js +35 -0
  41. package/addon/routes/connectivity/devices/index/details/vehicle.js +7 -0
  42. package/addon/routes/connectivity/devices/index.js +3 -0
  43. package/addon/routes/connectivity/telematics/details/attachments.js +72 -9
  44. package/addon/routes/connectivity/telematics/details/devices.js +4 -0
  45. package/addon/routes/connectivity/telematics/details/sensors.js +1 -0
  46. package/addon/routes/connectivity/telematics/details.js +1 -1
  47. package/addon/routes/connectivity/telematics/edit.js +1 -1
  48. package/addon/routes/maintenance/index.js +3 -0
  49. package/addon/routes/maintenance/work-orders/index.js +3 -0
  50. package/addon/routes/settings/index.js +3 -0
  51. package/addon/routes.js +2 -0
  52. package/addon/services/order-creation.js +54 -1
  53. package/addon/services/order-validation.js +3 -2
  54. package/addon/services/service-rate-actions.js +1 -0
  55. package/addon/styles/fleetops-engine.css +1821 -6
  56. package/addon/templates/analytics/index.hbs +14 -0
  57. package/addon/templates/analytics/reports/index.hbs +4 -4
  58. package/addon/templates/connectivity/devices/index/details/events.hbs +85 -1
  59. package/addon/templates/connectivity/devices/index/details/sensors.hbs +73 -0
  60. package/addon/templates/connectivity/devices/index/details/vehicle.hbs +84 -0
  61. package/addon/templates/connectivity/telematics/details/attachments.hbs +198 -121
  62. package/addon/templates/connectivity/telematics/details/devices.hbs +4 -1
  63. package/addon/templates/connectivity/telematics/details/events.hbs +4 -1
  64. package/addon/templates/connectivity/telematics/details/sensors.hbs +3 -0
  65. package/addon/templates/maintenance/index.hbs +113 -0
  66. package/addon/templates/management/fuel-transactions/index/details.hbs +1 -1
  67. package/addon/templates/management/index.hbs +109 -73
  68. package/addon/templates/management/vehicles/index/edit.hbs +1 -1
  69. package/addon/templates/operations/orders/index.hbs +1 -1
  70. package/addon/templates/operations/service-rates/index.hbs +1 -1
  71. package/addon/templates/settings/index.hbs +83 -0
  72. package/addon/templates/settings/routing.hbs +2 -2
  73. package/addon/utils/fleet-ops-options.js +38 -0
  74. package/app/components/order/form/orchestrator-constraints.js +1 -0
  75. package/app/controllers/connectivity/devices/index/details/sensors.js +1 -0
  76. package/app/controllers/connectivity/devices/index/details/vehicle.js +1 -0
  77. package/app/controllers/maintenance/index.js +1 -0
  78. package/app/controllers/management/index.js +1 -0
  79. package/app/controllers/settings/index.js +1 -0
  80. package/app/routes/analytics/index.js +1 -0
  81. package/app/routes/connectivity/devices/index/details/sensors.js +1 -0
  82. package/app/routes/connectivity/devices/index/details/vehicle.js +1 -0
  83. package/app/routes/maintenance/index.js +1 -0
  84. package/app/routes/settings/index.js +1 -0
  85. package/app/templates/analytics/index.js +1 -0
  86. package/app/templates/connectivity/devices/index/details/sensors.js +1 -0
  87. package/app/templates/connectivity/devices/index/details/vehicle.js +1 -0
  88. package/app/templates/maintenance/index.js +1 -0
  89. package/app/templates/management/index.js +1 -0
  90. package/app/templates/settings/index.js +1 -0
  91. package/composer.json +1 -1
  92. package/extension.json +1 -1
  93. package/package.json +3 -3
  94. package/server/migrations/2025_08_28_054930_create_work_orders_table.php +1 -0
  95. package/server/migrations/2026_06_15_000001_normalize_device_attachable_vehicle_morph_types.php +30 -0
  96. package/server/migrations/2026_06_18_000001_add_category_to_work_orders_table.php +32 -0
  97. package/server/seeders/Testing/MaintenanceSeeder.php +5 -4
  98. package/server/src/Console/Commands/FixInvalidPolymorphicRelationTypeNamespaces.php +1 -0
  99. package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +1 -0
  100. package/server/src/Console/Commands/SyncTelematics.php +89 -0
  101. package/server/src/Exceptions/TelematicProviderException.php +13 -2
  102. package/server/src/Http/Controllers/Api/v1/OrderController.php +6 -21
  103. package/server/src/Http/Controllers/Internal/v1/DeviceController.php +112 -11
  104. package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +16 -5
  105. package/server/src/Http/Controllers/Internal/v1/FleetController.php +9 -0
  106. package/server/src/Http/Controllers/Internal/v1/HubController.php +300 -0
  107. package/server/src/Http/Controllers/Internal/v1/LiveController.php +177 -0
  108. package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +1 -0
  109. package/server/src/Http/Controllers/Internal/v1/OrderController.php +4 -32
  110. package/server/src/Http/Controllers/Internal/v1/SearchController.php +506 -0
  111. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +4 -4
  112. package/server/src/Http/Controllers/Internal/v1/TelematicController.php +1 -1
  113. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +94 -10
  114. package/server/src/Http/Filter/DeviceEventFilter.php +44 -0
  115. package/server/src/Http/Filter/DeviceFilter.php +131 -0
  116. package/server/src/Http/Filter/DriverFilter.php +6 -0
  117. package/server/src/Http/Filter/SensorFilter.php +125 -0
  118. package/server/src/Http/Filter/VehicleFilter.php +19 -0
  119. package/server/src/Http/Requests/CreateDriverRequest.php +14 -13
  120. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -0
  121. package/server/src/Http/Resources/v1/Driver.php +11 -2
  122. package/server/src/Http/Resources/v1/WorkOrder.php +1 -0
  123. package/server/src/Jobs/FinalizeApiOrderCreation.php +47 -0
  124. package/server/src/Jobs/FinalizeInternalOrderCreation.php +35 -0
  125. package/server/src/Jobs/NotifyBulkAssignedDriver.php +47 -0
  126. package/server/src/Jobs/SyncTelematicDevicesJob.php +181 -66
  127. package/server/src/Models/Device.php +15 -1
  128. package/server/src/Models/DeviceEvent.php +1 -1
  129. package/server/src/Models/Driver.php +17 -1
  130. package/server/src/Models/Sensor.php +15 -2
  131. package/server/src/Models/Telematic.php +1 -1
  132. package/server/src/Models/Vehicle.php +5 -1
  133. package/server/src/Models/WorkOrder.php +5 -2
  134. package/server/src/Observers/DriverObserver.php +3 -3
  135. package/server/src/Observers/FleetObserver.php +23 -0
  136. package/server/src/Observers/VehicleObserver.php +3 -3
  137. package/server/src/Providers/FleetOpsServiceProvider.php +12 -0
  138. package/server/src/Support/LiveCacheService.php +1 -1
  139. package/server/src/Support/Telematics/Providers/AfaqyProvider.php +188 -28
  140. package/server/src/Support/Telematics/Providers/SafeeProvider.php +44 -3
  141. package/server/src/Support/Telematics/TelematicService.php +330 -30
  142. package/server/src/routes.php +10 -0
  143. package/server/tests/DeviceFilterTest.php +36 -0
  144. package/server/tests/HubRoutesTest.php +62 -0
  145. package/server/tests/OperationsMonitorEndpointTest.php +38 -0
  146. package/server/tests/OrderQueuedClosureRegressionTest.php +36 -0
  147. package/server/tests/TelematicsHardeningTest.php +455 -3
  148. package/server/tests/VehicleDriverAssignmentTest.php +27 -0
  149. package/translations/ar-ae.yml +1 -1
  150. package/translations/en-us.yaml +1 -0
  151. package/translations/vi-vn.yaml +1 -1
@@ -0,0 +1,89 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Console\Commands;
4
+
5
+ use Fleetbase\FleetOps\Jobs\SyncTelematicDevicesJob;
6
+ use Fleetbase\FleetOps\Models\Telematic;
7
+ use Fleetbase\FleetOps\Support\Telematics\TelematicProviderRegistry;
8
+ use Illuminate\Console\Command;
9
+ use Illuminate\Support\Facades\Cache;
10
+
11
+ class SyncTelematics extends Command
12
+ {
13
+ protected $signature = 'fleetops:sync-telematics
14
+ {--provider=* : Limit polling to one or more provider keys}
15
+ {--limit=500 : Maximum provider units to fetch per page}
16
+ {--sync-webhook-providers : Include providers that support webhooks}
17
+ {--no-lock : Skip process locking}';
18
+
19
+ protected $description = 'Poll active telematics providers for device snapshots and positional telemetry.';
20
+
21
+ public function handle(TelematicProviderRegistry $registry): int
22
+ {
23
+ $useLock = !$this->option('no-lock');
24
+ $lock = null;
25
+
26
+ if ($useLock) {
27
+ $lock = Cache::lock('fleetops:sync-telematics', 600);
28
+ if (!$lock->get()) {
29
+ $this->warn('Another telematics sync run appears to be in progress.');
30
+
31
+ return self::SUCCESS;
32
+ }
33
+ }
34
+
35
+ try {
36
+ $providerKeys = $this->pollableProviderKeys($registry);
37
+ if (empty($providerKeys)) {
38
+ $this->info('No pollable telematics providers found.');
39
+
40
+ return self::SUCCESS;
41
+ }
42
+
43
+ $query = Telematic::withoutGlobalScopes()
44
+ ->whereIn('provider', $providerKeys)
45
+ ->whereIn('status', ['active', 'connected'])
46
+ ->whereNotNull('company_uuid');
47
+
48
+ $queued = 0;
49
+ $query->orderBy('id')->chunkById(100, function ($telematics) use (&$queued) {
50
+ foreach ($telematics as $telematic) {
51
+ SyncTelematicDevicesJob::dispatch($telematic, [
52
+ 'limit' => (int) $this->option('limit'),
53
+ ]);
54
+ $queued++;
55
+ }
56
+ });
57
+
58
+ $this->info("Queued {$queued} telematics sync job(s).");
59
+
60
+ return self::SUCCESS;
61
+ } finally {
62
+ if ($lock) {
63
+ $lock->release();
64
+ }
65
+ }
66
+ }
67
+
68
+ protected function pollableProviderKeys(TelematicProviderRegistry $registry): array
69
+ {
70
+ $requestedProviders = array_filter((array) $this->option('provider'));
71
+ $includeWebhookProviders = (bool) $this->option('sync-webhook-providers');
72
+
73
+ return $registry->all()
74
+ ->filter(function ($descriptor) use ($requestedProviders, $includeWebhookProviders) {
75
+ if (!empty($requestedProviders) && !in_array($descriptor->key, $requestedProviders, true)) {
76
+ return false;
77
+ }
78
+
79
+ if (!$descriptor->supportsDiscovery) {
80
+ return false;
81
+ }
82
+
83
+ return $includeWebhookProviders || !$descriptor->supportsWebhooks;
84
+ })
85
+ ->keys()
86
+ ->values()
87
+ ->all();
88
+ }
89
+ }
@@ -2,8 +2,6 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Exceptions;
4
4
 
5
- use Exception;
6
-
7
5
  /**
8
6
  * Class TelematicProviderException.
9
7
  *
@@ -11,4 +9,17 @@ use Exception;
11
9
  */
12
10
  class TelematicProviderException extends \Exception
13
11
  {
12
+ protected array $context;
13
+
14
+ public function __construct(string $message = '', array $context = [], int $code = 0, ?\Throwable $previous = null)
15
+ {
16
+ parent::__construct($message, $code, $previous);
17
+
18
+ $this->context = $context;
19
+ }
20
+
21
+ public function context(): array
22
+ {
23
+ return $this->context;
24
+ }
14
25
  }
@@ -3,7 +3,6 @@
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
4
4
 
5
5
  use Fleetbase\FleetOps\Events\OrderDispatchFailed;
6
- use Fleetbase\FleetOps\Events\OrderReady;
7
6
  use Fleetbase\FleetOps\Events\OrderStarted;
8
7
  use Fleetbase\FleetOps\Exceptions\CustomerUserConflictException;
9
8
  use Fleetbase\FleetOps\Exceptions\UserAlreadyExistsException;
@@ -14,6 +13,7 @@ use Fleetbase\FleetOps\Http\Requests\UpdateOrderRequest;
14
13
  use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
15
14
  use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
16
15
  use Fleetbase\FleetOps\Http\Resources\v1\Proof as ProofResource;
16
+ use Fleetbase\FleetOps\Jobs\FinalizeApiOrderCreation;
17
17
  use Fleetbase\FleetOps\Models\Contact;
18
18
  use Fleetbase\FleetOps\Models\Driver;
19
19
  use Fleetbase\FleetOps\Models\Entity;
@@ -335,26 +335,11 @@ class OrderController extends Controller
335
335
  // Determine if order should be dispatched on creation
336
336
  $shouldDispatch = $request->boolean('dispatch') && $integratedVendorOrder === null;
337
337
 
338
- // Run background processes on queue
339
- dispatch(function () use ($order, $serviceQuote, $shouldDispatch): void {
340
- // notify driver if assigned
341
- $order->notifyDriverAssigned();
342
-
343
- // set driving distance and time
344
- $order->setPreliminaryDistanceAndTime();
345
-
346
- // if service quote attached purchase
347
- $order->purchaseServiceQuote($serviceQuote);
348
-
349
- // dispatch if flagged true
350
- if ($shouldDispatch) {
351
- $order->dispatchWithActivity();
352
- }
353
-
354
- // Trigger order created event
355
- event(new OrderReady($order));
356
- })
357
- ->afterCommit();
338
+ FinalizeApiOrderCreation::dispatch(
339
+ $order->uuid,
340
+ $serviceQuote instanceof ServiceQuote ? $serviceQuote->uuid : null,
341
+ $shouldDispatch
342
+ )->afterCommit();
358
343
 
359
344
  // response the driver resource
360
345
  return new OrderResource($order);
@@ -5,8 +5,10 @@ namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
5
5
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
6
6
  use Fleetbase\FleetOps\Models\Device;
7
7
  use Fleetbase\FleetOps\Models\Vehicle;
8
+ use Fleetbase\FleetOps\Support\Utils;
8
9
  use Illuminate\Http\JsonResponse;
9
10
  use Illuminate\Http\Request;
11
+ use Illuminate\Support\Facades\Log;
10
12
 
11
13
  class DeviceController extends FleetOpsController
12
14
  {
@@ -42,6 +44,31 @@ class DeviceController extends FleetOpsController
42
44
  if ($request->filled('device_id')) {
43
45
  $query->where('device_id', 'like', '%' . $request->input('device_id') . '%');
44
46
  }
47
+
48
+ if ($request->filled('connection_status')) {
49
+ $statuses = Utils::arrayFrom($request->input('connection_status'));
50
+
51
+ $query->where(function ($statusQuery) use ($statuses) {
52
+ foreach ($statuses as $status) {
53
+ match ($status) {
54
+ 'online' => $statusQuery->orWhere('last_online_at', '>=', now()->subMinutes(10)),
55
+ 'recently_offline' => $statusQuery->orWhereBetween('last_online_at', [now()->subMinutes(60), now()->subMinutes(10)]),
56
+ 'offline' => $statusQuery->orWhereBetween('last_online_at', [now()->subDay(), now()->subMinutes(60)]),
57
+ 'long_offline' => $statusQuery->orWhere('last_online_at', '<', now()->subDay()),
58
+ 'never_connected' => $statusQuery->orWhereNull('last_online_at'),
59
+ default => null,
60
+ };
61
+ }
62
+ });
63
+ }
64
+
65
+ if ($request->filled('last_online_at')) {
66
+ static::applyDateFilter($query, 'last_online_at', $request->input('last_online_at'));
67
+ }
68
+
69
+ if ($request->filled('updated_at')) {
70
+ static::applyDateFilter($query, 'updated_at', $request->input('updated_at'));
71
+ }
45
72
  }
46
73
 
47
74
  /**
@@ -64,11 +91,30 @@ class DeviceController extends FleetOpsController
64
91
  'vehicle' => 'required_without:attachable_uuid|nullable|string',
65
92
  ]);
66
93
 
67
- $device = $this->findDevice($id);
68
- $vehicle = $this->findVehicle($request->input('vehicle') ?? $request->input('attachable_uuid'));
94
+ $vehicleId = $request->input('vehicle') ?? $request->input('attachable_uuid');
95
+ $device = $this->resolveDevice($id);
96
+ $vehicle = $this->resolveVehicle($vehicleId);
97
+
98
+ if (!$device) {
99
+ $this->logDeviceAttachmentLookupFailure('attach', 'device', $id, $vehicleId);
100
+
101
+ return response()->error('Device not found or not available for this organization.', 404);
102
+ }
103
+
104
+ if (!$vehicle) {
105
+ $this->logDeviceAttachmentLookupFailure('attach', 'vehicle', $id, $vehicleId);
106
+
107
+ return response()->error('Vehicle not found or not available for this organization.', 404);
108
+ }
69
109
 
70
- $device->attachTo($vehicle);
71
- $device->load(['telematic', 'warranty', 'attachable']);
110
+ try {
111
+ $device->attachTo($vehicle);
112
+ $device->load(['telematic', 'warranty', 'attachable']);
113
+ } catch (\Throwable $e) {
114
+ $this->logDeviceAttachmentFailure('attach', $device, $vehicle, $e);
115
+
116
+ return response()->error('Unable to attach device to vehicle. Please try again or contact support.', 500);
117
+ }
72
118
 
73
119
  return response()->json([
74
120
  'status' => 'ok',
@@ -81,9 +127,22 @@ class DeviceController extends FleetOpsController
81
127
  */
82
128
  public function detach(string $id): JsonResponse
83
129
  {
84
- $device = $this->findDevice($id);
85
- $device->detach();
86
- $device->load(['telematic', 'warranty', 'attachable']);
130
+ $device = $this->resolveDevice($id);
131
+
132
+ if (!$device) {
133
+ $this->logDeviceAttachmentLookupFailure('detach', 'device', $id, null);
134
+
135
+ return response()->error('Device not found or not available for this organization.', 404);
136
+ }
137
+
138
+ try {
139
+ $device->detach();
140
+ $device->load(['telematic', 'warranty', 'attachable']);
141
+ } catch (\Throwable $e) {
142
+ $this->logDeviceAttachmentFailure('detach', $device, null, $e);
143
+
144
+ return response()->error('Unable to detach device from vehicle. Please try again or contact support.', 500);
145
+ }
87
146
 
88
147
  return response()->json([
89
148
  'status' => 'ok',
@@ -91,21 +150,63 @@ class DeviceController extends FleetOpsController
91
150
  ]);
92
151
  }
93
152
 
94
- protected function findDevice(string $id): Device
153
+ protected function resolveDevice(string $id): ?Device
95
154
  {
96
155
  return Device::where(function ($query) use ($id) {
97
156
  $query->where('uuid', $id)->orWhere('public_id', $id);
98
157
  })
99
158
  ->where('company_uuid', session('company'))
100
- ->firstOrFail();
159
+ ->first();
101
160
  }
102
161
 
103
- protected function findVehicle(?string $id): Vehicle
162
+ protected function resolveVehicle(?string $id): ?Vehicle
104
163
  {
164
+ if (!$id) {
165
+ return null;
166
+ }
167
+
105
168
  return Vehicle::where(function ($query) use ($id) {
106
169
  $query->where('uuid', $id)->orWhere('public_id', $id);
107
170
  })
108
171
  ->where('company_uuid', session('company'))
109
- ->firstOrFail();
172
+ ->first();
173
+ }
174
+
175
+ protected static function applyDateFilter($query, string $column, string|array $value): void
176
+ {
177
+ $dates = Utils::dateRange($value);
178
+
179
+ if (is_array($dates)) {
180
+ $query->whereBetween($column, $dates);
181
+ } else {
182
+ $query->whereDate($column, $dates);
183
+ }
184
+ }
185
+
186
+ protected function logDeviceAttachmentLookupFailure(string $action, string $missingResource, string $deviceId, ?string $vehicleId): void
187
+ {
188
+ Log::warning('Device attachment lookup failed', [
189
+ 'action' => $action,
190
+ 'missing_resource' => $missingResource,
191
+ 'device_id' => $deviceId,
192
+ 'vehicle_id' => $vehicleId,
193
+ 'company_uuid' => session('company'),
194
+ 'request_id' => request()->headers->get('X-Request-ID') ?? request()->headers->get('X-Correlation-ID'),
195
+ ]);
196
+ }
197
+
198
+ protected function logDeviceAttachmentFailure(string $action, Device $device, ?Vehicle $vehicle, \Throwable $exception): void
199
+ {
200
+ Log::error('Device attachment failed', [
201
+ 'action' => $action,
202
+ 'device_uuid' => $device->uuid,
203
+ 'device_id' => $device->public_id,
204
+ 'vehicle_uuid' => $vehicle?->uuid,
205
+ 'vehicle_id' => $vehicle?->public_id,
206
+ 'company_uuid' => session('company'),
207
+ 'request_id' => request()->headers->get('X-Request-ID') ?? request()->headers->get('X-Correlation-ID'),
208
+ 'exception_class' => get_class($exception),
209
+ 'exception' => $exception->getMessage(),
210
+ ]);
110
211
  }
111
212
  }
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
5
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
6
6
  use Fleetbase\FleetOps\Models\DeviceEvent;
7
+ use Fleetbase\FleetOps\Support\Utils;
7
8
  use Illuminate\Http\JsonResponse;
8
9
 
9
10
  class DeviceEventController extends FleetOpsController
@@ -32,11 +33,21 @@ class DeviceEventController extends FleetOpsController
32
33
  }
33
34
 
34
35
  if ($request->filled('processed')) {
35
- match ($request->input('processed')) {
36
- 'processed' => $query->whereNotNull('processed_at'),
37
- 'unprocessed' => $query->whereNull('processed_at'),
38
- default => null,
39
- };
36
+ $states = Utils::arrayFrom($request->input('processed'));
37
+
38
+ if (!$states) {
39
+ return;
40
+ }
41
+
42
+ $query->where(function ($query) use ($states) {
43
+ foreach ($states as $state) {
44
+ match ($state) {
45
+ 'processed' => $query->orWhereNotNull('processed_at'),
46
+ 'unprocessed' => $query->orWhereNull('processed_at'),
47
+ default => null,
48
+ };
49
+ }
50
+ });
40
51
  }
41
52
  }
42
53
 
@@ -11,6 +11,7 @@ use Fleetbase\FleetOps\Models\Fleet;
11
11
  use Fleetbase\FleetOps\Models\FleetDriver;
12
12
  use Fleetbase\FleetOps\Models\FleetVehicle;
13
13
  use Fleetbase\FleetOps\Models\Vehicle;
14
+ use Fleetbase\FleetOps\Support\LiveCacheService;
14
15
  use Fleetbase\Http\Requests\ExportRequest;
15
16
  use Fleetbase\Http\Requests\ImportRequest;
16
17
  use Illuminate\Http\Request;
@@ -121,6 +122,8 @@ class FleetController extends FleetOpsController
121
122
  'driver_uuid' => $driver->uuid,
122
123
  ])->delete();
123
124
 
125
+ LiveCacheService::invalidate('operations-monitor');
126
+
124
127
  return response()->json([
125
128
  'status' => 'ok',
126
129
  'deleted' => $deleted,
@@ -153,6 +156,8 @@ class FleetController extends FleetOpsController
153
156
  ]);
154
157
  }
155
158
 
159
+ LiveCacheService::invalidate('operations-monitor');
160
+
156
161
  return response()->json([
157
162
  'status' => 'ok',
158
163
  'exists' => $exists,
@@ -178,6 +183,8 @@ class FleetController extends FleetOpsController
178
183
  'vehicle_uuid' => $vehicle->uuid,
179
184
  ])->delete();
180
185
 
186
+ LiveCacheService::invalidate('operations-monitor');
187
+
181
188
  return response()->json([
182
189
  'status' => 'ok',
183
190
  'deleted' => $deleted,
@@ -210,6 +217,8 @@ class FleetController extends FleetOpsController
210
217
  ]);
211
218
  }
212
219
 
220
+ LiveCacheService::invalidate('operations-monitor');
221
+
213
222
  return response()->json([
214
223
  'status' => 'ok',
215
224
  'exists' => $exists,