@fleetbase/fleetops-engine 0.6.53 → 0.6.55
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.
- package/addon/components/admin/routing-settings.hbs +2 -1
- package/addon/components/cell/attached-vehicle.hbs +10 -0
- package/addon/components/cell/attached-vehicle.js +58 -0
- package/addon/components/cell/device-identity.hbs +24 -0
- package/addon/components/cell/device-identity.js +129 -0
- package/addon/components/cell/driver-identity.hbs +33 -0
- package/addon/components/cell/driver-identity.js +143 -0
- package/addon/components/cell/equipment-identity.hbs +5 -0
- package/addon/components/cell/equipment-identity.js +48 -0
- package/addon/components/cell/part-identity.hbs +5 -0
- package/addon/components/cell/part-identity.js +63 -0
- package/addon/components/cell/telematic-device.hbs +38 -0
- package/addon/components/cell/telematic-device.js +44 -0
- package/addon/components/cell/telematic-provider.hbs +33 -16
- package/addon/components/cell/telematic-provider.js +50 -8
- package/addon/components/cell/vehicle-identity.hbs +33 -0
- package/addon/components/cell/vehicle-identity.js +138 -0
- package/addon/components/device/details.hbs +106 -135
- package/addon/components/device/details.js +174 -1
- package/addon/components/device/form.hbs +2 -2
- package/addon/components/device/form.js +7 -0
- package/addon/components/device/panel-header.hbs +46 -21
- package/addon/components/device/panel-header.js +49 -1
- package/addon/components/device/panel-tabs/events.hbs +30 -0
- package/addon/components/device/panel-tabs/events.js +128 -0
- package/addon/components/device/panel-tabs/sensors.hbs +30 -0
- package/addon/components/device/panel-tabs/sensors.js +93 -0
- package/addon/components/device/panel-tabs/vehicle.hbs +68 -0
- package/addon/components/device/panel-tabs/vehicle.js +90 -0
- package/addon/components/equipment/form.js +8 -1
- package/addon/components/layout/fleet-ops-sidebar/operations-monitor.js +76 -11
- package/addon/components/layout/fleet-ops-sidebar.hbs +1 -1
- package/addon/components/layout/fleet-ops-sidebar.js +101 -17
- package/addon/components/map/drawer/device-event-listing.js +2 -0
- package/addon/components/map/drawer/driver-listing.js +2 -0
- package/addon/components/map/drawer/place-listing.js +2 -0
- package/addon/components/map/drawer/position-listing.hbs +11 -6
- package/addon/components/map/drawer/position-listing.js +17 -4
- package/addon/components/map/drawer/vehicle-listing.js +2 -0
- package/addon/components/order/form/details.hbs +1 -43
- package/addon/components/order/form/details.js +18 -53
- package/addon/components/order/form/orchestrator-constraints.hbs +40 -0
- package/addon/components/order/form/orchestrator-constraints.js +61 -0
- package/addon/components/order/form/payload.js +48 -2
- package/addon/components/order/form/route.js +15 -0
- package/addon/components/order/form/service-rate.hbs +62 -11
- package/addon/components/order/form/service-rate.js +124 -2
- package/addon/components/order/form.hbs +2 -0
- package/addon/components/sensor/panel-header.hbs +47 -15
- package/addon/components/sensor/panel-header.js +59 -1
- package/addon/components/table/cell/dropdown/action-item.hbs +31 -0
- package/addon/components/table/cell/dropdown/action-item.js +62 -0
- package/addon/components/table/cell/dropdown.hbs +28 -0
- package/addon/components/table/cell/dropdown.js +91 -0
- package/addon/components/telematic/details.hbs +7 -1
- package/addon/components/telematic/form.js +16 -8
- package/addon/components/vendor/panel-header.hbs +82 -0
- package/addon/components/vendor/panel-header.js +48 -0
- package/addon/components/work-order/details.hbs +5 -1
- package/addon/components/work-order/form.hbs +26 -4
- package/addon/components/work-order/form.js +5 -1
- package/addon/controllers/connectivity/devices/index/details/events.js +244 -1
- package/addon/controllers/connectivity/devices/index/details/sensors.js +199 -0
- package/addon/controllers/connectivity/devices/index/details/vehicle.js +122 -0
- package/addon/controllers/connectivity/devices/index/details.js +12 -0
- package/addon/controllers/connectivity/devices/index.js +144 -129
- package/addon/controllers/connectivity/events/details.js +3 -0
- package/addon/controllers/connectivity/events/index.js +187 -11
- package/addon/controllers/connectivity/sensors/index.js +156 -14
- package/addon/controllers/connectivity/telematics/details/attachments.js +220 -54
- package/addon/controllers/connectivity/telematics/details/devices.js +170 -129
- package/addon/controllers/connectivity/telematics/details/events.js +39 -11
- package/addon/controllers/connectivity/telematics/details/sensors.js +39 -19
- package/addon/controllers/maintenance/equipment/index.js +1 -2
- package/addon/controllers/maintenance/parts/index.js +1 -2
- package/addon/controllers/maintenance/work-orders/index.js +18 -1
- package/addon/controllers/management/drivers/index.js +82 -42
- package/addon/controllers/management/fuel-reports/index.js +63 -4
- package/addon/controllers/management/issues/index.js +63 -4
- package/addon/controllers/management/vehicles/index.js +33 -6
- package/addon/routes/connectivity/devices/index/details/events.js +37 -1
- package/addon/routes/connectivity/devices/index/details/sensors.js +35 -0
- package/addon/routes/connectivity/devices/index/details/vehicle.js +29 -0
- package/addon/routes/connectivity/devices/index.js +7 -0
- package/addon/routes/connectivity/events/details.js +3 -0
- package/addon/routes/connectivity/events/index.js +6 -2
- package/addon/routes/connectivity/sensors/index.js +7 -2
- package/addon/routes/connectivity/telematics/details/attachments.js +72 -9
- package/addon/routes/connectivity/telematics/details/devices.js +6 -0
- package/addon/routes/connectivity/telematics/details/sensors.js +1 -0
- package/addon/routes/connectivity/telematics/details.js +1 -1
- package/addon/routes/connectivity/telematics/edit.js +1 -1
- package/addon/routes/maintenance/work-orders/index.js +1 -0
- package/addon/routes.js +2 -0
- package/addon/services/device-actions.js +30 -0
- package/addon/services/device-event-actions.js +1 -1
- package/addon/services/equipment-actions.js +1 -0
- package/addon/services/order-creation.js +54 -1
- package/addon/services/order-validation.js +3 -2
- package/addon/services/sensor-actions.js +3 -0
- package/addon/services/service-rate-actions.js +40 -1
- package/addon/services/vehicle-actions.js +24 -12
- package/addon/services/vendor-actions.js +3 -0
- package/addon/styles/fleetops-engine.css +28 -4
- package/addon/templates/connectivity/devices/index/details/events.hbs +85 -1
- package/addon/templates/connectivity/devices/index/details/sensors.hbs +73 -0
- package/addon/templates/connectivity/devices/index/details/vehicle.hbs +147 -0
- package/addon/templates/connectivity/telematics/details/attachments.hbs +198 -121
- package/addon/templates/connectivity/telematics/details/devices.hbs +4 -1
- package/addon/templates/connectivity/telematics/details/events.hbs +4 -1
- package/addon/templates/connectivity/telematics/details/sensors.hbs +3 -0
- package/addon/templates/management/vehicles/index/edit.hbs +1 -1
- package/addon/templates/management/vendors/index/details.hbs +2 -2
- package/addon/templates/settings/notifications.hbs +2 -1
- package/addon/templates/settings/routing.hbs +1 -0
- package/addon/utils/device-table-columns.js +288 -0
- package/addon/utils/fleet-ops-options.js +38 -0
- package/addon/utils/identity-cell-resource.js +20 -0
- package/addon/utils/map-drawer-dropdown-position.js +47 -0
- package/addon/utils/trackable-option.js +93 -0
- package/app/components/cell/attached-vehicle.js +1 -0
- package/app/components/cell/device-identity.js +1 -0
- package/app/components/cell/driver-identity.js +1 -0
- package/app/components/cell/equipment-identity.js +1 -0
- package/app/components/cell/part-identity.js +1 -0
- package/app/components/cell/telematic-device.js +1 -0
- package/app/components/cell/vehicle-identity.js +1 -0
- package/app/components/device/panel-tabs/events.hbs +30 -0
- package/app/components/device/panel-tabs/events.js +128 -0
- package/app/components/device/panel-tabs/sensors.hbs +30 -0
- package/app/components/device/panel-tabs/sensors.js +93 -0
- package/app/components/device/panel-tabs/vehicle.hbs +68 -0
- package/app/components/device/panel-tabs/vehicle.js +90 -0
- package/app/components/order/form/orchestrator-constraints.js +1 -0
- package/app/components/table/cell/dropdown/action-item.js +1 -0
- package/app/components/table/cell/dropdown.js +1 -0
- package/app/components/vendor/panel-header.js +1 -0
- package/app/controllers/connectivity/devices/index/details/sensors.js +1 -0
- package/app/controllers/connectivity/devices/index/details/vehicle.js +1 -0
- package/app/controllers/connectivity/events/{index/details.js → details.js} +1 -1
- package/app/routes/connectivity/devices/index/details/sensors.js +1 -0
- package/app/routes/connectivity/devices/index/details/vehicle.js +1 -0
- package/app/routes/connectivity/events/{index/details.js → details.js} +1 -1
- package/app/templates/connectivity/devices/index/details/sensors.js +1 -0
- package/app/templates/connectivity/devices/index/details/vehicle.js +1 -0
- package/app/templates/connectivity/events/{index/details.js → details.js} +1 -1
- package/app/utils/map-drawer-dropdown-position.js +1 -0
- package/app/utils/trackable-option.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/migrations/2025_08_28_054930_create_work_orders_table.php +1 -0
- package/server/migrations/2026_06_18_000001_add_category_to_work_orders_table.php +32 -0
- package/server/seeders/Testing/MaintenanceSeeder.php +5 -4
- package/server/src/Console/Commands/ProcessMaintenanceTriggers.php +1 -0
- package/server/src/Console/Commands/SyncTelematics.php +89 -0
- package/server/src/Exceptions/TelematicProviderException.php +13 -2
- package/server/src/Http/Controllers/Api/v1/OrderController.php +6 -21
- package/server/src/Http/Controllers/Internal/v1/DeviceController.php +55 -1
- package/server/src/Http/Controllers/Internal/v1/DeviceEventController.php +17 -6
- package/server/src/Http/Controllers/Internal/v1/FleetController.php +9 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +178 -1
- package/server/src/Http/Controllers/Internal/v1/MaintenanceScheduleController.php +1 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +4 -32
- package/server/src/Http/Controllers/Internal/v1/SearchController.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +4 -4
- package/server/src/Http/Controllers/Internal/v1/ServiceRateController.php +82 -13
- package/server/src/Http/Filter/DeviceEventFilter.php +65 -0
- package/server/src/Http/Filter/DeviceFilter.php +80 -0
- package/server/src/Http/Filter/SensorFilter.php +125 -0
- package/server/src/Http/Filter/VehicleFilter.php +13 -0
- package/server/src/Http/Requests/CreateDriverRequest.php +14 -13
- package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -0
- package/server/src/Http/Resources/v1/Driver.php +11 -2
- package/server/src/Http/Resources/v1/Index/Vehicle.php +19 -0
- package/server/src/Http/Resources/v1/WorkOrder.php +1 -0
- package/server/src/Jobs/FinalizeApiOrderCreation.php +47 -0
- package/server/src/Jobs/FinalizeInternalOrderCreation.php +35 -0
- package/server/src/Jobs/NotifyBulkAssignedDriver.php +47 -0
- package/server/src/Jobs/SyncTelematicDevicesJob.php +180 -123
- package/server/src/Models/Device.php +17 -1
- package/server/src/Models/DeviceEvent.php +82 -1
- package/server/src/Models/Driver.php +16 -0
- package/server/src/Models/Equipment.php +55 -0
- package/server/src/Models/Sensor.php +15 -2
- package/server/src/Models/Telematic.php +1 -1
- package/server/src/Models/Vehicle.php +5 -1
- package/server/src/Models/WorkOrder.php +5 -2
- package/server/src/Observers/DriverObserver.php +3 -3
- package/server/src/Observers/FleetObserver.php +23 -0
- package/server/src/Observers/VehicleObserver.php +3 -3
- package/server/src/Providers/FleetOpsServiceProvider.php +2 -0
- package/server/src/Support/LiveCacheService.php +1 -1
- package/server/src/Support/Telematics/Providers/AfaqyProvider.php +143 -20
- package/server/src/Support/Telematics/Providers/FlespiProvider.php +89 -15
- package/server/src/Support/Telematics/Providers/GeotabProvider.php +123 -35
- package/server/src/Support/Telematics/Providers/SafeeProvider.php +70 -5
- package/server/src/Support/Telematics/Providers/SamsaraProvider.php +122 -14
- package/server/src/Support/Telematics/TelematicService.php +330 -30
- package/server/src/routes.php +1 -1
- package/server/tests/DeviceFilterTest.php +45 -0
- package/server/tests/DriverVehicleStatusDefaultTest.php +19 -2
- package/server/tests/EquipmentAssignmentMorphTypeTest.php +35 -0
- package/server/tests/OperationsMonitorEndpointTest.php +38 -0
- package/server/tests/OrderQueuedClosureRegressionTest.php +36 -0
- package/server/tests/ServiceRateRouteValidationTest.php +101 -0
- package/server/tests/TelematicsHardeningTest.php +598 -6
- package/server/tests/VehicleDriverAssignmentTest.php +27 -0
- package/translations/en-us.yaml +1 -0
- package/addon/controllers/connectivity/events/index/details.js +0 -3
- package/addon/routes/connectivity/events/index/details.js +0 -3
- /package/addon/templates/connectivity/events/{index/details.hbs → details.hbs} +0 -0
|
@@ -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
|
+
{--exclude-webhook-providers : Skip 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
|
+
$excludeWebhookProviders = (bool) $this->option('exclude-webhook-providers');
|
|
72
|
+
|
|
73
|
+
return $registry->all()
|
|
74
|
+
->filter(function ($descriptor) use ($requestedProviders, $excludeWebhookProviders) {
|
|
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 !$excludeWebhookProviders || !$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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
$
|
|
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,6 +5,7 @@ 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;
|
|
10
11
|
use Illuminate\Support\Facades\Log;
|
|
@@ -27,6 +28,7 @@ class DeviceController extends FleetOpsController
|
|
|
27
28
|
public static function onQueryRecord($query, $request): void
|
|
28
29
|
{
|
|
29
30
|
$query->with(['telematic', 'warranty', 'attachable']);
|
|
31
|
+
$query->withCount('sensors');
|
|
30
32
|
|
|
31
33
|
if ($request->filled('attachment_state')) {
|
|
32
34
|
match ($request->input('attachment_state')) {
|
|
@@ -37,12 +39,41 @@ class DeviceController extends FleetOpsController
|
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
if ($request->filled('vehicle')) {
|
|
40
|
-
$query
|
|
42
|
+
static::applyVehicleFilter($query, $request->input('vehicle'));
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
if ($request->filled('device_id')) {
|
|
44
46
|
$query->where('device_id', 'like', '%' . $request->input('device_id') . '%');
|
|
45
47
|
}
|
|
48
|
+
|
|
49
|
+
if ($request->filled('serial_number')) {
|
|
50
|
+
$query->where('serial_number', 'like', '%' . $request->input('serial_number') . '%');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if ($request->filled('connection_status')) {
|
|
54
|
+
$statuses = Utils::arrayFrom($request->input('connection_status'));
|
|
55
|
+
|
|
56
|
+
$query->where(function ($statusQuery) use ($statuses) {
|
|
57
|
+
foreach ($statuses as $status) {
|
|
58
|
+
match ($status) {
|
|
59
|
+
'online' => $statusQuery->orWhere('last_online_at', '>=', now()->subMinutes(10)),
|
|
60
|
+
'recently_offline' => $statusQuery->orWhereBetween('last_online_at', [now()->subMinutes(60), now()->subMinutes(10)]),
|
|
61
|
+
'offline' => $statusQuery->orWhereBetween('last_online_at', [now()->subDay(), now()->subMinutes(60)]),
|
|
62
|
+
'long_offline' => $statusQuery->orWhere('last_online_at', '<', now()->subDay()),
|
|
63
|
+
'never_connected' => $statusQuery->orWhereNull('last_online_at'),
|
|
64
|
+
default => null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if ($request->filled('last_online_at')) {
|
|
71
|
+
static::applyDateFilter($query, 'last_online_at', $request->input('last_online_at'));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if ($request->filled('updated_at')) {
|
|
75
|
+
static::applyDateFilter($query, 'updated_at', $request->input('updated_at'));
|
|
76
|
+
}
|
|
46
77
|
}
|
|
47
78
|
|
|
48
79
|
/**
|
|
@@ -54,6 +85,7 @@ class DeviceController extends FleetOpsController
|
|
|
54
85
|
public static function onFindRecord($query, $request): void
|
|
55
86
|
{
|
|
56
87
|
$query->with(['telematic', 'warranty', 'attachable']);
|
|
88
|
+
$query->withCount('sensors');
|
|
57
89
|
}
|
|
58
90
|
|
|
59
91
|
/**
|
|
@@ -146,6 +178,28 @@ class DeviceController extends FleetOpsController
|
|
|
146
178
|
->first();
|
|
147
179
|
}
|
|
148
180
|
|
|
181
|
+
protected static function applyDateFilter($query, string $column, string|array $value): void
|
|
182
|
+
{
|
|
183
|
+
$dates = Utils::dateRange($value);
|
|
184
|
+
|
|
185
|
+
if (is_array($dates)) {
|
|
186
|
+
$query->whereBetween($column, $dates);
|
|
187
|
+
} else {
|
|
188
|
+
$query->whereDate($column, $dates);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
protected static function applyVehicleFilter($query, string $vehicle): void
|
|
193
|
+
{
|
|
194
|
+
$query->where(function ($vehicleQuery) use ($vehicle) {
|
|
195
|
+
$vehicleQuery->where('attachable_uuid', $vehicle)
|
|
196
|
+
->orWhereIn('attachable_uuid', Vehicle::query()
|
|
197
|
+
->where('company_uuid', session('company'))
|
|
198
|
+
->where('public_id', $vehicle)
|
|
199
|
+
->pluck('uuid'));
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
149
203
|
protected function logDeviceAttachmentLookupFailure(string $action, string $missingResource, string $deviceId, ?string $vehicleId): void
|
|
150
204
|
{
|
|
151
205
|
Log::warning('Device attachment lookup failed', [
|
|
@@ -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
|
|
@@ -23,7 +24,7 @@ class DeviceEventController extends FleetOpsController
|
|
|
23
24
|
*/
|
|
24
25
|
public static function onQueryRecord($query, $request): void
|
|
25
26
|
{
|
|
26
|
-
$query->with(['device']);
|
|
27
|
+
$query->with(['device.telematic']);
|
|
27
28
|
|
|
28
29
|
if ($request->filled('telematic')) {
|
|
29
30
|
$query->whereHas('device', function ($deviceQuery) use ($request) {
|
|
@@ -32,11 +33,21 @@ class DeviceEventController extends FleetOpsController
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
if ($request->filled('processed')) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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,
|
|
@@ -8,12 +8,16 @@ use Fleetbase\FleetOps\Http\Resources\v1\Index\Order as OrderIndexResource;
|
|
|
8
8
|
use Fleetbase\FleetOps\Http\Resources\v1\Index\Place as PlaceIndexResource;
|
|
9
9
|
use Fleetbase\FleetOps\Http\Resources\v1\Index\Vehicle as VehicleIndexResource;
|
|
10
10
|
use Fleetbase\FleetOps\Models\Driver;
|
|
11
|
+
use Fleetbase\FleetOps\Models\Fleet;
|
|
12
|
+
use Fleetbase\FleetOps\Models\FleetDriver;
|
|
13
|
+
use Fleetbase\FleetOps\Models\FleetVehicle;
|
|
11
14
|
use Fleetbase\FleetOps\Models\Order;
|
|
12
15
|
use Fleetbase\FleetOps\Models\Place;
|
|
13
16
|
use Fleetbase\FleetOps\Models\Route;
|
|
14
17
|
use Fleetbase\FleetOps\Models\Vehicle;
|
|
15
18
|
use Fleetbase\FleetOps\Support\LiveCacheService;
|
|
16
19
|
use Fleetbase\FleetOps\Support\LiveOrderQuery;
|
|
20
|
+
use Fleetbase\FleetOps\Support\Utils;
|
|
17
21
|
use Fleetbase\Http\Controllers\Controller;
|
|
18
22
|
use Illuminate\Http\Request;
|
|
19
23
|
|
|
@@ -144,7 +148,7 @@ class LiveController extends Controller
|
|
|
144
148
|
|
|
145
149
|
return LiveCacheService::remember('drivers', $cacheParams, function () use ($bounds, $limit) {
|
|
146
150
|
$query = Driver::where(['company_uuid' => session('company')])
|
|
147
|
-
->with(['user', 'vehicle'])
|
|
151
|
+
->with(['user', 'vehicle.devices'])
|
|
148
152
|
->applyDirectivesForPermissions('fleet-ops list driver');
|
|
149
153
|
|
|
150
154
|
$this->applyLiveLocationGuards($query);
|
|
@@ -186,6 +190,179 @@ class LiveController extends Controller
|
|
|
186
190
|
});
|
|
187
191
|
}
|
|
188
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Get the complete resource snapshot used by the operations sidebar monitor.
|
|
195
|
+
*
|
|
196
|
+
* @return array
|
|
197
|
+
*/
|
|
198
|
+
public function operationsMonitor()
|
|
199
|
+
{
|
|
200
|
+
return LiveCacheService::remember('operations-monitor', [], function () {
|
|
201
|
+
$drivers = Driver::where(['company_uuid' => session('company')])
|
|
202
|
+
->with(['user', 'vehicle'])
|
|
203
|
+
->applyDirectivesForPermissions('fleet-ops list driver')
|
|
204
|
+
->orderBy('id')
|
|
205
|
+
->get();
|
|
206
|
+
|
|
207
|
+
$vehicles = Vehicle::where(['company_uuid' => session('company')])
|
|
208
|
+
->with(['driver'])
|
|
209
|
+
->applyDirectivesForPermissions('fleet-ops list vehicle')
|
|
210
|
+
->orderBy('id')
|
|
211
|
+
->get();
|
|
212
|
+
|
|
213
|
+
$fleets = Fleet::where(['company_uuid' => session('company')])
|
|
214
|
+
->applyDirectivesForPermissions('fleet-ops list fleet')
|
|
215
|
+
->orderBy('name')
|
|
216
|
+
->orderBy('id')
|
|
217
|
+
->get();
|
|
218
|
+
|
|
219
|
+
$driverIdsByUuid = $drivers->pluck('uuid', 'uuid');
|
|
220
|
+
$vehicleIdsByUuid = $vehicles->pluck('uuid', 'uuid');
|
|
221
|
+
$onlineDriverUuids = $drivers->where('online', true)->pluck('uuid')->flip();
|
|
222
|
+
$onlineVehicleUuids = $vehicles->where('online', true)->pluck('uuid')->flip();
|
|
223
|
+
$fleetUuids = $fleets->pluck('uuid');
|
|
224
|
+
|
|
225
|
+
$driverMemberships = FleetDriver::whereIn('fleet_uuid', $fleetUuids)
|
|
226
|
+
->whereIn('driver_uuid', $driverIdsByUuid->keys())
|
|
227
|
+
->get()
|
|
228
|
+
->groupBy('fleet_uuid');
|
|
229
|
+
|
|
230
|
+
$vehicleMemberships = FleetVehicle::whereIn('fleet_uuid', $fleetUuids)
|
|
231
|
+
->whereIn('vehicle_uuid', $vehicleIdsByUuid->keys())
|
|
232
|
+
->get()
|
|
233
|
+
->groupBy('fleet_uuid');
|
|
234
|
+
|
|
235
|
+
$fleetNodes = $fleets->mapWithKeys(function (Fleet $fleet) use ($driverMemberships, $vehicleMemberships, $driverIdsByUuid, $vehicleIdsByUuid, $onlineDriverUuids, $onlineVehicleUuids) {
|
|
236
|
+
$fleetDriverUuids = $driverMemberships->get($fleet->uuid, collect())->pluck('driver_uuid')->unique()->values();
|
|
237
|
+
$fleetVehicleUuids = $vehicleMemberships->get($fleet->uuid, collect())->pluck('vehicle_uuid')->unique()->values();
|
|
238
|
+
$driverIds = $fleetDriverUuids->map(fn ($uuid) => $driverIdsByUuid->get($uuid))->filter()->values();
|
|
239
|
+
$vehicleIds = $fleetVehicleUuids->map(fn ($uuid) => $vehicleIdsByUuid->get($uuid))->filter()->values();
|
|
240
|
+
|
|
241
|
+
return [
|
|
242
|
+
$fleet->uuid => [
|
|
243
|
+
'id' => $fleet->uuid,
|
|
244
|
+
'uuid' => $fleet->uuid,
|
|
245
|
+
'public_id' => $fleet->public_id,
|
|
246
|
+
'name' => $fleet->name,
|
|
247
|
+
'task' => $fleet->task,
|
|
248
|
+
'status' => $fleet->status,
|
|
249
|
+
'slug' => $fleet->slug,
|
|
250
|
+
'parent_fleet_uuid' => $fleet->parent_fleet_uuid,
|
|
251
|
+
'drivers_count' => $driverIds->count(),
|
|
252
|
+
'drivers_online_count' => $fleetDriverUuids->filter(fn ($uuid) => $onlineDriverUuids->has($uuid))->count(),
|
|
253
|
+
'vehicles_count' => $vehicleIds->count(),
|
|
254
|
+
'vehicles_online_count' => $fleetVehicleUuids->filter(fn ($uuid) => $onlineVehicleUuids->has($uuid))->count(),
|
|
255
|
+
'driver_ids' => $driverIds->all(),
|
|
256
|
+
'vehicle_ids' => $vehicleIds->all(),
|
|
257
|
+
'subfleets' => [],
|
|
258
|
+
'updated_at' => $fleet->updated_at,
|
|
259
|
+
'created_at' => $fleet->created_at,
|
|
260
|
+
],
|
|
261
|
+
];
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
return [
|
|
265
|
+
'drivers' => $drivers->map(fn (Driver $driver) => $this->serializeMonitorDriver($driver))->values()->all(),
|
|
266
|
+
'vehicles' => $vehicles->map(fn (Vehicle $vehicle) => $this->serializeMonitorVehicle($vehicle))->values()->all(),
|
|
267
|
+
'fleets' => $this->buildOperationsMonitorFleetTree($fleetNodes),
|
|
268
|
+
'meta' => [
|
|
269
|
+
'generated_at' => now()->toISOString(),
|
|
270
|
+
'ttl' => LiveCacheService::DEFAULT_TTL,
|
|
271
|
+
'drivers_count' => $drivers->count(),
|
|
272
|
+
'vehicles_count' => $vehicles->count(),
|
|
273
|
+
'fleets_count' => $fleets->count(),
|
|
274
|
+
],
|
|
275
|
+
];
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
protected function serializeMonitorDriver(Driver $driver): array
|
|
280
|
+
{
|
|
281
|
+
return [
|
|
282
|
+
'id' => $driver->uuid,
|
|
283
|
+
'uuid' => $driver->uuid,
|
|
284
|
+
'public_id' => $driver->public_id,
|
|
285
|
+
'company_uuid' => $driver->company_uuid,
|
|
286
|
+
'user_uuid' => $driver->user_uuid,
|
|
287
|
+
'vehicle_uuid' => $driver->vehicle_uuid,
|
|
288
|
+
'vendor_uuid' => $driver->vendor_uuid,
|
|
289
|
+
'current_job_uuid' => $driver->current_job_uuid,
|
|
290
|
+
'name' => $driver->name,
|
|
291
|
+
'email' => $driver->email,
|
|
292
|
+
'phone' => $driver->phone,
|
|
293
|
+
'photo_url' => $driver->photo_url,
|
|
294
|
+
'avatar_url' => $driver->photo_url,
|
|
295
|
+
'vehicle_name' => $driver->vehicle_name,
|
|
296
|
+
'status' => $driver->status,
|
|
297
|
+
'location' => Utils::castPoint($driver->location),
|
|
298
|
+
'heading' => (int) data_get($driver, 'heading', 0),
|
|
299
|
+
'altitude' => (int) data_get($driver, 'altitude', 0),
|
|
300
|
+
'speed' => (int) data_get($driver, 'speed', 0),
|
|
301
|
+
'online' => (bool) data_get($driver, 'online', false),
|
|
302
|
+
'assigned_orders_count' => null,
|
|
303
|
+
'meta' => [
|
|
304
|
+
'_index_resource' => true,
|
|
305
|
+
],
|
|
306
|
+
'updated_at' => $driver->updated_at,
|
|
307
|
+
'created_at' => $driver->created_at,
|
|
308
|
+
];
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
protected function serializeMonitorVehicle(Vehicle $vehicle): array
|
|
312
|
+
{
|
|
313
|
+
return [
|
|
314
|
+
'id' => $vehicle->uuid,
|
|
315
|
+
'uuid' => $vehicle->uuid,
|
|
316
|
+
'public_id' => $vehicle->public_id,
|
|
317
|
+
'company_uuid' => $vehicle->company_uuid,
|
|
318
|
+
'vendor_uuid' => $vehicle->vendor_uuid,
|
|
319
|
+
'photo_uuid' => $vehicle->photo_uuid,
|
|
320
|
+
'internal_id' => $vehicle->internal_id,
|
|
321
|
+
'name' => $vehicle->name,
|
|
322
|
+
'display_name' => $vehicle->display_name,
|
|
323
|
+
'driver_name' => $vehicle->driver_name,
|
|
324
|
+
'plate_number' => $vehicle->plate_number,
|
|
325
|
+
'serial_number' => $vehicle->serial_number,
|
|
326
|
+
'fuel_card_number' => $vehicle->fuel_card_number,
|
|
327
|
+
'vin' => $vehicle->vin,
|
|
328
|
+
'make' => $vehicle->make,
|
|
329
|
+
'model' => $vehicle->model,
|
|
330
|
+
'year' => $vehicle->year,
|
|
331
|
+
'photo_url' => $vehicle->photo_url,
|
|
332
|
+
'avatar_url' => $vehicle->avatar_url,
|
|
333
|
+
'status' => $vehicle->status,
|
|
334
|
+
'location' => Utils::castPoint($vehicle->location),
|
|
335
|
+
'heading' => (int) data_get($vehicle, 'heading', 0),
|
|
336
|
+
'altitude' => (int) data_get($vehicle, 'altitude', 0),
|
|
337
|
+
'speed' => (int) data_get($vehicle, 'speed', 0),
|
|
338
|
+
'online' => (bool) data_get($vehicle, 'online', false),
|
|
339
|
+
'assigned_orders_count' => null,
|
|
340
|
+
'meta' => [
|
|
341
|
+
'_index_resource' => true,
|
|
342
|
+
],
|
|
343
|
+
'updated_at' => $vehicle->updated_at,
|
|
344
|
+
'created_at' => $vehicle->created_at,
|
|
345
|
+
];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
protected function buildOperationsMonitorFleetTree($fleetNodes): array
|
|
349
|
+
{
|
|
350
|
+
$nodes = $fleetNodes->map(fn ($node) => $node)->all();
|
|
351
|
+
|
|
352
|
+
foreach ($nodes as $uuid => $node) {
|
|
353
|
+
$parentUuid = data_get($node, 'parent_fleet_uuid');
|
|
354
|
+
|
|
355
|
+
if ($parentUuid && isset($nodes[$parentUuid])) {
|
|
356
|
+
$nodes[$parentUuid]['subfleets'][] = &$nodes[$uuid];
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return collect($nodes)
|
|
361
|
+
->filter(fn ($node) => empty(data_get($node, 'parent_fleet_uuid')) || !isset($nodes[data_get($node, 'parent_fleet_uuid')]))
|
|
362
|
+
->values()
|
|
363
|
+
->all();
|
|
364
|
+
}
|
|
365
|
+
|
|
189
366
|
/**
|
|
190
367
|
* Get places based on filters for the current company.
|
|
191
368
|
*
|
|
@@ -102,6 +102,7 @@ class MaintenanceScheduleController extends FleetOpsController
|
|
|
102
102
|
'company_uuid' => $schedule->company_uuid,
|
|
103
103
|
'schedule_uuid' => $schedule->uuid,
|
|
104
104
|
'subject' => $schedule->name,
|
|
105
|
+
'category' => 'preventive_maintenance',
|
|
105
106
|
'status' => 'open',
|
|
106
107
|
'priority' => $schedule->default_priority ?? 'normal',
|
|
107
108
|
'target_type' => $schedule->subject_type,
|
|
@@ -6,7 +6,6 @@ use Fleetbase\Exceptions\FleetbaseRequestValidationException;
|
|
|
6
6
|
use Fleetbase\FleetOps\Events\EntityActivityChanged;
|
|
7
7
|
use Fleetbase\FleetOps\Events\EntityCompleted;
|
|
8
8
|
use Fleetbase\FleetOps\Events\OrderDispatchFailed;
|
|
9
|
-
use Fleetbase\FleetOps\Events\OrderReady;
|
|
10
9
|
use Fleetbase\FleetOps\Events\OrderStarted;
|
|
11
10
|
use Fleetbase\FleetOps\Events\WaypointActivityChanged;
|
|
12
11
|
use Fleetbase\FleetOps\Events\WaypointCompleted;
|
|
@@ -20,6 +19,8 @@ use Fleetbase\FleetOps\Http\Resources\v1\Index\Order as OrderIndexResource;
|
|
|
20
19
|
use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
|
|
21
20
|
use Fleetbase\FleetOps\Http\Resources\v1\Proof as ProofResource;
|
|
22
21
|
use Fleetbase\FleetOps\Imports\OrdersImport;
|
|
22
|
+
use Fleetbase\FleetOps\Jobs\FinalizeInternalOrderCreation;
|
|
23
|
+
use Fleetbase\FleetOps\Jobs\NotifyBulkAssignedDriver;
|
|
23
24
|
use Fleetbase\FleetOps\Models\Driver;
|
|
24
25
|
use Fleetbase\FleetOps\Models\Entity;
|
|
25
26
|
use Fleetbase\FleetOps\Models\Order;
|
|
@@ -210,14 +211,7 @@ class OrderController extends FleetOpsController
|
|
|
210
211
|
// if service quote attached purchase
|
|
211
212
|
$order->purchaseServiceQuote($serviceQuote);
|
|
212
213
|
|
|
213
|
-
|
|
214
|
-
dispatch(function () use ($order): void {
|
|
215
|
-
// notify driver if assigned
|
|
216
|
-
$order->notifyDriverAssigned();
|
|
217
|
-
|
|
218
|
-
// Trigger order created event
|
|
219
|
-
event(new OrderReady($order));
|
|
220
|
-
})->afterCommit();
|
|
214
|
+
FinalizeInternalOrderCreation::dispatch($order->uuid)->afterCommit();
|
|
221
215
|
}
|
|
222
216
|
);
|
|
223
217
|
|
|
@@ -527,29 +521,7 @@ class OrderController extends FleetOpsController
|
|
|
527
521
|
|
|
528
522
|
// Queue Per‑Order Notifications
|
|
529
523
|
if (!$request->boolean('silent')) {
|
|
530
|
-
dispatch(
|
|
531
|
-
// Re‑hydrate Driver To Avoid Serializing The Full Model
|
|
532
|
-
$driver = Driver::whereUuid($driver->uuid)->first();
|
|
533
|
-
|
|
534
|
-
// Stream Orders To Keep Memory Footprint Low
|
|
535
|
-
Order::whereIn('uuid', $orderUuids)
|
|
536
|
-
->cursor()
|
|
537
|
-
->each(function (Order $order) use ($driver): void {
|
|
538
|
-
// Synchronize In‑Memory Model
|
|
539
|
-
$order->setRelation('driverAssigned', $driver);
|
|
540
|
-
$order->driver_assigned_uuid = $driver->uuid;
|
|
541
|
-
|
|
542
|
-
try {
|
|
543
|
-
$order->notifyDriverAssigned();
|
|
544
|
-
} catch (\Throwable $e) {
|
|
545
|
-
logger()->warning(
|
|
546
|
-
'Failed notifying driver on order ' . $order->uuid,
|
|
547
|
-
['error' => $e->getMessage()]
|
|
548
|
-
);
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
})
|
|
552
|
-
->afterCommit();
|
|
524
|
+
NotifyBulkAssignedDriver::dispatch($orderUuids->all(), $driver->uuid)->afterCommit();
|
|
553
525
|
}
|
|
554
526
|
|
|
555
527
|
return response()->json([
|
|
@@ -332,9 +332,9 @@ class SearchController extends Controller
|
|
|
332
332
|
|
|
333
333
|
private function searchWorkOrders(string $query, int $limit): Collection
|
|
334
334
|
{
|
|
335
|
-
return $this->searchGeneric(WorkOrder::class, ['code', 'subject', 'instructions', 'status', 'priority', 'public_id', 'uuid'], $query, $limit, fn (WorkOrder $workOrder) => [
|
|
335
|
+
return $this->searchGeneric(WorkOrder::class, ['code', 'subject', 'category', 'instructions', 'status', 'priority', 'public_id', 'uuid'], $query, $limit, fn (WorkOrder $workOrder) => [
|
|
336
336
|
'label' => $workOrder->code ?: $workOrder->subject,
|
|
337
|
-
'description' => $this->description($workOrder->status, $workOrder->priority, $workOrder->subject),
|
|
337
|
+
'description' => $this->description($workOrder->status, $workOrder->priority, $workOrder->category ?: $workOrder->subject),
|
|
338
338
|
'icon' => 'clipboard-list',
|
|
339
339
|
'type' => 'Work Order',
|
|
340
340
|
'route' => 'console.fleet-ops.maintenance.work-orders.index.details',
|