@fleetbase/fleetops-engine 0.6.44 → 0.6.46
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/map-settings.hbs +26 -0
- package/addon/components/admin/map-settings.js +46 -0
- package/addon/components/admin/routing-settings.hbs +11 -0
- package/addon/components/cell/order-route-type.hbs +46 -0
- package/addon/components/cell/order-route-type.js +90 -0
- package/addon/components/cell/place-address.hbs +1 -0
- package/addon/components/display-place.hbs +45 -56
- package/addon/components/display-place.js +21 -0
- package/addon/components/entity/form.hbs +24 -0
- package/addon/components/entity/form.js +30 -0
- package/addon/components/layout/fleet-ops-sidebar/driver-listing.js +5 -5
- package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +5 -5
- package/addon/components/layout/fleet-ops-sidebar.js +8 -0
- package/addon/components/leaflet-draw-control.js +1 -1
- package/addon/components/maintenance-schedule/form.js +2 -1
- package/addon/components/map/drawer/driver-listing.js +5 -5
- package/addon/components/map/drawer/geofence-event-listing.js +5 -2
- package/addon/components/map/drawer/place-listing.js +5 -5
- package/addon/components/map/drawer/position-listing.js +102 -21
- package/addon/components/map/drawer/vehicle-listing.js +5 -5
- package/addon/components/map/google-live-map.hbs +9 -0
- package/addon/components/map/google-live-map.js +445 -0
- package/addon/components/map/leaflet-live-map.hbs +186 -142
- package/addon/components/map/leaflet-live-map.js +121 -41
- package/addon/components/map/toolbar/visibility-control-panel.js +2 -2
- package/addon/components/map/toolbar/zones-panel.hbs +9 -9
- package/addon/components/map/toolbar.hbs +3 -3
- package/addon/components/map/toolbar.js +9 -1
- package/addon/components/modals/map-layer-form.hbs +132 -63
- package/addon/components/modals/orchestrator-import.hbs +4 -11
- package/addon/components/modals/orchestrator-import.js +17 -1
- package/addon/components/modals/update-order-activity.hbs +1 -1
- package/addon/components/orchestrator/order-pool.js +3 -2
- package/addon/components/orchestrator-workbench.js +29 -41
- package/addon/components/order/details/detail.js +2 -2
- package/addon/components/order/details/payload.hbs +5 -5
- package/addon/components/order/details/payload.js +18 -1
- package/addon/components/order/details/route.hbs +2 -2
- package/addon/components/order/details/route.js +76 -3
- package/addon/components/order/form/payload.hbs +33 -0
- package/addon/components/order/form/payload.js +1 -0
- package/addon/components/order/form/route.hbs +8 -8
- package/addon/components/order/form/route.js +78 -18
- package/addon/components/order/form/service-rate.hbs +1 -1
- package/addon/components/order/form.js +2 -2
- package/addon/components/order/route-editor.hbs +209 -147
- package/addon/components/order/route-editor.js +143 -102
- package/addon/components/place/address.hbs +1 -0
- package/addon/components/place/address.js +12 -0
- package/addon/components/route-list.hbs +43 -55
- package/addon/components/route-list.js +47 -0
- package/addon/components/route-optimization-wizard-panel.js +3 -4
- package/addon/components/service-rate/details.hbs +6 -6
- package/addon/components/service-rate/form.hbs +28 -15
- package/addon/components/vehicle/card.hbs +4 -4
- package/addon/controllers/maintenance/schedules/index.js +2 -1
- package/addon/controllers/operations/orders/index/details/virtual.js +5 -0
- package/addon/controllers/operations/orders/index/details.js +113 -15
- package/addon/controllers/operations/orders/index/new.js +1 -1
- package/addon/controllers/operations/orders/index.js +8 -1
- package/addon/controllers/operations/service-rates/index/edit.js +1 -0
- package/addon/controllers/operations/service-rates/index/new.js +1 -0
- package/addon/controllers/settings/map.js +97 -0
- package/addon/controllers/settings/routing.js +47 -12
- package/addon/extension.js +11 -0
- package/addon/helpers/f-to-int.js +6 -0
- package/addon/helpers/place-address-html.js +6 -0
- package/addon/instance-initializers/register-google-routes.js +17 -0
- package/addon/instance-initializers/register-osrm.js +5 -0
- package/addon/routes/application.js +9 -3
- package/addon/routes/operations/orchestrator.js +13 -0
- package/addon/routes/operations/orders/index/details/virtual.js +1 -0
- package/addon/routes/operations/orders/index/details.js +47 -24
- package/addon/routes/operations/orders/index/new.js +9 -0
- package/addon/routes/operations/orders/index.js +0 -1
- package/addon/routes/settings/map.js +3 -0
- package/addon/routes.js +1 -0
- package/addon/services/entity-actions.js +1 -1
- package/addon/services/equipment-actions.js +4 -6
- package/addon/services/geofence-event-bus.js +2 -1
- package/addon/services/geofence.js +204 -168
- package/addon/services/google-routes.js +300 -0
- package/addon/services/leaflet-draw-restriction.js +2 -1
- package/addon/services/leaflet-map-manager.js +21 -0
- package/addon/services/maintenance-actions.js +4 -6
- package/addon/services/map-adapter/google.js +2205 -0
- package/addon/services/map-adapter/leaflet.js +1042 -0
- package/addon/services/map-adapter-interface.js +551 -0
- package/addon/services/map-manager.js +768 -0
- package/addon/services/map-settings.js +75 -0
- package/addon/services/movement-tracker.js +83 -32
- package/addon/services/order-actions.js +11 -1
- package/addon/services/osrm.js +79 -6
- package/addon/services/part-actions.js +4 -6
- package/addon/services/position-playback.js +135 -62
- package/addon/services/route-engine.js +83 -0
- package/addon/services/service-areas.js +8 -1
- package/addon/services/service-rate-actions.js +8 -3
- package/addon/styles/fleetops-engine.css +555 -0
- package/addon/templates/management/vehicles/index.hbs +0 -1
- package/addon/templates/operations/orders/index/details/virtual.hbs +7 -1
- package/addon/templates/operations/orders/index/details.hbs +0 -1
- package/addon/templates/settings/map.hbs +53 -0
- package/addon/templates/settings/routing.hbs +15 -4
- package/addon/utils/fleet-ops-options.js +34 -0
- package/addon/utils/has-valid-coordinates.js +6 -0
- package/addon/utils/map-provider-options.js +6 -0
- package/addon/utils/order-route-editing.js +86 -0
- package/addon/utils/order-route-summary.js +20 -0
- package/addon/utils/place-address-html.js +41 -0
- package/addon/utils/route-colors.js +43 -12
- package/addon/utils/route-visualization.js +93 -0
- package/addon/utils/serialize-payload.js +1 -1
- package/addon/utils/vendor-integration.js +2 -1
- package/app/components/admin/map-settings.js +1 -0
- package/app/components/admin/routing-settings.js +1 -0
- package/app/components/cell/order-route-type.js +1 -0
- package/app/components/cell/place-address.js +1 -0
- package/app/components/map/google-live-map.js +1 -0
- package/app/components/place/address.js +1 -0
- package/app/controllers/operations/orders/index/details/virtual.js +1 -0
- package/app/controllers/settings/map.js +1 -0
- package/app/helpers/f-to-int.js +1 -0
- package/app/helpers/place-address-html.js +1 -0
- package/app/routes/settings/map.js +1 -0
- package/app/services/map-adapter/google.js +1 -0
- package/app/services/map-adapter/leaflet.js +1 -0
- package/app/services/map-adapter-interface.js +1 -0
- package/app/services/map-manager.js +1 -0
- package/app/services/map-settings.js +1 -0
- package/app/templates/settings/map.js +1 -0
- package/app/utils/has-valid-coordinates.js +1 -0
- package/app/utils/order-route-editing.js +2 -0
- package/app/utils/order-route-summary.js +1 -0
- package/app/utils/place-address-html.js +1 -0
- package/app/utils/route-colors.js +1 -1
- package/app/utils/route-visualization.js +1 -0
- package/assets/images/drawing-controls-spritesheet.svg +156 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/src/Auth/Schemas/FleetOps.php +5 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +36 -8
- package/server/src/Http/Controllers/Api/v1/PayloadController.php +14 -1
- package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +11 -3
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -0
- package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +7 -2
- package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +6 -1
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +2 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +2 -1
- package/server/src/Http/Controllers/Internal/v1/OrchestrationController.php +7 -4
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +61 -34
- package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +3 -2
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +106 -3
- package/server/src/Http/Filter/OrderFilter.php +2 -1
- package/server/src/Http/Requests/CreateServiceRateRequest.php +2 -2
- package/server/src/Http/Resources/v1/Index/Payload.php +9 -7
- package/server/src/Http/Resources/v1/Order.php +20 -2
- package/server/src/Http/Resources/v1/ServiceQuote.php +2 -2
- package/server/src/Models/Entity.php +7 -0
- package/server/src/Models/Order.php +81 -8
- package/server/src/Models/OrderConfig.php +15 -0
- package/server/src/Models/Payload.php +131 -27
- package/server/src/Models/Place.php +182 -48
- package/server/src/Models/ServiceRate.php +125 -32
- package/server/src/Observers/PurchaseRateObserver.php +3 -5
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +59 -23
- package/server/src/Rules/ComputableAlgo.php +1 -3
- package/server/src/Support/Algo.php +87 -1
- package/server/src/Support/Utils.php +69 -0
- package/server/src/routes.php +4 -0
- package/translations/en-us.yaml +1937 -1916
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.46",
|
|
4
4
|
"description": "Fleet & Transport Management Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "fleet-ops"
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@babel/core": "^7.23.2",
|
|
45
45
|
"@fleetbase/ember-core": "^0.3.18",
|
|
46
|
-
"@fleetbase/ember-ui": "^0.3.
|
|
47
|
-
"@fleetbase/fleetops-data": "^0.1.
|
|
46
|
+
"@fleetbase/ember-ui": "^0.3.29",
|
|
47
|
+
"@fleetbase/fleetops-data": "^0.1.31",
|
|
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",
|
|
@@ -100,6 +100,11 @@ class OrderController extends Controller
|
|
|
100
100
|
$pickup = data_get($payloadInput, 'pickup');
|
|
101
101
|
$dropoff = data_get($payloadInput, 'dropoff');
|
|
102
102
|
$return = data_get($payloadInput, 'return');
|
|
103
|
+
$hasPickupField = array_key_exists('pickup', $payloadInput);
|
|
104
|
+
$hasDropoffField = array_key_exists('dropoff', $payloadInput);
|
|
105
|
+
$hasReturnField = array_key_exists('return', $payloadInput);
|
|
106
|
+
$hasWaypointsField = array_key_exists('waypoints', $payloadInput);
|
|
107
|
+
$hasRouteEndpointFields = $hasPickupField || $hasDropoffField || $hasReturnField;
|
|
103
108
|
|
|
104
109
|
if ($pickup) {
|
|
105
110
|
$payload->setPickup($pickup, [
|
|
@@ -321,7 +326,7 @@ class OrderController extends Controller
|
|
|
321
326
|
}
|
|
322
327
|
|
|
323
328
|
// load required relations
|
|
324
|
-
$order->load(['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate', 'customer', 'facilitator']);
|
|
329
|
+
$order->load(['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate.serviceQuote.items', 'customer', 'facilitator']);
|
|
325
330
|
|
|
326
331
|
// Determine if order should be dispatched on creation
|
|
327
332
|
$shouldDispatch = $request->boolean('dispatch') && $integratedVendorOrder === null;
|
|
@@ -364,7 +369,7 @@ class OrderController extends Controller
|
|
|
364
369
|
|
|
365
370
|
// find for the order
|
|
366
371
|
try {
|
|
367
|
-
$order = Order::findRecordOrFail($id, ['trackingNumber', 'driverAssigned', 'purchaseRate', 'customer', 'facilitator']);
|
|
372
|
+
$order = Order::findRecordOrFail($id, ['trackingNumber', 'driverAssigned', 'purchaseRate.serviceQuote.items', 'customer', 'facilitator']);
|
|
368
373
|
} catch (ModelNotFoundException $exception) {
|
|
369
374
|
return response()->json(
|
|
370
375
|
[
|
|
@@ -414,14 +419,21 @@ class OrderController extends Controller
|
|
|
414
419
|
$payload->save();
|
|
415
420
|
|
|
416
421
|
// set waypoints and entities after payload is saved
|
|
417
|
-
if ($waypoints) {
|
|
422
|
+
if ($hasWaypointsField && is_array($waypoints) && count($waypoints)) {
|
|
418
423
|
$payload->setWaypoints($waypoints);
|
|
424
|
+
} elseif ($hasWaypointsField || $hasRouteEndpointFields) {
|
|
425
|
+
$payload->removeWaypoints();
|
|
419
426
|
}
|
|
420
427
|
|
|
421
428
|
if ($entities) {
|
|
422
429
|
$payload->setEntities($entities);
|
|
423
430
|
}
|
|
424
431
|
|
|
432
|
+
$firstWaypoint = $payload->getPickupOrFirstWaypoint();
|
|
433
|
+
if ($firstWaypoint instanceof Place) {
|
|
434
|
+
$payload->setCurrentWaypoint($firstWaypoint);
|
|
435
|
+
}
|
|
436
|
+
|
|
425
437
|
$input['payload_uuid'] = $payload->uuid;
|
|
426
438
|
} elseif ($request->has('payload')) {
|
|
427
439
|
$input['payload_uuid'] = Utils::getUuid('payloads', [
|
|
@@ -440,6 +452,11 @@ class OrderController extends Controller
|
|
|
440
452
|
$pickup = data_get($payloadInput, 'pickup');
|
|
441
453
|
$dropoff = data_get($payloadInput, 'dropoff');
|
|
442
454
|
$return = data_get($payloadInput, 'return');
|
|
455
|
+
$hasPickupField = $request->exists('pickup');
|
|
456
|
+
$hasDropoffField = $request->exists('dropoff');
|
|
457
|
+
$hasReturnField = $request->exists('return');
|
|
458
|
+
$hasWaypointsField = $request->exists('waypoints');
|
|
459
|
+
$hasRouteEndpointFields = $hasPickupField || $hasDropoffField || $hasReturnField;
|
|
443
460
|
|
|
444
461
|
// if no pickup and dropoff extract from waypoints
|
|
445
462
|
if (empty($pickup) && empty($dropoff) && count($waypoints)) {
|
|
@@ -462,14 +479,21 @@ class OrderController extends Controller
|
|
|
462
479
|
$payload->save();
|
|
463
480
|
|
|
464
481
|
// set waypoints and entities after payload is saved
|
|
465
|
-
if ($waypoints) {
|
|
482
|
+
if ($hasWaypointsField && is_array($waypoints) && count($waypoints)) {
|
|
466
483
|
$payload->setWaypoints($waypoints);
|
|
484
|
+
} elseif ($hasWaypointsField || $hasRouteEndpointFields) {
|
|
485
|
+
$payload->removeWaypoints();
|
|
467
486
|
}
|
|
468
487
|
|
|
469
488
|
if ($entities) {
|
|
470
489
|
$payload->setEntities($entities);
|
|
471
490
|
}
|
|
472
491
|
|
|
492
|
+
$firstWaypoint = $payload->getPickupOrFirstWaypoint();
|
|
493
|
+
if ($firstWaypoint instanceof Place) {
|
|
494
|
+
$payload->setCurrentWaypoint($firstWaypoint);
|
|
495
|
+
}
|
|
496
|
+
|
|
473
497
|
$input['payload_uuid'] = $payload->uuid;
|
|
474
498
|
}
|
|
475
499
|
|
|
@@ -549,7 +573,7 @@ class OrderController extends Controller
|
|
|
549
573
|
$order->flushAttributesCache();
|
|
550
574
|
|
|
551
575
|
// load required relations
|
|
552
|
-
$order->load(['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate', 'customer', 'facilitator']);
|
|
576
|
+
$order->load(['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate.serviceQuote.items', 'customer', 'facilitator']);
|
|
553
577
|
|
|
554
578
|
// response the order resource
|
|
555
579
|
return new OrderResource($order);
|
|
@@ -759,7 +783,7 @@ class OrderController extends Controller
|
|
|
759
783
|
{
|
|
760
784
|
// find for the order
|
|
761
785
|
try {
|
|
762
|
-
$order = Order::findRecordOrFail($id, ['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate', 'customer', 'facilitator']);
|
|
786
|
+
$order = Order::findRecordOrFail($id, ['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate.serviceQuote.items', 'customer', 'facilitator']);
|
|
763
787
|
} catch (ModelNotFoundException $exception) {
|
|
764
788
|
return response()->json(
|
|
765
789
|
[
|
|
@@ -839,7 +863,7 @@ class OrderController extends Controller
|
|
|
839
863
|
public function dispatchOrder(string $id)
|
|
840
864
|
{
|
|
841
865
|
try {
|
|
842
|
-
$order = Order::findRecordOrFail($id, ['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate', 'customer', 'facilitator']);
|
|
866
|
+
$order = Order::findRecordOrFail($id, ['trackingNumber', 'trackingStatuses', 'driverAssigned', 'vehicleAssigned', 'purchaseRate.serviceQuote.items', 'customer', 'facilitator']);
|
|
843
867
|
} catch (ModelNotFoundException $exception) {
|
|
844
868
|
return response()->json(
|
|
845
869
|
[
|
|
@@ -1159,7 +1183,11 @@ class OrderController extends Controller
|
|
|
1159
1183
|
})->first();
|
|
1160
1184
|
}
|
|
1161
1185
|
|
|
1162
|
-
$
|
|
1186
|
+
$orderConfig = $order->ensureOrderConfig();
|
|
1187
|
+
if (!$orderConfig) {
|
|
1188
|
+
return response()->apiError('No order config found for order.');
|
|
1189
|
+
}
|
|
1190
|
+
$activities = $orderConfig->nextActivity($waypoint);
|
|
1163
1191
|
|
|
1164
1192
|
// If activity is to complete order add proof of delivery properties if required
|
|
1165
1193
|
// This is a temporary fix until activity is updated to handle POD on it's own
|
|
@@ -31,6 +31,11 @@ class PayloadController extends Controller
|
|
|
31
31
|
$pickup = data_get($input, 'pickup');
|
|
32
32
|
$dropoff = data_get($input, 'dropoff');
|
|
33
33
|
$return = data_get($input, 'return');
|
|
34
|
+
$hasPickupField = array_key_exists('pickup', $input);
|
|
35
|
+
$hasDropoffField = array_key_exists('dropoff', $input);
|
|
36
|
+
$hasReturnField = array_key_exists('return', $input);
|
|
37
|
+
$hasWaypointsField = array_key_exists('waypoints', $input);
|
|
38
|
+
$hasRouteEndpointFields = $hasPickupField || $hasDropoffField || $hasReturnField;
|
|
34
39
|
|
|
35
40
|
// make sure company is set
|
|
36
41
|
$input['company_uuid'] = session('company');
|
|
@@ -116,8 +121,10 @@ class PayloadController extends Controller
|
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
// set waypoints
|
|
119
|
-
if ($waypoints) {
|
|
124
|
+
if ($hasWaypointsField && is_array($waypoints) && count($waypoints)) {
|
|
120
125
|
$payload->setWaypoints($waypoints);
|
|
126
|
+
} elseif ($hasWaypointsField || $hasRouteEndpointFields) {
|
|
127
|
+
$payload->removeWaypoints();
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
// set entities
|
|
@@ -131,6 +138,12 @@ class PayloadController extends Controller
|
|
|
131
138
|
// save the payload
|
|
132
139
|
$payload->save();
|
|
133
140
|
|
|
141
|
+
// set the first / current waypoint from the effective route shape
|
|
142
|
+
$firstWaypoint = $payload->getPickupOrFirstWaypoint();
|
|
143
|
+
if ($firstWaypoint instanceof Place) {
|
|
144
|
+
$payload->setCurrentWaypoint($firstWaypoint);
|
|
145
|
+
}
|
|
146
|
+
|
|
134
147
|
// make sure entities and waypoints is loaded
|
|
135
148
|
$payload->load(['entities', 'waypoints', 'pickup', 'dropoff', 'return']);
|
|
136
149
|
|
|
@@ -41,10 +41,19 @@ class PurchaseRateController extends Controller
|
|
|
41
41
|
|
|
42
42
|
// order assignment
|
|
43
43
|
if ($request->has('order')) {
|
|
44
|
-
$
|
|
44
|
+
$orderUuid = Utils::getUuid('orders', [
|
|
45
45
|
'public_id' => $request->input('order'),
|
|
46
46
|
'company_uuid' => session('company'),
|
|
47
47
|
]);
|
|
48
|
+
|
|
49
|
+
$order = Order::where('uuid', $orderUuid)->first();
|
|
50
|
+
|
|
51
|
+
if ($order instanceof Order) {
|
|
52
|
+
$input['payload_uuid'] = $order->payload_uuid;
|
|
53
|
+
$input['customer_uuid'] = $order->customer_uuid;
|
|
54
|
+
$input['customer_type'] = $order->customer_type;
|
|
55
|
+
$input['company_uuid'] = $order->company_uuid ?? $input['company_uuid'];
|
|
56
|
+
}
|
|
48
57
|
} elseif ($createOrder) {
|
|
49
58
|
// create order from service quote
|
|
50
59
|
$serviceQuote = ServiceQuote::where('uuid', $input['service_quote_uuid'])->orWhere('public_id', $request->input('service_quote'))->first();
|
|
@@ -70,9 +79,8 @@ class PurchaseRateController extends Controller
|
|
|
70
79
|
// create the purchaseRate
|
|
71
80
|
$purchaseRate = PurchaseRate::create($input);
|
|
72
81
|
|
|
73
|
-
// set purchase rate to order
|
|
74
82
|
if ($order instanceof Order) {
|
|
75
|
-
$order->
|
|
83
|
+
$order->attachPurchaseRate($purchaseRate);
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
// response the driver resource
|
|
@@ -65,6 +65,7 @@ class ServiceAreaController extends Controller
|
|
|
65
65
|
// create the serviceArea
|
|
66
66
|
try {
|
|
67
67
|
$serviceArea = ServiceArea::create($input);
|
|
68
|
+
$serviceArea->refresh();
|
|
68
69
|
} catch (\Throwable $e) {
|
|
69
70
|
logger()->error('Unable to create service area.', ['error' => $e->getMessage()]);
|
|
70
71
|
|
|
@@ -135,6 +136,7 @@ class ServiceAreaController extends Controller
|
|
|
135
136
|
|
|
136
137
|
// update the serviceArea
|
|
137
138
|
$serviceArea->update($input);
|
|
139
|
+
$serviceArea->refresh();
|
|
138
140
|
|
|
139
141
|
// response the serviceArea resource
|
|
140
142
|
return new ServiceAreaResource($serviceArea);
|
|
@@ -98,6 +98,7 @@ class ServiceQuoteController extends Controller
|
|
|
98
98
|
'amount' => $subTotal,
|
|
99
99
|
'currency' => $serviceRate->currency,
|
|
100
100
|
]);
|
|
101
|
+
$quote->setRelation('serviceRate', $serviceRate);
|
|
101
102
|
|
|
102
103
|
$items = $lines->map(function ($line) use ($quote) {
|
|
103
104
|
return ServiceQuoteItem::create([
|
|
@@ -143,6 +144,7 @@ class ServiceQuoteController extends Controller
|
|
|
143
144
|
'amount' => $subTotal,
|
|
144
145
|
'currency' => $serviceRate->currency,
|
|
145
146
|
]);
|
|
147
|
+
$quote->setRelation('serviceRate', $serviceRate);
|
|
146
148
|
|
|
147
149
|
$items = $lines->map(function ($line) use ($quote) {
|
|
148
150
|
return ServiceQuoteItem::create([
|
|
@@ -230,6 +232,7 @@ class ServiceQuoteController extends Controller
|
|
|
230
232
|
|
|
231
233
|
// should all be Place like
|
|
232
234
|
$waypoints = collect([$pickup, ...$waypoints, $dropoff])->filter();
|
|
235
|
+
$endpointCount = (int) ($pickup instanceof Place) + (int) ($dropoff instanceof Place);
|
|
233
236
|
|
|
234
237
|
// if facilitator is an integrated partner resolve service quotes from bridge
|
|
235
238
|
if ($facilitator && Utils::isIntegratedVendorId($facilitator)) {
|
|
@@ -279,7 +282,7 @@ class ServiceQuoteController extends Controller
|
|
|
279
282
|
$serviceQuotes = collect();
|
|
280
283
|
|
|
281
284
|
if ($serviceRate) {
|
|
282
|
-
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery);
|
|
285
|
+
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery, $endpointCount);
|
|
283
286
|
|
|
284
287
|
$quote = ServiceQuote::create([
|
|
285
288
|
'request_id' => $requestId,
|
|
@@ -288,6 +291,7 @@ class ServiceQuoteController extends Controller
|
|
|
288
291
|
'amount' => $subTotal,
|
|
289
292
|
'currency' => $serviceRate->currency,
|
|
290
293
|
]);
|
|
294
|
+
$quote->setRelation('serviceRate', $serviceRate);
|
|
291
295
|
|
|
292
296
|
// set preliminary data to meta
|
|
293
297
|
$quote->updateMeta('preliminary_data', $preliminaryData);
|
|
@@ -326,7 +330,7 @@ class ServiceQuoteController extends Controller
|
|
|
326
330
|
|
|
327
331
|
// calculate quotes
|
|
328
332
|
foreach ($serviceRates as $serviceRate) {
|
|
329
|
-
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery);
|
|
333
|
+
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery, $endpointCount);
|
|
330
334
|
|
|
331
335
|
$quote = ServiceQuote::create([
|
|
332
336
|
'request_id' => $requestId,
|
|
@@ -335,6 +339,7 @@ class ServiceQuoteController extends Controller
|
|
|
335
339
|
'amount' => $subTotal,
|
|
336
340
|
'currency' => $serviceRate->currency,
|
|
337
341
|
]);
|
|
342
|
+
$quote->setRelation('serviceRate', $serviceRate);
|
|
338
343
|
|
|
339
344
|
// set preliminary data to meta
|
|
340
345
|
$quote->updateMeta('preliminary_data', $preliminaryData);
|
|
@@ -30,6 +30,8 @@ class ServiceRateController extends Controller
|
|
|
30
30
|
'rate_calculation_method',
|
|
31
31
|
'currency',
|
|
32
32
|
'base_fee',
|
|
33
|
+
'max_distance_unit',
|
|
34
|
+
'max_distance',
|
|
33
35
|
'per_meter_unit',
|
|
34
36
|
'per_meter_flat_rate_fee',
|
|
35
37
|
'meter_fees',
|
|
@@ -119,7 +121,10 @@ class ServiceRateController extends Controller
|
|
|
119
121
|
'rate_calculation_method',
|
|
120
122
|
'currency',
|
|
121
123
|
'base_fee',
|
|
122
|
-
'
|
|
124
|
+
'max_distance_unit',
|
|
125
|
+
'max_distance',
|
|
126
|
+
'per_meter_unit',
|
|
127
|
+
'per_meter_flat_rate_fee',
|
|
123
128
|
'meter_fees',
|
|
124
129
|
'meter_fees.*.distance',
|
|
125
130
|
'meter_fees.*.fee',
|
|
@@ -69,6 +69,7 @@ class ZoneController extends Controller
|
|
|
69
69
|
|
|
70
70
|
// create the zone
|
|
71
71
|
$zone = Zone::create($input);
|
|
72
|
+
$zone->refresh();
|
|
72
73
|
|
|
73
74
|
// response the zone resource
|
|
74
75
|
return new ZoneResource($zone);
|
|
@@ -134,6 +135,7 @@ class ZoneController extends Controller
|
|
|
134
135
|
|
|
135
136
|
// update the zone
|
|
136
137
|
$zone->update($input);
|
|
138
|
+
$zone->refresh();
|
|
137
139
|
|
|
138
140
|
// response the zone resource
|
|
139
141
|
return new ZoneResource($zone);
|
|
@@ -128,10 +128,11 @@ class LiveController extends Controller
|
|
|
128
128
|
->applyDirectivesForPermissions('fleet-ops list order')
|
|
129
129
|
->with([
|
|
130
130
|
'payload.entities',
|
|
131
|
-
'payload.waypoints',
|
|
132
131
|
'payload.dropoff',
|
|
133
132
|
'payload.pickup',
|
|
134
133
|
'payload.return',
|
|
134
|
+
'payload.firstWaypointMarker.place',
|
|
135
|
+
'payload.lastWaypointMarker.place',
|
|
135
136
|
'trackingNumber',
|
|
136
137
|
'trackingStatuses',
|
|
137
138
|
'driverAssigned' => function ($query) {
|
|
@@ -574,12 +574,15 @@ class OrchestrationController extends Controller
|
|
|
574
574
|
|
|
575
575
|
// ── Resolve OrderConfig ───────────────────────────────────────
|
|
576
576
|
$orderConfigUuid = null;
|
|
577
|
+
$resolvedOrderConfig = null;
|
|
577
578
|
if (!empty($firstRow['type'])) {
|
|
578
|
-
$
|
|
579
|
-
if ($
|
|
580
|
-
$orderConfigUuid = $
|
|
579
|
+
$resolvedOrderConfig = OrderConfig::resolveFromIdentifier($firstRow['type']);
|
|
580
|
+
if ($resolvedOrderConfig) {
|
|
581
|
+
$orderConfigUuid = $resolvedOrderConfig->uuid;
|
|
581
582
|
}
|
|
582
583
|
}
|
|
584
|
+
$resolvedOrderConfig ??= OrderConfig::defaultOrCreate();
|
|
585
|
+
$orderConfigUuid = $resolvedOrderConfig?->uuid;
|
|
583
586
|
|
|
584
587
|
// ── Resolve Customer ─────────────────────────────────────────
|
|
585
588
|
$customerUuid = null;
|
|
@@ -660,7 +663,7 @@ class OrchestrationController extends Controller
|
|
|
660
663
|
'driver_assigned_uuid' => $driverUuid,
|
|
661
664
|
'internal_id' => $firstRow['internal_id'] ?? null,
|
|
662
665
|
'status' => $firstRow['status'] ?? 'created',
|
|
663
|
-
'type' => $
|
|
666
|
+
'type' => $resolvedOrderConfig?->key ?? 'transport',
|
|
664
667
|
'notes' => $firstRow['notes'] ?? null,
|
|
665
668
|
'scheduled_at' => !empty($firstRow['scheduled_at'])
|
|
666
669
|
? Carbon::parse($firstRow['scheduled_at'])
|
|
@@ -109,9 +109,19 @@ class OrderController extends FleetOpsController
|
|
|
109
109
|
$input['integrated_vendor_order'] = $integratedVendorOrder;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
// Normalize order config + type onto the company transport
|
|
113
|
+
// config when an explicit config was not provided.
|
|
114
|
+
$resolvedOrderConfig = null;
|
|
115
|
+
if (!empty($input['order_config_uuid']) || !empty($input['type'])) {
|
|
116
|
+
$resolvedOrderConfig = OrderConfig::resolveFromIdentifier([$input['order_config_uuid'] ?? null, $input['type'] ?? null]);
|
|
117
|
+
}
|
|
118
|
+
$resolvedOrderConfig ??= OrderConfig::defaultOrCreate();
|
|
119
|
+
|
|
120
|
+
if ($resolvedOrderConfig) {
|
|
121
|
+
$input['order_config_uuid'] = $resolvedOrderConfig->uuid;
|
|
122
|
+
$input['type'] = $resolvedOrderConfig->key;
|
|
123
|
+
} elseif (!isset($input['type'])) {
|
|
124
|
+
$input['type'] = 'transport';
|
|
115
125
|
}
|
|
116
126
|
|
|
117
127
|
// if no status is set its default to `created`
|
|
@@ -119,14 +129,6 @@ class OrderController extends FleetOpsController
|
|
|
119
129
|
$input['status'] = 'created';
|
|
120
130
|
}
|
|
121
131
|
|
|
122
|
-
// Set order config
|
|
123
|
-
if (!isset($input['order_config_uuid'])) {
|
|
124
|
-
$defaultOrderConfig = OrderConfig::default();
|
|
125
|
-
if ($defaultOrderConfig) {
|
|
126
|
-
$input['order_config_uuid'] = $defaultOrderConfig->uuid;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
132
|
// Ensure orchestrator_priority is never null — the column is NOT NULL
|
|
131
133
|
// and the DB default is bypassed when Eloquent receives an explicit null.
|
|
132
134
|
if (!isset($input['orchestrator_priority']) || !is_numeric($input['orchestrator_priority'])) {
|
|
@@ -225,10 +227,14 @@ class OrderController extends FleetOpsController
|
|
|
225
227
|
*/
|
|
226
228
|
public function editOrderRoute(string $id, Request $request)
|
|
227
229
|
{
|
|
228
|
-
$pickup
|
|
229
|
-
$dropoff
|
|
230
|
-
$return
|
|
231
|
-
$waypoints
|
|
230
|
+
$pickup = $request->input('pickup');
|
|
231
|
+
$dropoff = $request->input('dropoff');
|
|
232
|
+
$return = $request->input('return');
|
|
233
|
+
$waypoints = $request->array('waypoints', []);
|
|
234
|
+
$hasPickupInput = $request->exists('pickup');
|
|
235
|
+
$hasDropoffInput = $request->exists('dropoff');
|
|
236
|
+
$hasReturnInput = $request->exists('return');
|
|
237
|
+
$hasWaypointsInput = $request->exists('waypoints');
|
|
232
238
|
|
|
233
239
|
// Get the order
|
|
234
240
|
$order = Order::where('uuid', $id)->with(['payload'])->first();
|
|
@@ -236,30 +242,51 @@ class OrderController extends FleetOpsController
|
|
|
236
242
|
return response()->error('Unable to find order to update route for.');
|
|
237
243
|
}
|
|
238
244
|
|
|
239
|
-
|
|
240
|
-
if ($waypoints) {
|
|
241
|
-
$order->payload->updateWaypoints($waypoints);
|
|
242
|
-
$order->payload->removePlace(['pickup', 'dropoff', 'return'], ['save' => true]);
|
|
243
|
-
} else {
|
|
244
|
-
// Update pickup
|
|
245
|
+
if ($hasPickupInput) {
|
|
245
246
|
if ($pickup) {
|
|
246
247
|
$order->payload->setPickup($pickup, ['save' => true]);
|
|
248
|
+
} else {
|
|
249
|
+
$order->payload->removePlace('pickup', ['save' => true]);
|
|
247
250
|
}
|
|
251
|
+
}
|
|
248
252
|
|
|
249
|
-
|
|
253
|
+
if ($hasDropoffInput) {
|
|
250
254
|
if ($dropoff) {
|
|
251
255
|
$order->payload->setDropoff($dropoff, ['save' => true]);
|
|
256
|
+
} else {
|
|
257
|
+
$order->payload->removePlace('dropoff', ['save' => true]);
|
|
252
258
|
}
|
|
259
|
+
}
|
|
253
260
|
|
|
254
|
-
|
|
261
|
+
if ($hasReturnInput) {
|
|
255
262
|
if ($return) {
|
|
256
|
-
$order->payload->
|
|
263
|
+
$order->payload->setReturn($return, ['save' => true]);
|
|
264
|
+
} else {
|
|
265
|
+
$order->payload->removePlace('return', ['save' => true]);
|
|
257
266
|
}
|
|
267
|
+
}
|
|
258
268
|
|
|
259
|
-
|
|
269
|
+
if ($hasWaypointsInput) {
|
|
270
|
+
if (!empty($waypoints)) {
|
|
271
|
+
$order->payload->updateWaypoints($waypoints);
|
|
272
|
+
} else {
|
|
273
|
+
$order->payload->removeWaypoints();
|
|
274
|
+
}
|
|
275
|
+
} elseif ($hasPickupInput || $hasDropoffInput || $hasReturnInput) {
|
|
260
276
|
$order->payload->removeWaypoints();
|
|
261
277
|
}
|
|
262
278
|
|
|
279
|
+
$startingDestination = $order->payload->getPickupOrFirstWaypoint();
|
|
280
|
+
if (!$startingDestination) {
|
|
281
|
+
$startingDestination = $order->payload->getDropoffOrLastWaypoint();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if ($startingDestination instanceof Place || $startingDestination instanceof Waypoint) {
|
|
285
|
+
$order->payload->setCurrentWaypoint($startingDestination);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
$order->load(['payload.pickup', 'payload.dropoff', 'payload.return', 'payload.waypoints']);
|
|
289
|
+
|
|
263
290
|
return ['order' => new $this->resource($order)];
|
|
264
291
|
}
|
|
265
292
|
|
|
@@ -531,14 +558,10 @@ class OrderController extends FleetOpsController
|
|
|
531
558
|
return response()->error('No order found to dispatch.');
|
|
532
559
|
}
|
|
533
560
|
|
|
534
|
-
//
|
|
535
|
-
|
|
536
|
-
if (!$order->
|
|
537
|
-
|
|
538
|
-
if ($defaultOrderConfig) {
|
|
539
|
-
$order->update(['order_config_uuid' => $defaultOrderConfig->uuid]);
|
|
540
|
-
$order->loadMissing('orderConfig');
|
|
541
|
-
}
|
|
561
|
+
// Ensure the order is normalized onto a real order config before
|
|
562
|
+
// dispatching activities.
|
|
563
|
+
if (!$order->ensureOrderConfig()) {
|
|
564
|
+
return response()->error('No order config found for dispatch.');
|
|
542
565
|
}
|
|
543
566
|
|
|
544
567
|
if (!$order->hasDriverAssigned && !$order->adhoc) {
|
|
@@ -711,7 +734,11 @@ class OrderController extends FleetOpsController
|
|
|
711
734
|
}
|
|
712
735
|
|
|
713
736
|
$waypoint = $request->filled('waypoint') ? Waypoint::findByPlace($request->input('waypoint'), $order) : null;
|
|
714
|
-
$
|
|
737
|
+
$orderConfig = $order->ensureOrderConfig();
|
|
738
|
+
if (!$orderConfig) {
|
|
739
|
+
return response()->error('No order config found for order.');
|
|
740
|
+
}
|
|
741
|
+
$activities = $orderConfig->nextActivity($waypoint);
|
|
715
742
|
|
|
716
743
|
// If activity is to complete order add proof of delivery properties if required
|
|
717
744
|
// This is a temporary fix until activity is updated to handle POD on it's own
|
|
@@ -227,6 +227,7 @@ class ServiceQuoteController extends FleetOpsController
|
|
|
227
227
|
|
|
228
228
|
// should all be Place like
|
|
229
229
|
$waypoints = collect([$pickup, ...$waypoints, $dropoff])->filter();
|
|
230
|
+
$endpointCount = (int) ($pickup instanceof Place) + (int) ($dropoff instanceof Place);
|
|
230
231
|
|
|
231
232
|
// if facilitator is an integrated partner resolve service quotes from bridge
|
|
232
233
|
if ($facilitator && Str::startsWith($facilitator, 'integrated_vendor')) {
|
|
@@ -274,7 +275,7 @@ class ServiceQuoteController extends FleetOpsController
|
|
|
274
275
|
$serviceQuotes = collect();
|
|
275
276
|
|
|
276
277
|
if ($serviceRate) {
|
|
277
|
-
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery);
|
|
278
|
+
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery, $endpointCount);
|
|
278
279
|
|
|
279
280
|
$quote = ServiceQuote::create([
|
|
280
281
|
'request_id' => $requestId,
|
|
@@ -322,7 +323,7 @@ class ServiceQuoteController extends FleetOpsController
|
|
|
322
323
|
|
|
323
324
|
// calculate quotes
|
|
324
325
|
foreach ($serviceRates as $serviceRate) {
|
|
325
|
-
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery);
|
|
326
|
+
[$subTotal, $lines] = $serviceRate->quoteFromPreliminaryData($entities, $waypoints, $totalDistance, $totalTime, $isCashOnDelivery, $endpointCount);
|
|
326
327
|
|
|
327
328
|
$quote = ServiceQuote::create([
|
|
328
329
|
'request_id' => $requestId,
|