@fleetbase/fleetops-engine 0.6.46 → 0.6.48
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 +71 -0
- package/addon/components/admin/routing-settings.js +124 -0
- package/addon/components/customer/orders.js +1 -1
- package/addon/components/display-place.hbs +1 -1
- package/addon/components/map/order-list-overlay/order.hbs +18 -3
- package/addon/components/map/toolbar.hbs +2 -2
- package/addon/components/map/toolbar.js +10 -2
- package/addon/components/orchestrator/phase-builder.hbs +28 -5
- package/addon/components/orchestrator/phase-builder.js +21 -1
- package/addon/components/orchestrator/resource-panel.hbs +19 -1
- package/addon/components/orchestrator/resource-panel.js +4 -0
- package/addon/components/orchestrator-workbench.js +3 -1
- package/addon/components/order/details/purchase-rate.hbs +19 -22
- package/addon/components/order/details/route.hbs +26 -1
- package/addon/components/order/details/route.js +50 -0
- package/addon/components/order/details/tracking.hbs +171 -27
- package/addon/components/order/details/tracking.js +457 -0
- package/addon/components/order/form/details.hbs +1 -2
- package/addon/components/order/form/details.js +6 -0
- package/addon/components/order/form/route.js +9 -1
- package/addon/components/order/kanban-card.hbs +18 -3
- package/addon/components/order-list-overlay/order.hbs +18 -3
- package/addon/components/order-progress-card.hbs +21 -6
- package/addon/components/order-tracking-lookup.hbs +7 -7
- package/addon/components/order-tracking-lookup.js +1 -1
- package/addon/components/route-list.hbs +78 -8
- package/addon/components/route-list.js +48 -6
- package/addon/components/tracking-stop-progress.hbs +45 -0
- package/addon/components/tracking-stop-progress.js +79 -0
- package/addon/controllers/settings/payments/index.js +1 -1
- package/addon/controllers/settings/routing.js +98 -1
- package/addon/helpers/format-duration.js +38 -0
- package/addon/routes/application.js +6 -0
- package/addon/services/order-list-overlay.js +2 -2
- package/addon/styles/fleetops-engine.css +733 -0
- package/addon/templates/settings/routing.hbs +60 -2
- package/app/components/tracking-stop-progress.js +1 -0
- package/app/helpers/format-duration.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +3 -3
- package/pnpm-workspace.yaml +7 -0
- package/server/config/fleetops.php +32 -11
- package/server/migrations/2026_05_13_000001_repair_customer_contact_user_types.php +86 -0
- package/server/seeders/VroomOrchestrationSeeder.php +402 -0
- package/server/src/Http/Controllers/Api/v1/OrchestrationController.php +64 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +26 -26
- package/server/src/Http/Controllers/Api/v1/PayloadController.php +10 -10
- package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +41 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +6 -42
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +69 -15
- package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +119 -12
- package/server/src/Http/Resources/v1/Index/Payload.php +2 -2
- package/server/src/Models/Contact.php +122 -13
- package/server/src/Models/Order.php +1 -1
- package/server/src/Models/Payload.php +8 -8
- package/server/src/Models/Place.php +0 -3
- package/server/src/Models/ServiceRate.php +1 -1
- package/server/src/Observers/ContactObserver.php +8 -0
- package/server/src/Orchestration/Engines/CapacityAllocationEngine.php +220 -0
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +330 -38
- package/server/src/Orchestration/Support/OrchestrationPayloadBuilder.php +259 -51
- package/server/src/Providers/FleetOpsServiceProvider.php +27 -0
- package/server/src/Support/LiveOrderQuery.php +75 -0
- package/server/src/Support/Metrics.php +15 -0
- package/server/src/Support/OSRM.php +11 -6
- package/server/src/Support/OrderTracker.php +7 -582
- package/server/src/Support/Utils.php +1 -1
- package/server/src/Tracking/Contracts/TrackingProviderInterface.php +19 -0
- package/server/src/Tracking/Providers/CalculatedTrackingProvider.php +65 -0
- package/server/src/Tracking/Providers/GoogleRoutesTrackingProvider.php +118 -0
- package/server/src/Tracking/Providers/OsrmTrackingProvider.php +71 -0
- package/server/src/Tracking/README.md +25 -0
- package/server/src/Tracking/Support/FakeTrackingProvider.php +42 -0
- package/server/src/Tracking/TrackingContext.php +63 -0
- package/server/src/Tracking/TrackingContextBuilder.php +204 -0
- package/server/src/Tracking/TrackingIntelligenceService.php +180 -0
- package/server/src/Tracking/TrackingOptions.php +49 -0
- package/server/src/Tracking/TrackingProviderCapabilities.php +30 -0
- package/server/src/Tracking/TrackingProviderManager.php +89 -0
- package/server/src/Tracking/TrackingProviderRegistry.php +35 -0
- package/server/src/Tracking/TrackingProviderResult.php +20 -0
- package/server/src/Tracking/TrackingStop.php +59 -0
- package/server/src/routes.php +11 -0
- package/server/tests/CapacityAllocationEngineTest.php +108 -0
- package/server/tests/LiveOrderQueryTest.php +34 -0
- package/server/tests/OrchestrationPayloadBuilderTest.php +132 -0
- package/server/tests/OrchestratorConsumableApiTest.php +74 -0
- package/server/tests/PingDriverEndpointTest.php +19 -0
- package/server/tests/TrackingIntelligenceTest.php +176 -0
- package/server/tests/VroomOrchestrationEngineTest.php +159 -0
- package/translations/en-us.yaml +4 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<Layout::Section::Header @title=
|
|
1
|
+
<Layout::Section::Header @title="FleetOps Routing & Tracking">
|
|
2
2
|
<Button
|
|
3
3
|
@type="primary"
|
|
4
4
|
@size="sm"
|
|
@@ -48,10 +48,68 @@
|
|
|
48
48
|
/>
|
|
49
49
|
</InputGroup>
|
|
50
50
|
</ContentPanel>
|
|
51
|
+
<ContentPanel @title="Tracking Intelligence" @open={{true}} @wrapperClass="bordered-classic">
|
|
52
|
+
<InputGroup @name="Tracking Provider" @helpText="Choose the provider used for live tracking intelligence and ETA calculations.">
|
|
53
|
+
<Select
|
|
54
|
+
@value={{this.trackingProvider}}
|
|
55
|
+
@options={{this.trackingProviderOptions}}
|
|
56
|
+
@optionLabel="label"
|
|
57
|
+
@optionValue="value"
|
|
58
|
+
@onSelect={{fn (mut this.trackingProvider)}}
|
|
59
|
+
@placeholder="Select tracking provider"
|
|
60
|
+
class="w-full"
|
|
61
|
+
/>
|
|
62
|
+
</InputGroup>
|
|
63
|
+
<InputGroup @name="Fallback Providers" @helpText="Providers used when the selected tracking provider is unavailable.">
|
|
64
|
+
<div class="fleetbase-model-select fleetbase-power-select ember-model-select">
|
|
65
|
+
<PowerSelectMultiple
|
|
66
|
+
@searchEnabled={{true}}
|
|
67
|
+
@options={{this.trackingProviderOptions}}
|
|
68
|
+
@selected={{this.selectedTrackingFallbackOptions}}
|
|
69
|
+
@onChange={{this.setTrackingFallbacks}}
|
|
70
|
+
@placeholder="Select fallback providers"
|
|
71
|
+
@triggerClass="form-select form-input flex-1"
|
|
72
|
+
as |provider|
|
|
73
|
+
>
|
|
74
|
+
{{provider.label}}
|
|
75
|
+
</PowerSelectMultiple>
|
|
76
|
+
</div>
|
|
77
|
+
</InputGroup>
|
|
78
|
+
<div class="flex justify-end">
|
|
79
|
+
<Button
|
|
80
|
+
@type="default"
|
|
81
|
+
@size="xs"
|
|
82
|
+
@icon={{if this.showTrackingAdvancedSettings "chevron-up" "chevron-down"}}
|
|
83
|
+
@text="Advanced Settings"
|
|
84
|
+
@onClick={{this.toggleTrackingAdvancedSettings}}
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
{{#if this.showTrackingAdvancedSettings}}
|
|
88
|
+
<div class="mt-2 space-y-4 rounded-md border border-gray-200 bg-gray-50 p-3 dark:border-gray-700 dark:bg-gray-800">
|
|
89
|
+
<InputGroup @name="Traffic-Aware ETA" @helpText="Use provider traffic data when supported.">
|
|
90
|
+
<Toggle @isToggled={{this.trackingTrafficEnabled}} @onToggle={{fn (mut this.trackingTrafficEnabled)}} />
|
|
91
|
+
</InputGroup>
|
|
92
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
93
|
+
<InputGroup @name="Summary Cache TTL" @helpText="Seconds to cache the final tracking summary.">
|
|
94
|
+
<Input @type="number" @value={{this.trackingCacheTtlSeconds}} min="15" max="300" class="form-input w-full" />
|
|
95
|
+
</InputGroup>
|
|
96
|
+
<InputGroup @name="Route Cache TTL" @helpText="Seconds to cache provider route responses.">
|
|
97
|
+
<Input @type="number" @value={{this.trackingRouteCacheTtlSeconds}} min="60" max="1800" class="form-input w-full" />
|
|
98
|
+
</InputGroup>
|
|
99
|
+
<InputGroup @name="Stale Location Threshold" @helpText="Seconds before driver location is marked stale.">
|
|
100
|
+
<Input @type="number" @value={{this.trackingStaleLocationThresholdSeconds}} min="30" max="3600" class="form-input w-full" />
|
|
101
|
+
</InputGroup>
|
|
102
|
+
<InputGroup @name="Fallback Speed" @helpText="Kilometers per hour used by the calculated provider.">
|
|
103
|
+
<Input @type="number" @value={{this.trackingDefaultVehicleSpeedKph}} min="1" max="160" class="form-input w-full" />
|
|
104
|
+
</InputGroup>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
{{/if}}
|
|
108
|
+
</ContentPanel>
|
|
51
109
|
<RegistryYield @registry="fleet-ops:template:settings:routing" as |RegistryComponent|>
|
|
52
110
|
<RegistryComponent @controller={{this}} />
|
|
53
111
|
</RegistryYield>
|
|
54
112
|
</div>
|
|
55
113
|
</div>
|
|
56
114
|
<Spacer @height="600px" />
|
|
57
|
-
</Layout::Section::Body>
|
|
115
|
+
</Layout::Section::Body>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/fleetops-engine/components/tracking-stop-progress';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, formatDurationValue } from '@fleetbase/fleetops-engine/helpers/format-duration';
|
package/composer.json
CHANGED
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetbase/fleetops-engine",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.48",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops"
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@babel/core": "^7.23.2",
|
|
45
|
-
"@fleetbase/ember-core": "^0.3.
|
|
45
|
+
"@fleetbase/ember-core": "^0.3.19",
|
|
46
46
|
"@fleetbase/ember-ui": "^0.3.29",
|
|
47
|
-
"@fleetbase/fleetops-data": "^0.1.
|
|
47
|
+
"@fleetbase/fleetops-data": "^0.1.32",
|
|
48
48
|
"@fleetbase/leaflet-routing-machine": "^3.2.17",
|
|
49
49
|
"@fortawesome/ember-fontawesome": "^2.0.0",
|
|
50
50
|
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* -------------------------------------------
|
|
5
5
|
* FleetOps API Configuration
|
|
6
|
-
*
|
|
6
|
+
* -------------------------------------------.
|
|
7
7
|
*/
|
|
8
8
|
return [
|
|
9
9
|
/*
|
|
@@ -14,17 +14,17 @@ return [
|
|
|
14
14
|
'api' => [
|
|
15
15
|
'version' => '0.0.1',
|
|
16
16
|
'routing' => [
|
|
17
|
-
'prefix'
|
|
18
|
-
'internal_prefix' => 'int'
|
|
19
|
-
]
|
|
17
|
+
'prefix' => null,
|
|
18
|
+
'internal_prefix' => 'int',
|
|
19
|
+
],
|
|
20
20
|
],
|
|
21
21
|
'connection' => [
|
|
22
|
-
'db' => env('DB_CONNECTION', 'mysql')
|
|
22
|
+
'db' => env('DB_CONNECTION', 'mysql'),
|
|
23
23
|
],
|
|
24
24
|
|
|
25
25
|
/*
|
|
26
26
|
|--------------------------------------------------------------------------
|
|
27
|
-
| Facilitator Fee - This is a percentage fee the system admin takes when
|
|
27
|
+
| Facilitator Fee - This is a percentage fee the system admin takes when
|
|
28
28
|
| facilitating any payments in the system.
|
|
29
29
|
| Example: if `10` then 10% fee will be taken on all payments.
|
|
30
30
|
|--------------------------------------------------------------------------
|
|
@@ -37,7 +37,7 @@ return [
|
|
|
37
37
|
|--------------------------------------------------------------------------
|
|
38
38
|
*/
|
|
39
39
|
'osrm' => [
|
|
40
|
-
'host' => env('OSRM_HOST', 'https://router.project-osrm.org')
|
|
40
|
+
'host' => env('OSRM_HOST', 'https://router.project-osrm.org'),
|
|
41
41
|
],
|
|
42
42
|
|
|
43
43
|
/*
|
|
@@ -61,12 +61,33 @@ return [
|
|
|
61
61
|
|
|
62
62
|
/*
|
|
63
63
|
|--------------------------------------------------------------------------
|
|
64
|
-
| Distance Matrix Calculator
|
|
64
|
+
| Distance Matrix Calculator
|
|
65
65
|
| Options: "calculate", "google", "osrm"
|
|
66
66
|
|--------------------------------------------------------------------------
|
|
67
67
|
*/
|
|
68
68
|
'distance_matrix' => [
|
|
69
|
-
'provider' => env('DISTANCE_MATRIX_PROVIDER', 'calculate')
|
|
69
|
+
'provider' => env('DISTANCE_MATRIX_PROVIDER', 'calculate'),
|
|
70
|
+
],
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
|--------------------------------------------------------------------------
|
|
74
|
+
| Order Tracking Intelligence
|
|
75
|
+
|--------------------------------------------------------------------------
|
|
76
|
+
|
|
|
77
|
+
| Provider-neutral tracking data for active orders. The provider registry
|
|
78
|
+
| can be extended by third-party packages without editing FleetOps core.
|
|
79
|
+
|
|
|
80
|
+
| Built-in providers: "google_routes", "osrm", "calculated"
|
|
81
|
+
|--------------------------------------------------------------------------
|
|
82
|
+
*/
|
|
83
|
+
'tracking' => [
|
|
84
|
+
'provider' => env('TRACKING_PROVIDER', 'google_routes'),
|
|
85
|
+
'fallbacks' => array_filter(explode(',', env('TRACKING_PROVIDER_FALLBACKS', 'osrm,calculated'))),
|
|
86
|
+
'traffic_enabled' => env('TRACKING_TRAFFIC_ENABLED', true),
|
|
87
|
+
'cache_ttl_seconds' => env('TRACKING_CACHE_TTL_SECONDS', 60),
|
|
88
|
+
'route_cache_ttl_seconds' => env('TRACKING_ROUTE_CACHE_TTL_SECONDS', 600),
|
|
89
|
+
'stale_location_threshold_seconds' => env('TRACKING_STALE_LOCATION_THRESHOLD_SECONDS', 300),
|
|
90
|
+
'default_vehicle_speed_kph' => env('TRACKING_DEFAULT_VEHICLE_SPEED_KPH', 35),
|
|
70
91
|
],
|
|
71
92
|
|
|
72
93
|
/*
|
|
@@ -76,7 +97,7 @@ return [
|
|
|
76
97
|
*/
|
|
77
98
|
'navigator' => [
|
|
78
99
|
'bypass_verification_code' => env('SMS_AUTH_BYPASS_CODE', env('NAVIGATOR_BYPASS_VERIFICATION_CODE')),
|
|
79
|
-
'app_identifier'
|
|
100
|
+
'app_identifier' => env('NAVIGATOR_APP_IDENTIFIER', 'io.fleetbase.navigator'),
|
|
80
101
|
],
|
|
81
102
|
|
|
82
103
|
/*
|
|
@@ -189,5 +210,5 @@ return [
|
|
|
189
210
|
|--------------------------------------------------------------------------
|
|
190
211
|
*/
|
|
191
212
|
'versions' => ['2020-09-30', '2024-03-12'],
|
|
192
|
-
'version'
|
|
213
|
+
'version' => '2024-03-12',
|
|
193
214
|
];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
use Fleetbase\FleetOps\Models\Contact;
|
|
4
|
+
use Fleetbase\Models\CompanyUser;
|
|
5
|
+
use Illuminate\Database\Migrations\Migration;
|
|
6
|
+
use Illuminate\Support\Facades\DB;
|
|
7
|
+
use Illuminate\Support\Facades\Schema;
|
|
8
|
+
|
|
9
|
+
return new class extends Migration {
|
|
10
|
+
/**
|
|
11
|
+
* Run the migrations.
|
|
12
|
+
*
|
|
13
|
+
* @return void
|
|
14
|
+
*/
|
|
15
|
+
public function up()
|
|
16
|
+
{
|
|
17
|
+
Contact::withoutGlobalScopes()
|
|
18
|
+
->where('type', 'customer')
|
|
19
|
+
->whereNull('deleted_at')
|
|
20
|
+
->chunkById(100, function ($contacts) {
|
|
21
|
+
foreach ($contacts as $contact) {
|
|
22
|
+
try {
|
|
23
|
+
$contact->repairCustomerTypeInvariant(true);
|
|
24
|
+
} catch (Throwable $e) {
|
|
25
|
+
// Skip ambiguous or unrecoverable records; runtime invariants handle new writes.
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if (!$this->canUseCustomerRoleHint()) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
DB::table('contacts')
|
|
35
|
+
->select('contacts.id')
|
|
36
|
+
->join('company_users', function ($join) {
|
|
37
|
+
$join->on('company_users.user_uuid', '=', 'contacts.user_uuid');
|
|
38
|
+
$join->on('company_users.company_uuid', '=', 'contacts.company_uuid');
|
|
39
|
+
})
|
|
40
|
+
->join('model_has_roles', function ($join) {
|
|
41
|
+
$join->on('model_has_roles.model_uuid', '=', 'company_users.uuid');
|
|
42
|
+
$join->where('model_has_roles.model_type', CompanyUser::class);
|
|
43
|
+
})
|
|
44
|
+
->join('roles', 'roles.id', '=', 'model_has_roles.role_id')
|
|
45
|
+
->where('roles.name', 'Fleet-Ops Customer')
|
|
46
|
+
->whereNull('contacts.deleted_at')
|
|
47
|
+
->where(function ($query) {
|
|
48
|
+
$query->whereNull('contacts.type');
|
|
49
|
+
$query->orWhere('contacts.type', '!=', 'customer');
|
|
50
|
+
})
|
|
51
|
+
->distinct()
|
|
52
|
+
->orderBy('contacts.id')
|
|
53
|
+
->chunk(100, function ($rows) {
|
|
54
|
+
foreach ($rows as $row) {
|
|
55
|
+
$contact = Contact::withoutGlobalScopes()->find($row->id);
|
|
56
|
+
if (!$contact) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
$contact->repairCustomerTypeInvariant(true);
|
|
62
|
+
} catch (Throwable $e) {
|
|
63
|
+
// Skip ambiguous or unrecoverable records; role is only a recovery hint.
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Reverse the migrations.
|
|
71
|
+
*
|
|
72
|
+
* @return void
|
|
73
|
+
*/
|
|
74
|
+
public function down()
|
|
75
|
+
{
|
|
76
|
+
// Data repair is intentionally not reversible.
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private function canUseCustomerRoleHint(): bool
|
|
80
|
+
{
|
|
81
|
+
return Schema::hasTable('contacts')
|
|
82
|
+
&& Schema::hasTable('company_users')
|
|
83
|
+
&& Schema::hasTable('model_has_roles')
|
|
84
|
+
&& Schema::hasTable('roles');
|
|
85
|
+
}
|
|
86
|
+
};
|