@fleetbase/fleetops-engine 0.6.29 → 0.6.31
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/customer/create-order-form.hbs +1 -1
- package/addon/components/customer/order-form.hbs +34 -34
- package/addon/components/customer/orders.hbs +2 -2
- package/addon/components/display-place.hbs +1 -1
- package/addon/components/driver/form.js +5 -1
- package/addon/components/driver/pill.hbs +16 -17
- package/addon/components/driver/pill.js +5 -1
- package/addon/components/map/leaflet-live-map.js +35 -3
- package/addon/components/map/order-list-overlay/order.hbs +1 -0
- package/addon/components/map/order-list-overlay/order.js +42 -0
- package/addon/components/modals/bulk-assign-driver.hbs +2 -2
- package/addon/components/order/details/detail.hbs +6 -6
- package/addon/components/order/details/notes.js +1 -1
- package/addon/components/order/route-editor.hbs +3 -3
- package/addon/components/order-tracking-lookup.hbs +1 -1
- package/addon/components/service-rate/details.hbs +117 -75
- package/addon/components/service-rate/form.hbs +7 -4
- package/addon/components/service-rate/form.js +6 -0
- package/addon/components/vehicle/pill.hbs +32 -33
- package/addon/components/vehicle/pill.js +5 -1
- package/addon/controllers/operations/orders/index.js +1 -1
- package/addon/controllers/operations/scheduler/index.js +17 -2
- package/addon/controllers/operations/service-rates/index/edit.js +1 -7
- package/addon/controllers/operations/service-rates/index/new.js +0 -7
- package/addon/controllers/operations/service-rates/index.js +10 -2
- package/addon/routes/operations/orders/index/details.js +7 -0
- package/addon/routes/operations/scheduler/index.js +3 -3
- package/addon/services/driver-actions.js +20 -4
- package/addon/services/leaflet-routing-control.js +7 -1
- package/addon/services/order-list-overlay.js +0 -1
- package/addon/services/place-actions.js +20 -4
- package/addon/services/service-rate-actions.js +31 -0
- package/addon/services/vehicle-actions.js +20 -4
- package/addon/templates/operations/scheduler/index.hbs +2 -2
- package/addon/utils/create-full-calendar-event-from-order.js +6 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +4 -4
- package/server/migrations/2025_12_16_000001_add_subject_created_at_index_to_positions.php +40 -0
- package/server/migrations/2025_12_16_000003_add_performance_indexes_to_fleetops_core_tables.php +442 -0
- package/server/src/Console/Commands/DispatchAdhocOrders.php +7 -2
- package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +30 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +184 -86
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +14 -1
- package/server/src/Http/Controllers/Internal/v1/PlaceController.php +5 -0
- package/server/src/Http/Filter/DriverFilter.php +10 -0
- package/server/src/Http/Filter/OrderFilter.php +8 -1
- package/server/src/Http/Resources/v1/Contact.php +2 -2
- package/server/src/Http/Resources/v1/Entity.php +1 -1
- package/server/src/Http/Resources/v1/Index/Customer.php +33 -0
- package/server/src/Http/Resources/v1/Index/Driver.php +45 -0
- package/server/src/Http/Resources/v1/Index/Facilitator.php +33 -0
- package/server/src/Http/Resources/v1/Index/Order.php +127 -0
- package/server/src/Http/Resources/v1/Index/Payload.php +57 -0
- package/server/src/Http/Resources/v1/Index/Place.php +45 -0
- package/server/src/Http/Resources/v1/Index/TrackingNumber.php +25 -0
- package/server/src/Http/Resources/v1/Index/Vehicle.php +50 -0
- package/server/src/Http/Resources/v1/Order.php +41 -14
- package/server/src/Http/Resources/v1/Place.php +1 -1
- package/server/src/Http/Resources/v1/Position.php +2 -1
- package/server/src/Http/Resources/v1/ServiceRate.php +4 -4
- package/server/src/Http/Resources/v1/ServiceRateFee.php +12 -12
- package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +14 -7
- package/server/src/Http/Resources/v1/TrackingNumber.php +1 -1
- package/server/src/Http/Resources/v1/Waypoint.php +1 -1
- package/server/src/Listeners/HandleOrderDispatched.php +5 -0
- package/server/src/Models/Contact.php +2 -0
- package/server/src/Models/Device.php +2 -0
- package/server/src/Models/DeviceEvent.php +2 -0
- package/server/src/Models/Driver.php +2 -0
- package/server/src/Models/FuelReport.php +2 -0
- package/server/src/Models/Issue.php +2 -0
- package/server/src/Models/Order.php +12 -5
- package/server/src/Models/Place.php +2 -0
- package/server/src/Models/Position.php +2 -0
- package/server/src/Models/ServiceArea.php +2 -0
- package/server/src/Models/ServiceRate.php +5 -1
- package/server/src/Models/ServiceRateFee.php +3 -17
- package/server/src/Models/ServiceRateParcelFee.php +1 -12
- package/server/src/Models/Vehicle.php +2 -0
- package/server/src/Models/Vendor.php +2 -0
- package/server/src/Models/Zone.php +2 -0
- package/server/src/Observers/DriverObserver.php +23 -0
- package/server/src/Observers/OrderObserver.php +31 -0
- package/server/src/Observers/PlaceObserver.php +31 -0
- package/server/src/Observers/ServiceRateObserver.php +0 -18
- package/server/src/Observers/VehicleObserver.php +7 -0
- package/server/src/Support/LiveCacheService.php +165 -0
- package/server/src/Support/OSRM.php +49 -22
- package/server/src/Support/OrderTracker.php +100 -28
- package/translations/en-us.yaml +3 -1
|
@@ -30,7 +30,11 @@ export default class PlaceActionsService extends ResourceActionService {
|
|
|
30
30
|
place,
|
|
31
31
|
});
|
|
32
32
|
},
|
|
33
|
-
edit: (place) => {
|
|
33
|
+
edit: async (place) => {
|
|
34
|
+
if (place?.meta?._index_resource) {
|
|
35
|
+
await place.reload();
|
|
36
|
+
}
|
|
37
|
+
|
|
34
38
|
return this.resourceContextPanel.open({
|
|
35
39
|
content: 'place/form',
|
|
36
40
|
title: this.intl.t('common.edit-resource-name', { resourceName: place.address }),
|
|
@@ -40,7 +44,11 @@ export default class PlaceActionsService extends ResourceActionService {
|
|
|
40
44
|
place,
|
|
41
45
|
});
|
|
42
46
|
},
|
|
43
|
-
view: (place) => {
|
|
47
|
+
view: async (place) => {
|
|
48
|
+
if (place?.meta?._index_resource) {
|
|
49
|
+
await place.reload();
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
return this.resourceContextPanel.open({
|
|
45
53
|
place,
|
|
46
54
|
tabs: [
|
|
@@ -65,7 +73,11 @@ export default class PlaceActionsService extends ResourceActionService {
|
|
|
65
73
|
...options,
|
|
66
74
|
});
|
|
67
75
|
},
|
|
68
|
-
edit: (place, options = {}, saveOptions = {}) => {
|
|
76
|
+
edit: async (place, options = {}, saveOptions = {}) => {
|
|
77
|
+
if (place?.meta?._index_resource) {
|
|
78
|
+
await place.reload();
|
|
79
|
+
}
|
|
80
|
+
|
|
69
81
|
return this.modalsManager.show('modals/resource', {
|
|
70
82
|
resource: place,
|
|
71
83
|
title: this.intl.t('common.edit-resource-name', { resourceName: place.address }),
|
|
@@ -76,7 +88,11 @@ export default class PlaceActionsService extends ResourceActionService {
|
|
|
76
88
|
...options,
|
|
77
89
|
});
|
|
78
90
|
},
|
|
79
|
-
view: (place, options = {}) => {
|
|
91
|
+
view: async (place, options = {}) => {
|
|
92
|
+
if (place?.meta?._index_resource) {
|
|
93
|
+
await place.reload();
|
|
94
|
+
}
|
|
95
|
+
|
|
80
96
|
return this.modalsManager.show('modals/resource', {
|
|
81
97
|
resource: place,
|
|
82
98
|
title: place.displayName,
|
|
@@ -138,6 +138,37 @@ export default class ServiceRateActionsService extends ResourceActionService {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
generateFixedRateFees(serviceRate) {
|
|
142
|
+
if (!serviceRate.isFixedRate) return;
|
|
143
|
+
|
|
144
|
+
const maxDistance = Number(serviceRate.max_distance) || 0;
|
|
145
|
+
const existing = serviceRate.rate_fees.toArray();
|
|
146
|
+
const byDistance = new Map(existing.map((f) => [f.distance, f]));
|
|
147
|
+
|
|
148
|
+
// Remove fees beyond max_distance
|
|
149
|
+
existing.forEach((fee) => {
|
|
150
|
+
if (fee.distance >= maxDistance) {
|
|
151
|
+
serviceRate.rate_fees.removeObject(fee);
|
|
152
|
+
if (!fee.isNew) {
|
|
153
|
+
fee.deleteRecord();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Add missing fees
|
|
159
|
+
for (let d = 0; d < maxDistance; d++) {
|
|
160
|
+
if (!byDistance.has(d)) {
|
|
161
|
+
const fee = this.store.createRecord('service-rate-fee', {
|
|
162
|
+
distance: d,
|
|
163
|
+
distance_unit: serviceRate.max_distance_unit,
|
|
164
|
+
fee: 0,
|
|
165
|
+
currency: serviceRate.currency,
|
|
166
|
+
});
|
|
167
|
+
serviceRate.rate_fees.pushObject(fee);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
141
172
|
#getDefaultParcelFees() {
|
|
142
173
|
const defaults = [
|
|
143
174
|
{
|
|
@@ -29,7 +29,11 @@ export default class VehicleActionsService extends ResourceActionService {
|
|
|
29
29
|
...options,
|
|
30
30
|
});
|
|
31
31
|
},
|
|
32
|
-
edit: (vehicle, options = {}) => {
|
|
32
|
+
edit: async (vehicle, options = {}) => {
|
|
33
|
+
if (vehicle?.meta?._index_resource) {
|
|
34
|
+
await vehicle.reload();
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
return this.resourceContextPanel.open({
|
|
34
38
|
content: 'vehicle/form',
|
|
35
39
|
title: this.intl.t('common.edit-resource-name', { resourceName: vehicle.name }),
|
|
@@ -47,7 +51,11 @@ export default class VehicleActionsService extends ResourceActionService {
|
|
|
47
51
|
...options,
|
|
48
52
|
});
|
|
49
53
|
},
|
|
50
|
-
view: (vehicle, options = {}) => {
|
|
54
|
+
view: async (vehicle, options = {}) => {
|
|
55
|
+
if (vehicle?.meta?._index_resource) {
|
|
56
|
+
await vehicle.reload();
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
return this.resourceContextPanel.open({
|
|
52
60
|
vehicle,
|
|
53
61
|
header: 'vehicle/panel-header',
|
|
@@ -83,7 +91,11 @@ export default class VehicleActionsService extends ResourceActionService {
|
|
|
83
91
|
...options,
|
|
84
92
|
});
|
|
85
93
|
},
|
|
86
|
-
edit: (vehicle, options = {}, saveOptions = {}) => {
|
|
94
|
+
edit: async (vehicle, options = {}, saveOptions = {}) => {
|
|
95
|
+
if (vehicle?.meta?._index_resource) {
|
|
96
|
+
await vehicle.reload();
|
|
97
|
+
}
|
|
98
|
+
|
|
87
99
|
return this.modalsManager.show('modals/resource', {
|
|
88
100
|
resource: vehicle,
|
|
89
101
|
title: this.intl.t('common.edit-resource-name', { resourceName: vehicle.name }),
|
|
@@ -94,7 +106,11 @@ export default class VehicleActionsService extends ResourceActionService {
|
|
|
94
106
|
...options,
|
|
95
107
|
});
|
|
96
108
|
},
|
|
97
|
-
view: (vehicle, options = {}) => {
|
|
109
|
+
view: async (vehicle, options = {}) => {
|
|
110
|
+
if (vehicle?.meta?._index_resource) {
|
|
111
|
+
await vehicle.reload();
|
|
112
|
+
}
|
|
113
|
+
|
|
98
114
|
return this.modalsManager.show('modals/resource', {
|
|
99
115
|
resource: vehicle,
|
|
100
116
|
title: vehicle.name,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<Layout::Section::Header @title={{t "menu.scheduler"}}>
|
|
2
|
-
<div class="flex items-center gap-2">
|
|
2
|
+
{{!-- <div class="flex items-center gap-2">
|
|
3
3
|
<Button
|
|
4
4
|
@type={{if (eq this.viewMode "orders") "primary" "default"}}
|
|
5
5
|
@text="Orders"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
@size="sm"
|
|
24
24
|
/>
|
|
25
25
|
{{/if}}
|
|
26
|
-
</div>
|
|
26
|
+
</div> --}}
|
|
27
27
|
</Layout::Section::Header>
|
|
28
28
|
|
|
29
29
|
<Layout::Section::Body>
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { get } from '@ember/object';
|
|
2
2
|
|
|
3
3
|
export function createOrderEventTitle(order) {
|
|
4
|
+
return get(order, 'tracking') ?? get(order, 'public_id');
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function createOrderEventDescription(order) {
|
|
4
8
|
const scheduledAtTime = get(order, 'scheduledAtTime');
|
|
5
9
|
const driverAssignedName = get(order, 'driver_assigned.name');
|
|
6
10
|
const vehicleAssignedName = get(order, 'driver_assigned.vehicle_name');
|
|
@@ -23,7 +27,9 @@ export default function createFullCalendarEventFromOrder(order) {
|
|
|
23
27
|
return {
|
|
24
28
|
id: order.id,
|
|
25
29
|
title: createOrderEventTitle(order),
|
|
30
|
+
description: createOrderEventDescription(order),
|
|
26
31
|
start: order.scheduled_at,
|
|
32
|
+
displayEventTime: false,
|
|
27
33
|
allDay: true,
|
|
28
34
|
display: 'block',
|
|
29
35
|
};
|
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.31",
|
|
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.
|
|
46
|
-
"@fleetbase/ember-ui": "^0.3.
|
|
47
|
-
"@fleetbase/fleetops-data": "^0.1.
|
|
45
|
+
"@fleetbase/ember-core": "^0.3.9",
|
|
46
|
+
"@fleetbase/ember-ui": "^0.3.15",
|
|
47
|
+
"@fleetbase/fleetops-data": "^0.1.24",
|
|
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",
|
|
@@ -0,0 +1,40 @@
|
|
|
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 optimization: Add composite index on (subject_uuid, created_at)
|
|
12
|
+
* to dramatically improve query performance for the positions endpoint.
|
|
13
|
+
*
|
|
14
|
+
* This index supports queries like:
|
|
15
|
+
* SELECT * FROM positions WHERE subject_uuid = ? ORDER BY created_at DESC
|
|
16
|
+
*
|
|
17
|
+
* Expected performance improvement:
|
|
18
|
+
* - positions endpoint: 5605ms → 100-200ms (96-98% improvement)
|
|
19
|
+
*
|
|
20
|
+
* @return void
|
|
21
|
+
*/
|
|
22
|
+
public function up()
|
|
23
|
+
{
|
|
24
|
+
Schema::table('positions', function (Blueprint $table) {
|
|
25
|
+
$table->index(['subject_uuid', 'created_at'], 'positions_subject_created_at_index');
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Reverse the migrations.
|
|
31
|
+
*
|
|
32
|
+
* @return void
|
|
33
|
+
*/
|
|
34
|
+
public function down()
|
|
35
|
+
{
|
|
36
|
+
Schema::table('positions', function (Blueprint $table) {
|
|
37
|
+
$table->dropIndex('positions_subject_created_at_index');
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
};
|