@fleetbase/fleetops-engine 0.6.12 → 0.6.14
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/orders.js +6 -8
- package/addon/components/layout/fleet-ops-sidebar.js +8 -0
- package/addon/components/live-map.js +6 -8
- package/addon/components/order-config/fields-editor.js +1 -1
- package/addon/components/route-optimization-engine-select-button.hbs +25 -0
- package/addon/components/route-optimization-engine-select-button.js +13 -0
- package/addon/controllers/operations/orders/index/new.js +52 -150
- package/addon/controllers/operations/orders/index/view.js +8 -9
- package/addon/controllers/settings/routing.js +47 -0
- package/addon/engine.js +27 -0
- package/addon/routes/application.js +8 -0
- package/addon/routes/operations/orders/index/view.js +12 -3
- package/addon/routes/settings/routing.js +3 -0
- package/addon/routes.js +1 -0
- package/addon/services/leaflet-router-control.js +64 -0
- package/addon/services/osrm.js +46 -0
- package/addon/services/route-optimization-interface.js +9 -0
- package/addon/services/route-optimization.js +67 -0
- package/addon/templates/operations/orders/index/new.hbs +21 -16
- package/addon/templates/settings/routing.hbs +32 -0
- package/app/components/route-optimization-engine-select-button.js +1 -0
- package/app/controllers/settings/routing.js +1 -0
- package/app/routes/settings/routing.js +1 -0
- package/app/services/leaflet-router-control.js +1 -0
- package/app/services/osrm.js +1 -0
- package/app/services/route-optimization-interface.js +1 -0
- package/app/services/route-optimization.js +1 -0
- package/app/templates/settings/routing.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +2 -2
- package/server/config/api.php +10 -1
- package/server/src/Auth/Schemas/FleetOps.php +5 -0
- package/server/src/Events/EntityActivityChanged.php +118 -0
- package/server/src/Events/EntityCompleted.php +118 -0
- package/server/src/Events/OrderCanceled.php +2 -2
- package/server/src/Events/OrderCompleted.php +2 -2
- package/server/src/Events/OrderDispatched.php +2 -2
- package/server/src/Events/OrderDriverAssigned.php +1 -1
- package/server/src/Events/OrderFailed.php +2 -2
- package/server/src/Events/OrderReady.php +1 -1
- package/server/src/Events/OrderStarted.php +1 -1
- package/server/src/Events/WaypointActivityChanged.php +2 -2
- package/server/src/Events/WaypointCompleted.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +30 -0
- package/server/src/Listeners/NotifyOrderEvent.php +1 -0
- package/server/src/Models/Order.php +7 -1
- package/server/src/Models/Payload.php +19 -8
- package/server/src/Models/Place.php +49 -13
- package/server/src/routes.php +2 -0
- package/translations/en-us.yaml +5 -0
|
@@ -18,10 +18,10 @@ class OrderDispatched extends ResourceLifecycleEvent
|
|
|
18
18
|
/**
|
|
19
19
|
* Assosciated activity which triggered the event.
|
|
20
20
|
*/
|
|
21
|
-
public ?Activity $activity;
|
|
21
|
+
public ?Activity $activity = null;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Assosciated order waypoint which event is for.
|
|
25
25
|
*/
|
|
26
|
-
public ?Waypoint $waypoint;
|
|
26
|
+
public ?Waypoint $waypoint = null;
|
|
27
27
|
}
|
|
@@ -18,10 +18,10 @@ class OrderFailed extends ResourceLifecycleEvent
|
|
|
18
18
|
/**
|
|
19
19
|
* Assosciated activity which triggered the event.
|
|
20
20
|
*/
|
|
21
|
-
public ?Activity $activity;
|
|
21
|
+
public ?Activity $activity = null;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Assosciated order waypoint which event is for.
|
|
25
25
|
*/
|
|
26
|
-
public ?Waypoint $waypoint;
|
|
26
|
+
public ?Waypoint $waypoint = null;
|
|
27
27
|
}
|
|
@@ -21,12 +21,12 @@ class WaypointActivityChanged implements ShouldBroadcast
|
|
|
21
21
|
/**
|
|
22
22
|
* The waypoint which is completed.
|
|
23
23
|
*/
|
|
24
|
-
public Waypoint $waypoint;
|
|
24
|
+
public ?Waypoint $waypoint = null;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The activity which triggered the waypoint completed.
|
|
28
28
|
*/
|
|
29
|
-
public Activity $activity;
|
|
29
|
+
public ?Activity $activity = null;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* The event id.
|
|
@@ -21,12 +21,12 @@ class WaypointCompleted implements ShouldBroadcast
|
|
|
21
21
|
/**
|
|
22
22
|
* The waypoint which is completed.
|
|
23
23
|
*/
|
|
24
|
-
public Waypoint $waypoint;
|
|
24
|
+
public ?Waypoint $waypoint = null;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The activity which triggered the waypoint completed.
|
|
28
28
|
*/
|
|
29
|
-
public Activity $activity;
|
|
29
|
+
public ?Activity $activity = null;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* The event id.
|
|
@@ -354,7 +354,7 @@ class OrderController extends FleetOpsController
|
|
|
354
354
|
*/
|
|
355
355
|
public function bulkCancel(BulkActionRequest $request)
|
|
356
356
|
{
|
|
357
|
-
/** @var
|
|
357
|
+
/** @var \Illuminate\Database\Eloquent\Collection $orders */
|
|
358
358
|
$orders = Order::whereIn('uuid', $request->input('ids'))->get();
|
|
359
359
|
|
|
360
360
|
$count = $orders->count();
|
|
@@ -174,4 +174,34 @@ class SettingController extends Controller
|
|
|
174
174
|
'notificationSettings' => $notificationSettings,
|
|
175
175
|
]);
|
|
176
176
|
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Save routing settings.
|
|
180
|
+
*
|
|
181
|
+
* @param Request $request the HTTP request object containing the routing settings data
|
|
182
|
+
*
|
|
183
|
+
* @return \Illuminate\Http\JsonResponse a JSON response
|
|
184
|
+
*/
|
|
185
|
+
public function saveRoutingSettings(Request $request)
|
|
186
|
+
{
|
|
187
|
+
$router = $request->input('router');
|
|
188
|
+
Setting::configureCompany('routing', ['router' => $router]);
|
|
189
|
+
|
|
190
|
+
return response()->json([
|
|
191
|
+
'status' => 'ok',
|
|
192
|
+
'message' => 'Routing settings succesfully saved.',
|
|
193
|
+
]);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Retrieve and return the routing settings.
|
|
198
|
+
*
|
|
199
|
+
* @return \Illuminate\Http\JsonResponse
|
|
200
|
+
*/
|
|
201
|
+
public function getRoutingSettings()
|
|
202
|
+
{
|
|
203
|
+
$routingSettings = Setting::lookupCompany('routing', ['router' => 'osrm']);
|
|
204
|
+
|
|
205
|
+
return response()->json($routingSettings);
|
|
206
|
+
}
|
|
177
207
|
}
|
|
@@ -34,6 +34,7 @@ class NotifyOrderEvent implements ShouldQueue
|
|
|
34
34
|
$reason = $event->activity ? $event->activity->get('details') : '';
|
|
35
35
|
NotificationRegistry::notify(OrderCanceled::class, $order, $reason, $event->waypoint);
|
|
36
36
|
}
|
|
37
|
+
|
|
37
38
|
if ($event instanceof \Fleetbase\FleetOps\Events\OrderCompleted) {
|
|
38
39
|
NotificationRegistry::notify(OrderCompleted::class, $order, $event->waypoint);
|
|
39
40
|
}
|
|
@@ -1173,6 +1173,12 @@ class Order extends Model
|
|
|
1173
1173
|
{
|
|
1174
1174
|
$this->status = 'canceled';
|
|
1175
1175
|
|
|
1176
|
+
// if saving update the status and add the cancel activity
|
|
1177
|
+
$this->loadMissing('orderConfig');
|
|
1178
|
+
$canceledActivity = $this->orderConfig->getCanceledActivity();
|
|
1179
|
+
$this->updateActivity($canceledActivity);
|
|
1180
|
+
|
|
1181
|
+
// trigger integrated vendor cancelation
|
|
1176
1182
|
if ($this->isIntegratedVendorOrder()) {
|
|
1177
1183
|
$api = $this->facilitator->api();
|
|
1178
1184
|
|
|
@@ -1181,7 +1187,7 @@ class Order extends Model
|
|
|
1181
1187
|
}
|
|
1182
1188
|
}
|
|
1183
1189
|
|
|
1184
|
-
return event(new OrderCanceled($this));
|
|
1190
|
+
return dispatch(fn () => event(new OrderCanceled($this)))->afterCommit();
|
|
1185
1191
|
}
|
|
1186
1192
|
|
|
1187
1193
|
/**
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Models;
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Casts\Json;
|
|
6
|
+
use Fleetbase\FleetOps\Events\EntityActivityChanged;
|
|
7
|
+
use Fleetbase\FleetOps\Events\EntityCompleted;
|
|
6
8
|
use Fleetbase\FleetOps\Events\WaypointActivityChanged;
|
|
7
9
|
use Fleetbase\FleetOps\Events\WaypointCompleted;
|
|
8
10
|
use Fleetbase\FleetOps\Flow\Activity;
|
|
@@ -337,11 +339,13 @@ class Payload extends Model
|
|
|
337
339
|
}
|
|
338
340
|
|
|
339
341
|
// Handle customer assosciation for waypoint
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
342
|
+
$customerId = data_get($attributes, 'customer_uuid');
|
|
343
|
+
$customerType = data_get($attributes, 'customer_type', 'fleetops:contact');
|
|
344
|
+
if ($customerId && $customerType) {
|
|
345
|
+
$customerTypeNamespace = Utils::getMutationType($customerType);
|
|
346
|
+
$customerExists = app($customerTypeNamespace)->where('uuid', $customerId)->exists();
|
|
343
347
|
if ($customerExists) {
|
|
344
|
-
$waypoint['customer_uuid'] = $
|
|
348
|
+
$waypoint['customer_uuid'] = $customerId;
|
|
345
349
|
$waypoint['customer_type'] = $customerTypeNamespace;
|
|
346
350
|
}
|
|
347
351
|
}
|
|
@@ -392,11 +396,13 @@ class Payload extends Model
|
|
|
392
396
|
}
|
|
393
397
|
|
|
394
398
|
// Handle customer assosciation for waypoint
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
399
|
+
$customerId = data_get($attributes, 'customer_uuid');
|
|
400
|
+
$customerType = data_get($attributes, 'customer_type', 'fleetops:contact');
|
|
401
|
+
if ($customerId && $customerType) {
|
|
402
|
+
$customerTypeNamespace = Utils::getMutationType($customerType);
|
|
403
|
+
$customerExists = app($customerTypeNamespace)->where('uuid', $customerId)->exists();
|
|
398
404
|
if ($customerExists) {
|
|
399
|
-
$waypoint['customer_uuid'] = $
|
|
405
|
+
$waypoint['customer_uuid'] = $customerId;
|
|
400
406
|
$waypoint['customer_type'] = $customerTypeNamespace;
|
|
401
407
|
}
|
|
402
408
|
}
|
|
@@ -792,6 +798,11 @@ class Payload extends Model
|
|
|
792
798
|
$entities = $this->entities->where('destination_uuid', $this->current_waypoint_uuid);
|
|
793
799
|
foreach ($entities as $entity) {
|
|
794
800
|
$entity->insertActivity($activity, $location, $proof);
|
|
801
|
+
if ($activity && $activity->complete()) {
|
|
802
|
+
event(new EntityCompleted($entity, $activity));
|
|
803
|
+
} else {
|
|
804
|
+
event(new EntityActivityChanged($entity, $activity));
|
|
805
|
+
}
|
|
795
806
|
}
|
|
796
807
|
|
|
797
808
|
// if this activity completes the waypoint notify waypoint customer
|
|
@@ -366,6 +366,22 @@ class Place extends Model
|
|
|
366
366
|
return static::createFromGoogleAddress($results->first(), $saveInstance);
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Create a new Place instance from a geocoding lookup.
|
|
371
|
+
*
|
|
372
|
+
* @return \Fleetbase\Models\Place|null
|
|
373
|
+
*/
|
|
374
|
+
public static function getValuesFromGeocodingLookup(string $address): array
|
|
375
|
+
{
|
|
376
|
+
$results = \Geocoder\Laravel\Facades\Geocoder::geocode($address)->get();
|
|
377
|
+
|
|
378
|
+
if ($results->isEmpty() || !$results->first()) {
|
|
379
|
+
return ['street1' => $address];
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return static::getGoogleAddressArray($results->first());
|
|
383
|
+
}
|
|
384
|
+
|
|
369
385
|
/**
|
|
370
386
|
* Create a new Place instance from a geocoding lookup.
|
|
371
387
|
*
|
|
@@ -482,12 +498,12 @@ class Place extends Model
|
|
|
482
498
|
if (is_string($place)) {
|
|
483
499
|
// Check if $place is a valid public_id, return matching Place object if found
|
|
484
500
|
if (Utils::isPublicId($place)) {
|
|
485
|
-
return
|
|
501
|
+
return static::where('public_id', $place)->first();
|
|
486
502
|
}
|
|
487
503
|
|
|
488
504
|
// Check if $place is a valid uuid, return matching Place object if found
|
|
489
505
|
if (Str::isUuid($place)) {
|
|
490
|
-
return
|
|
506
|
+
return static::where('uuid', $place)->first();
|
|
491
507
|
}
|
|
492
508
|
|
|
493
509
|
// Attempt to find by address or name
|
|
@@ -521,12 +537,27 @@ class Place extends Model
|
|
|
521
537
|
$uuid = data_get($place, 'uuid');
|
|
522
538
|
|
|
523
539
|
// If $place has a valid uuid and a matching Place object exists, return the uuid
|
|
524
|
-
if (Str::isUuid($uuid) && $existingPlace =
|
|
540
|
+
if (Str::isUuid($uuid) && $existingPlace = static::where('uuid', $uuid)->first()) {
|
|
525
541
|
return $existingPlace;
|
|
526
542
|
}
|
|
527
543
|
|
|
528
|
-
//
|
|
529
|
-
|
|
544
|
+
// If has $attributes['address']
|
|
545
|
+
if (!empty($place['address'])) {
|
|
546
|
+
return static::createFromGeocodingLookup($place['address'], $saveInstance);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Perform google lookup to fill address
|
|
550
|
+
$street1 = $place['street1'];
|
|
551
|
+
if ($street1) {
|
|
552
|
+
return static::create(array_merge($place, static::getValuesFromGeocodingLookup($street1)));
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Otherwise, create a new Place owith the given attributes
|
|
556
|
+
if (empty($place['location'])) {
|
|
557
|
+
$place['location'] = new SpatialPoint(0, 0);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
return static::create($place);
|
|
530
561
|
}
|
|
531
562
|
// If $place is a GoogleAddress object
|
|
532
563
|
elseif ($place instanceof \Geocoder\Provider\GoogleMaps\Model\GoogleAddress) {
|
|
@@ -547,10 +578,10 @@ class Place extends Model
|
|
|
547
578
|
{
|
|
548
579
|
if (Utils::isCoordinatesStrict($place)) {
|
|
549
580
|
// create a place from coordinates using reverse loopup
|
|
550
|
-
return
|
|
581
|
+
return static::insertFromCoordinates($place);
|
|
551
582
|
} elseif (is_string($place)) {
|
|
552
583
|
if (Utils::isPublicId($place)) {
|
|
553
|
-
$resolvedPlace =
|
|
584
|
+
$resolvedPlace = static::where('public_id', $place)->first();
|
|
554
585
|
|
|
555
586
|
if ($resolvedPlace) {
|
|
556
587
|
return $resolvedPlace->uuid;
|
|
@@ -558,14 +589,19 @@ class Place extends Model
|
|
|
558
589
|
}
|
|
559
590
|
|
|
560
591
|
if (Str::isUuid($place)) {
|
|
561
|
-
$resolvedPlace =
|
|
592
|
+
$resolvedPlace = static::where('uuid', $place)->first();
|
|
562
593
|
|
|
563
594
|
if ($resolvedPlace) {
|
|
564
595
|
return $resolvedPlace->uuid;
|
|
565
596
|
}
|
|
566
597
|
}
|
|
567
598
|
|
|
568
|
-
|
|
599
|
+
// handle address if set
|
|
600
|
+
if (!empty($place['address'])) {
|
|
601
|
+
return static::insertFromGeocodingLookup($place['address']);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return static::insertFromGeocodingLookup($place);
|
|
569
605
|
} elseif (is_array($place) || is_object($place)) {
|
|
570
606
|
// if place already exists just return uuid
|
|
571
607
|
if (static::isValidPlaceUuid(data_get($place, 'uuid'))) {
|
|
@@ -592,12 +628,12 @@ class Place extends Model
|
|
|
592
628
|
|
|
593
629
|
public static function isValidPlaceUuid($uuid): bool
|
|
594
630
|
{
|
|
595
|
-
return is_string($uuid) && Str::isUuid($uuid) &&
|
|
631
|
+
return is_string($uuid) && Str::isUuid($uuid) && static::where('uuid', $uuid)->exists();
|
|
596
632
|
}
|
|
597
633
|
|
|
598
634
|
public static function isValidPlacePublicId($publicId): bool
|
|
599
635
|
{
|
|
600
|
-
return is_string($publicId) && Utils::isPublicId($publicId) &&
|
|
636
|
+
return is_string($publicId) && Utils::isPublicId($publicId) && static::where('public_id', $publicId)->exists();
|
|
601
637
|
}
|
|
602
638
|
|
|
603
639
|
/**
|
|
@@ -717,7 +753,7 @@ class Place extends Model
|
|
|
717
753
|
return null;
|
|
718
754
|
}
|
|
719
755
|
|
|
720
|
-
$place =
|
|
756
|
+
$place = static::createFromGeocodingLookup($address, false);
|
|
721
757
|
foreach ($addressFields as $field => $options) {
|
|
722
758
|
if ($place->isFillable($field) && empty($place->{$field})) {
|
|
723
759
|
$value = Utils::or($row, array_merge([$field], $options['alias']));
|
|
@@ -783,7 +819,7 @@ class Place extends Model
|
|
|
783
819
|
* $data = ['address' => '123 Main St, Anytown, USA'];
|
|
784
820
|
* $place = Place::createFromImport($data, true);
|
|
785
821
|
*/
|
|
786
|
-
public static function createFromImport(array $row, bool $saveInstance = false): Place
|
|
822
|
+
public static function createFromImport(array $row, bool $saveInstance = false): ?Place
|
|
787
823
|
{
|
|
788
824
|
// Filter array for null key values
|
|
789
825
|
$row = array_filter($row);
|
package/server/src/routes.php
CHANGED
|
@@ -469,6 +469,8 @@ Route::prefix(config('fleetops.api.routing.prefix', null))->namespace('Fleetbase
|
|
|
469
469
|
$router->get('notification-registry', 'SettingController@getNotificationRegistry');
|
|
470
470
|
$router->get('notification-settings', 'SettingController@getNotificationSettings');
|
|
471
471
|
$router->post('notification-settings', 'SettingController@saveNotificationSettings');
|
|
472
|
+
$router->get('routing-settings', 'SettingController@getRoutingSettings');
|
|
473
|
+
$router->post('routing-settings', 'SettingController@saveRoutingSettings');
|
|
472
474
|
}
|
|
473
475
|
);
|
|
474
476
|
$router->group(
|
package/translations/en-us.yaml
CHANGED
|
@@ -298,6 +298,7 @@ fleet-ops:
|
|
|
298
298
|
loading-vehicle: Loading fleet vehicles...
|
|
299
299
|
layout:
|
|
300
300
|
fleet-ops-sidebar:
|
|
301
|
+
routing: Routing
|
|
301
302
|
notifications: Notifications
|
|
302
303
|
payments: Payments
|
|
303
304
|
navigator-app: Navigator App
|
|
@@ -1635,6 +1636,10 @@ fleet-ops:
|
|
|
1635
1636
|
fleet-ops-notification-settings: Fleet-Ops Notification Settings
|
|
1636
1637
|
fleet-ops-notifications: Fleet-Ops Notifications
|
|
1637
1638
|
configure-notifications: Configure Notifications
|
|
1639
|
+
routing:
|
|
1640
|
+
fleet-ops-routing-settings: Fleet-Ops Routing Settings
|
|
1641
|
+
fleet-ops-routing: Fleet-Ops Routing
|
|
1642
|
+
configure-routing: Configure Routing
|
|
1638
1643
|
navigator-app:
|
|
1639
1644
|
navigator-app-settings: Navigator App Settings
|
|
1640
1645
|
payments:
|