@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.
Files changed (92) hide show
  1. package/addon/components/customer/create-order-form.hbs +1 -1
  2. package/addon/components/customer/order-form.hbs +34 -34
  3. package/addon/components/customer/orders.hbs +2 -2
  4. package/addon/components/display-place.hbs +1 -1
  5. package/addon/components/driver/form.js +5 -1
  6. package/addon/components/driver/pill.hbs +16 -17
  7. package/addon/components/driver/pill.js +5 -1
  8. package/addon/components/map/leaflet-live-map.js +35 -3
  9. package/addon/components/map/order-list-overlay/order.hbs +1 -0
  10. package/addon/components/map/order-list-overlay/order.js +42 -0
  11. package/addon/components/modals/bulk-assign-driver.hbs +2 -2
  12. package/addon/components/order/details/detail.hbs +6 -6
  13. package/addon/components/order/details/notes.js +1 -1
  14. package/addon/components/order/route-editor.hbs +3 -3
  15. package/addon/components/order-tracking-lookup.hbs +1 -1
  16. package/addon/components/service-rate/details.hbs +117 -75
  17. package/addon/components/service-rate/form.hbs +7 -4
  18. package/addon/components/service-rate/form.js +6 -0
  19. package/addon/components/vehicle/pill.hbs +32 -33
  20. package/addon/components/vehicle/pill.js +5 -1
  21. package/addon/controllers/operations/orders/index.js +1 -1
  22. package/addon/controllers/operations/scheduler/index.js +17 -2
  23. package/addon/controllers/operations/service-rates/index/edit.js +1 -7
  24. package/addon/controllers/operations/service-rates/index/new.js +0 -7
  25. package/addon/controllers/operations/service-rates/index.js +10 -2
  26. package/addon/routes/operations/orders/index/details.js +7 -0
  27. package/addon/routes/operations/scheduler/index.js +3 -3
  28. package/addon/services/driver-actions.js +20 -4
  29. package/addon/services/leaflet-routing-control.js +7 -1
  30. package/addon/services/order-list-overlay.js +0 -1
  31. package/addon/services/place-actions.js +20 -4
  32. package/addon/services/service-rate-actions.js +31 -0
  33. package/addon/services/vehicle-actions.js +20 -4
  34. package/addon/templates/operations/scheduler/index.hbs +2 -2
  35. package/addon/utils/create-full-calendar-event-from-order.js +6 -0
  36. package/composer.json +1 -1
  37. package/extension.json +1 -1
  38. package/package.json +4 -4
  39. package/server/migrations/2025_12_16_000001_add_subject_created_at_index_to_positions.php +40 -0
  40. package/server/migrations/2025_12_16_000003_add_performance_indexes_to_fleetops_core_tables.php +442 -0
  41. package/server/src/Console/Commands/DispatchAdhocOrders.php +7 -2
  42. package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -0
  43. package/server/src/Http/Controllers/Api/v1/OrderController.php +30 -0
  44. package/server/src/Http/Controllers/Internal/v1/LiveController.php +184 -86
  45. package/server/src/Http/Controllers/Internal/v1/OrderController.php +14 -1
  46. package/server/src/Http/Controllers/Internal/v1/PlaceController.php +5 -0
  47. package/server/src/Http/Filter/DriverFilter.php +10 -0
  48. package/server/src/Http/Filter/OrderFilter.php +8 -1
  49. package/server/src/Http/Resources/v1/Contact.php +2 -2
  50. package/server/src/Http/Resources/v1/Entity.php +1 -1
  51. package/server/src/Http/Resources/v1/Index/Customer.php +33 -0
  52. package/server/src/Http/Resources/v1/Index/Driver.php +45 -0
  53. package/server/src/Http/Resources/v1/Index/Facilitator.php +33 -0
  54. package/server/src/Http/Resources/v1/Index/Order.php +127 -0
  55. package/server/src/Http/Resources/v1/Index/Payload.php +57 -0
  56. package/server/src/Http/Resources/v1/Index/Place.php +45 -0
  57. package/server/src/Http/Resources/v1/Index/TrackingNumber.php +25 -0
  58. package/server/src/Http/Resources/v1/Index/Vehicle.php +50 -0
  59. package/server/src/Http/Resources/v1/Order.php +41 -14
  60. package/server/src/Http/Resources/v1/Place.php +1 -1
  61. package/server/src/Http/Resources/v1/Position.php +2 -1
  62. package/server/src/Http/Resources/v1/ServiceRate.php +4 -4
  63. package/server/src/Http/Resources/v1/ServiceRateFee.php +12 -12
  64. package/server/src/Http/Resources/v1/ServiceRateParcelFee.php +14 -7
  65. package/server/src/Http/Resources/v1/TrackingNumber.php +1 -1
  66. package/server/src/Http/Resources/v1/Waypoint.php +1 -1
  67. package/server/src/Listeners/HandleOrderDispatched.php +5 -0
  68. package/server/src/Models/Contact.php +2 -0
  69. package/server/src/Models/Device.php +2 -0
  70. package/server/src/Models/DeviceEvent.php +2 -0
  71. package/server/src/Models/Driver.php +2 -0
  72. package/server/src/Models/FuelReport.php +2 -0
  73. package/server/src/Models/Issue.php +2 -0
  74. package/server/src/Models/Order.php +12 -5
  75. package/server/src/Models/Place.php +2 -0
  76. package/server/src/Models/Position.php +2 -0
  77. package/server/src/Models/ServiceArea.php +2 -0
  78. package/server/src/Models/ServiceRate.php +5 -1
  79. package/server/src/Models/ServiceRateFee.php +3 -17
  80. package/server/src/Models/ServiceRateParcelFee.php +1 -12
  81. package/server/src/Models/Vehicle.php +2 -0
  82. package/server/src/Models/Vendor.php +2 -0
  83. package/server/src/Models/Zone.php +2 -0
  84. package/server/src/Observers/DriverObserver.php +23 -0
  85. package/server/src/Observers/OrderObserver.php +31 -0
  86. package/server/src/Observers/PlaceObserver.php +31 -0
  87. package/server/src/Observers/ServiceRateObserver.php +0 -18
  88. package/server/src/Observers/VehicleObserver.php +7 -0
  89. package/server/src/Support/LiveCacheService.php +165 -0
  90. package/server/src/Support/OSRM.php +49 -22
  91. package/server/src/Support/OrderTracker.php +100 -28
  92. package/translations/en-us.yaml +3 -1
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbase/fleetops-api",
3
- "version": "0.6.29",
3
+ "version": "0.6.31",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "keywords": [
6
6
  "fleetbase-extension",
package/extension.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Fleet-Ops",
3
- "version": "0.6.29",
3
+ "version": "0.6.31",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "repository": "https://github.com/fleetbase/fleetops",
6
6
  "license": "AGPL-3.0-or-later",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/fleetops-engine",
3
- "version": "0.6.29",
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.8",
46
- "@fleetbase/ember-ui": "^0.3.14",
47
- "@fleetbase/fleetops-data": "^0.1.23",
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
+ };