@fleetbase/fleetops-engine 0.3.6 → 0.3.8
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/navigator-app.hbs +6 -3
- package/addon/components/layout/fleet-ops-sidebar/fleet-listing.hbs +5 -1
- package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +98 -1
- package/addon/components/layout/fleet-ops-sidebar.hbs +5 -1
- package/addon/components/layout/fleet-ops-sidebar.js +1 -0
- package/addon/controllers/management/drivers/index/edit.js +0 -26
- package/addon/engine.js +4 -4
- package/addon/styles/fleetops-engine.css +17 -0
- package/addon/templates/operations/service-rates/index/new.hbs +1 -1
- package/composer.json +2 -2
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/config/fleetops.php +4 -1
- package/server/src/Casts/MultiPolygon.php +14 -3
- package/server/src/Casts/Point.php +12 -2
- package/server/src/Casts/Polygon.php +19 -4
- package/server/src/Http/Controllers/Api/v1/DriverController.php +34 -18
- package/server/src/Http/Controllers/Api/v1/EntityController.php +36 -1
- package/server/src/Http/Controllers/Api/v1/LabelController.php +2 -2
- package/server/src/Http/Controllers/Api/v1/OrderController.php +139 -59
- package/server/src/Http/Controllers/Api/v1/PayloadController.php +20 -12
- package/server/src/Http/Controllers/Api/v1/PlaceController.php +25 -3
- package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +71 -3
- package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +3 -2
- package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +2 -2
- package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +2 -2
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +22 -2
- package/server/src/Http/Controllers/Api/v1/ZoneController.php +59 -3
- package/server/src/Http/Controllers/Internal/v1/DriverController.php +148 -0
- package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +38 -0
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +11 -1
- package/server/src/Http/Filter/TrackingStatusFilter.php +10 -0
- package/server/src/Http/Requests/CancelOrderRequest.php +1 -2
- package/server/src/Http/Requests/CreateContactRequest.php +5 -4
- package/server/src/Http/Requests/CreateDriverRequest.php +13 -11
- package/server/src/Http/Requests/CreateEntityRequest.php +7 -4
- package/server/src/Http/Requests/CreateOrderRequest.php +2 -2
- package/server/src/Http/Requests/CreatePayloadRequest.php +1 -1
- package/server/src/Http/Requests/CreatePlaceRequest.php +46 -4
- package/server/src/Http/Requests/CreatePurchaseRateRequest.php +3 -2
- package/server/src/Http/Requests/CreateServiceAreaRequest.php +24 -4
- package/server/src/Http/Requests/CreateServiceRateRequest.php +22 -21
- package/server/src/Http/Requests/CreateTrackingStatusRequest.php +9 -8
- package/server/src/Http/Requests/CreateVehicleRequest.php +6 -4
- package/server/src/Http/Requests/CreateZoneRequest.php +24 -5
- package/server/src/Http/Requests/QueryServiceQuotesRequest.php +11 -10
- package/server/src/Http/Requests/ScheduleOrderRequest.php +32 -0
- package/server/src/Http/Requests/UpdateContactRequest.php +0 -13
- package/server/src/Http/Requests/UpdateServiceAreaRequest.php +1 -23
- package/server/src/Http/Requests/UpdateServiceQuoteRequest.php +1 -23
- package/server/src/Http/Requests/UpdateServiceRateRequest.php +1 -23
- package/server/src/Http/Requests/UpdateTrackingStatusRequest.php +1 -26
- package/server/src/Http/Resources/v1/DeletedResource.php +2 -9
- package/server/src/Http/Resources/v1/Entity.php +47 -44
- package/server/src/Http/Resources/v1/Order.php +1 -1
- package/server/src/Http/Resources/v1/ServiceArea.php +2 -2
- package/server/src/Http/Resources/v1/Vehicle.php +1 -3
- package/server/src/Http/Resources/v1/Zone.php +2 -4
- package/server/src/Models/Entity.php +99 -3
- package/server/src/Models/Order.php +75 -7
- package/server/src/Models/Payload.php +104 -33
- package/server/src/Models/Place.php +56 -17
- package/server/src/Models/ServiceArea.php +285 -18
- package/server/src/Models/ServiceRate.php +10 -6
- package/server/src/Models/TrackingNumber.php +18 -24
- package/server/src/Models/TrackingStatus.php +2 -6
- package/server/src/Models/Vehicle.php +2 -2
- package/server/src/Models/Waypoint.php +0 -10
- package/server/src/Models/Zone.php +132 -5
- package/server/src/Support/Flow.php +17 -3
- package/server/src/Support/Utils.php +143 -9
- package/server/src/routes.php +58 -3
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
namespace Fleetbase\FleetOps\Http\Resources\v1;
|
|
4
4
|
|
|
5
|
-
use Fleetbase\FleetOps\Support\Utils;
|
|
6
5
|
use Fleetbase\Http\Resources\FleetbaseResource;
|
|
7
6
|
use Fleetbase\Support\Http;
|
|
8
|
-
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
|
|
9
7
|
|
|
10
8
|
class Zone extends FleetbaseResource
|
|
11
9
|
{
|
|
@@ -24,7 +22,7 @@ class Zone extends FleetbaseResource
|
|
|
24
22
|
'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
|
|
25
23
|
'name' => $this->name,
|
|
26
24
|
'description' => $this->description,
|
|
27
|
-
'
|
|
25
|
+
'center' => $this->location,
|
|
28
26
|
'border' => $this->border,
|
|
29
27
|
'color' => $this->color,
|
|
30
28
|
'stroke_color' => $this->stroke_color,
|
|
@@ -45,7 +43,7 @@ class Zone extends FleetbaseResource
|
|
|
45
43
|
'id' => $this->public_id,
|
|
46
44
|
'name' => $this->name,
|
|
47
45
|
'description' => $this->description,
|
|
48
|
-
'
|
|
46
|
+
'center' => $this->location,
|
|
49
47
|
'border' => $this->border,
|
|
50
48
|
'color' => $this->color,
|
|
51
49
|
'stroke_color' => $this->stroke_color,
|
|
@@ -197,7 +197,7 @@ class Entity extends Model
|
|
|
197
197
|
*/
|
|
198
198
|
public function payload()
|
|
199
199
|
{
|
|
200
|
-
return $this->belongsTo(Payload::class);
|
|
200
|
+
return $this->belongsTo(Payload::class)->without(['entities']);
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
/**
|
|
@@ -273,7 +273,7 @@ class Entity extends Model
|
|
|
273
273
|
/**
|
|
274
274
|
* The length the entity belongs to.
|
|
275
275
|
*
|
|
276
|
-
* @var PhpUnitsOfMeasure\PhysicalQuantity\Length
|
|
276
|
+
* @var \PhpUnitsOfMeasure\PhysicalQuantity\Length
|
|
277
277
|
*/
|
|
278
278
|
public function getLengthUnitAttribute()
|
|
279
279
|
{
|
|
@@ -283,7 +283,7 @@ class Entity extends Model
|
|
|
283
283
|
/**
|
|
284
284
|
* The width the entity belongs to.
|
|
285
285
|
*
|
|
286
|
-
* @var PhpUnitsOfMeasure\PhysicalQuantity\Length
|
|
286
|
+
* @var \PhpUnitsOfMeasure\PhysicalQuantity\Length
|
|
287
287
|
*/
|
|
288
288
|
public function getWidthUnitAttribute()
|
|
289
289
|
{
|
|
@@ -350,6 +350,72 @@ class Entity extends Model
|
|
|
350
350
|
return data_get($this, 'trackingNumber.last_status');
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
+
public function setDestination($destinationKey, Payload $payload, bool $save = true): Entity
|
|
354
|
+
{
|
|
355
|
+
// if waypoint index provided
|
|
356
|
+
if (is_numeric($destinationKey)) {
|
|
357
|
+
$waypoint = $payload->waypoints->values()->get($destinationKey);
|
|
358
|
+
|
|
359
|
+
if ($waypoint) {
|
|
360
|
+
$this->destination_uuid = $waypoint->uuid;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// if explicitly set to pickup
|
|
365
|
+
if ($destinationKey === 'pickup' && $payload->pickup) {
|
|
366
|
+
$this->destination_uuid = $payload->pickup->uuid;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// if explicitly set to dropoff
|
|
370
|
+
if ($destinationKey === 'dropoff' && $payload->dropoff) {
|
|
371
|
+
$this->destination_uuid = $payload->dropoff->uuid;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// if waypoint public_id
|
|
375
|
+
if (Utils::isPublicId($destinationKey)) {
|
|
376
|
+
$waypoint = $payload->waypoints->firstWhere('public_id', $destinationKey);
|
|
377
|
+
|
|
378
|
+
// if no waypoint found from public_id check pickup/dropoff
|
|
379
|
+
if (!$waypoint) {
|
|
380
|
+
$waypoint = collect([$this->pickup, $this->dropoff])->firstWhere('public_id', $destinationKey);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if ($waypoint) {
|
|
384
|
+
$this->destination_uuid = $waypoint->uuid;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// if waypoint uuid
|
|
389
|
+
if (Str::isUuid($destinationKey)) {
|
|
390
|
+
$waypoint = $payload->waypoints->firstWhere('uuid', $destinationKey);
|
|
391
|
+
|
|
392
|
+
// if no waypoint found from uuid check pickup/dropoff
|
|
393
|
+
if (!$waypoint) {
|
|
394
|
+
$waypoint = collect([$payload->pickup, $payload->dropoff])->firstWhere('uuid', $destinationKey);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if ($waypoint) {
|
|
398
|
+
$this->destination_uuid = $waypoint->uuid;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// confirm destination_uuid is indeed a place record
|
|
403
|
+
if (isset($attributes['destination_uuid']) && Place::where('uuid', $attributes['destination_uuid'])->doesntExist()) {
|
|
404
|
+
// search waypoints for search_uuid if any
|
|
405
|
+
$destination = Place::where('meta->search_uuid', $attributes['destination_uuid'])->first();
|
|
406
|
+
|
|
407
|
+
if ($destination instanceof Place) {
|
|
408
|
+
$this->destination_uuid = $destination->uuid;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if ($save) {
|
|
413
|
+
$this->save();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return $this;
|
|
417
|
+
}
|
|
418
|
+
|
|
353
419
|
public static function insertGetUuid($values = [], Payload $payload = null)
|
|
354
420
|
{
|
|
355
421
|
if (is_array($values) && isset($values['uuid'])) {
|
|
@@ -408,4 +474,34 @@ class Entity extends Model
|
|
|
408
474
|
$this->customer_uuid = $model->uuid;
|
|
409
475
|
$this->customer_type = Utils::getMutationType($model);
|
|
410
476
|
}
|
|
477
|
+
|
|
478
|
+
public function getPayload(): ?Payload
|
|
479
|
+
{
|
|
480
|
+
$this->load('payload');
|
|
481
|
+
|
|
482
|
+
if ($this->payload instanceof Payload) {
|
|
483
|
+
return $this->payload;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (Str::isUuid($this->payload_uuid)) {
|
|
487
|
+
return Payload::where('uuid', $this->payload_uuid)->first();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
public function getTrashedPayload(): ?Payload
|
|
494
|
+
{
|
|
495
|
+
$payload = $this->payload()->withoutGlobalScopes()->first();
|
|
496
|
+
|
|
497
|
+
if ($payload instanceof Payload) {
|
|
498
|
+
return $payload;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (Str::isUuid($this->payload_uuid)) {
|
|
502
|
+
return Payload::where('uuid', $this->payload_uuid)->withoutGlobalScopes()->first();
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return null;
|
|
506
|
+
}
|
|
411
507
|
}
|
|
@@ -604,12 +604,12 @@ class Order extends Model
|
|
|
604
604
|
|
|
605
605
|
public function getIsAssignedNotDispatchedAttribute(): bool
|
|
606
606
|
{
|
|
607
|
-
return !empty($this->driver_assigned_uuid) &&
|
|
607
|
+
return !empty($this->driver_assigned_uuid) && $this->dispatched_at === null;
|
|
608
608
|
}
|
|
609
609
|
|
|
610
610
|
public function getIsNotDispatchedAttribute(): bool
|
|
611
611
|
{
|
|
612
|
-
return
|
|
612
|
+
return $this->dispatched_at === null;
|
|
613
613
|
}
|
|
614
614
|
|
|
615
615
|
public function getIsIntegratedVendorOrderAttribute()
|
|
@@ -894,7 +894,7 @@ class Order extends Model
|
|
|
894
894
|
return !$this->dispatched && Carbon::fromString($this->scheduled_at)->between($min, $max);
|
|
895
895
|
}
|
|
896
896
|
|
|
897
|
-
public function dispatch($save =
|
|
897
|
+
public function dispatch($save = true)
|
|
898
898
|
{
|
|
899
899
|
$this->dispatched = true;
|
|
900
900
|
$this->dispatched_at = now();
|
|
@@ -907,11 +907,42 @@ class Order extends Model
|
|
|
907
907
|
return event(new OrderDispatched($this));
|
|
908
908
|
}
|
|
909
909
|
|
|
910
|
-
public function
|
|
910
|
+
public function insertDispatchActivity(): Order
|
|
911
|
+
{
|
|
912
|
+
// get dispatch activity if any and apply to order
|
|
913
|
+
$dispatchActivity = Flow::getDispatchActivity($this);
|
|
914
|
+
|
|
915
|
+
if ($dispatchActivity) {
|
|
916
|
+
$this->updateActivity($dispatchActivity);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
return $this;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
public function dispatchWithActivity(): Order
|
|
923
|
+
{
|
|
924
|
+
$this->dispatch();
|
|
925
|
+
$this->insertDispatchActivity();
|
|
926
|
+
|
|
927
|
+
return $this;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
public function firstDispatch(): Order
|
|
911
931
|
{
|
|
912
932
|
if ($this->dispatched) {
|
|
913
933
|
$this->dispatch();
|
|
914
934
|
}
|
|
935
|
+
|
|
936
|
+
return $this;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
public function firstDispatchWithActivity(): Order
|
|
940
|
+
{
|
|
941
|
+
if ($this->dispatched) {
|
|
942
|
+
$this->dispatchWithActivity();
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
return $this;
|
|
915
946
|
}
|
|
916
947
|
|
|
917
948
|
public function cancel()
|
|
@@ -936,6 +967,22 @@ class Order extends Model
|
|
|
936
967
|
}
|
|
937
968
|
}
|
|
938
969
|
|
|
970
|
+
public function updateActivity(array $activity = null, $proof = null): Order
|
|
971
|
+
{
|
|
972
|
+
$status = data_get($activity, 'status');
|
|
973
|
+
$details = data_get($activity, 'details', '');
|
|
974
|
+
$code = data_get($activity, 'code', 'dispatched');
|
|
975
|
+
$location = $this->getLastLocation();
|
|
976
|
+
|
|
977
|
+
// insert dispatch activity
|
|
978
|
+
$this->insertActivity($status, $details, $location, $code, $proof);
|
|
979
|
+
|
|
980
|
+
// update status using code
|
|
981
|
+
$this->setStatus($code, true);
|
|
982
|
+
|
|
983
|
+
return $this;
|
|
984
|
+
}
|
|
985
|
+
|
|
939
986
|
public function notifyCompleted()
|
|
940
987
|
{
|
|
941
988
|
return event(new OrderCompleted($this));
|
|
@@ -950,7 +997,13 @@ class Order extends Model
|
|
|
950
997
|
public function setCustomerTypeAttribute($type)
|
|
951
998
|
{
|
|
952
999
|
if (is_string($type)) {
|
|
953
|
-
|
|
1000
|
+
$isNotNamespace = !Str::contains($type, '\\');
|
|
1001
|
+
$doesNotStartWithFleetOps = !Str::startsWith($type, 'fleet-ops');
|
|
1002
|
+
$isValidType = $type === 'customer' || $type === 'vendor';
|
|
1003
|
+
|
|
1004
|
+
// preprend fleet-ops IF not a namespace and does not start with fleet-ops
|
|
1005
|
+
// this is for handling ember style registry spacing
|
|
1006
|
+
if ($isNotNamespace && $doesNotStartWithFleetOps && $isValidType) {
|
|
954
1007
|
$type = 'fleet-ops:' . $type;
|
|
955
1008
|
}
|
|
956
1009
|
|
|
@@ -961,7 +1014,13 @@ class Order extends Model
|
|
|
961
1014
|
public function setFacilitatorTypeAttribute($type)
|
|
962
1015
|
{
|
|
963
1016
|
if (is_string($type)) {
|
|
964
|
-
|
|
1017
|
+
$isNotNamespace = !Str::contains($type, '\\');
|
|
1018
|
+
$doesNotStartWithFleetOps = !Str::startsWith($type, 'fleet-ops');
|
|
1019
|
+
$isValidType = $type === 'customer' || $type === 'vendor';
|
|
1020
|
+
|
|
1021
|
+
// preprend fleet-ops IF not a namespace and does not start with fleet-ops
|
|
1022
|
+
// this is for handling ember style registry spacing
|
|
1023
|
+
if ($isNotNamespace && $doesNotStartWithFleetOps && $isValidType) {
|
|
965
1024
|
$type = 'fleet-ops:' . $type;
|
|
966
1025
|
}
|
|
967
1026
|
|
|
@@ -1087,7 +1146,16 @@ class Order extends Model
|
|
|
1087
1146
|
public function getCurrentOriginPosition()
|
|
1088
1147
|
{
|
|
1089
1148
|
if ($this->hasDriverAssigned) {
|
|
1090
|
-
|
|
1149
|
+
$this->load(['driverAssigned']);
|
|
1150
|
+
$driverAssigned = $this->driverAssigned;
|
|
1151
|
+
|
|
1152
|
+
if (!$driverAssigned) {
|
|
1153
|
+
$driverAssigned = Driver::where('uuid', $this->driver_assigned_uuid)->first();
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if ($driverAssigned instanceof Driver) {
|
|
1157
|
+
return $driverAssigned->location;
|
|
1158
|
+
}
|
|
1091
1159
|
}
|
|
1092
1160
|
|
|
1093
1161
|
$origin = null;
|
|
@@ -12,6 +12,7 @@ use Fleetbase\Traits\HasPublicId;
|
|
|
12
12
|
use Fleetbase\Traits\HasUuid;
|
|
13
13
|
use Fleetbase\Traits\TracksApiCredential;
|
|
14
14
|
use Grimzy\LaravelMysqlSpatial\Types\Point;
|
|
15
|
+
use Illuminate\Support\Facades\DB;
|
|
15
16
|
use Illuminate\Support\Str;
|
|
16
17
|
|
|
17
18
|
class Payload extends Model
|
|
@@ -183,16 +184,6 @@ class Payload extends Model
|
|
|
183
184
|
return $this->hasManyThrough(Place::class, Waypoint::class, 'payload_uuid', 'uuid', 'uuid', 'place_uuid')->whereNull('waypoints.deleted_at')->withoutGlobalScopes();
|
|
184
185
|
}
|
|
185
186
|
|
|
186
|
-
/**
|
|
187
|
-
* Waypoints between start and end.
|
|
188
|
-
*
|
|
189
|
-
* @return \Illuminate\Database\Eloquent\Concerns\HasManyThrough
|
|
190
|
-
*/
|
|
191
|
-
public function waypointsCompleted()
|
|
192
|
-
{
|
|
193
|
-
return $this->hasManyThrough(Place::class, WaypointCompleted::class, 'payload_uuid', 'uuid', 'uuid', 'place_uuid')->withoutGlobalScopes();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
187
|
/**
|
|
197
188
|
* Always convert fee and rate to integer before insert.
|
|
198
189
|
*/
|
|
@@ -216,20 +207,16 @@ class Payload extends Model
|
|
|
216
207
|
}
|
|
217
208
|
}
|
|
218
209
|
|
|
219
|
-
//
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
$destination
|
|
223
|
-
|
|
210
|
+
// if a destination or waypoint is explicitly set
|
|
211
|
+
if (empty($attributes['destination_uuid'])) {
|
|
212
|
+
$destinationKey = Utils::or($attributes, ['waypoint', 'destination']);
|
|
213
|
+
$destination = $this->findDestinationFromKey($destinationKey);
|
|
224
214
|
if ($destination instanceof Place) {
|
|
225
215
|
$attributes['destination_uuid'] = $destination->uuid;
|
|
226
|
-
} else {
|
|
227
|
-
unset($attributes['destination_uuid']);
|
|
228
216
|
}
|
|
229
217
|
}
|
|
230
218
|
|
|
231
219
|
$entity = new Entity($attributes);
|
|
232
|
-
|
|
233
220
|
$this->entities()->save($entity);
|
|
234
221
|
}
|
|
235
222
|
|
|
@@ -253,15 +240,12 @@ class Payload extends Model
|
|
|
253
240
|
}
|
|
254
241
|
}
|
|
255
242
|
|
|
256
|
-
//
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
$destination
|
|
260
|
-
|
|
243
|
+
// if a destination or waypoint is explicitly set
|
|
244
|
+
if (empty($attributes['destination_uuid'])) {
|
|
245
|
+
$destinationKey = Utils::or($attributes, ['waypoint', 'destination']);
|
|
246
|
+
$destination = $this->findDestinationFromKey($destinationKey);
|
|
261
247
|
if ($destination instanceof Place) {
|
|
262
248
|
$attributes['destination_uuid'] = $destination->uuid;
|
|
263
|
-
} else {
|
|
264
|
-
unset($attributes['destination_uuid']);
|
|
265
249
|
}
|
|
266
250
|
}
|
|
267
251
|
|
|
@@ -277,8 +261,8 @@ class Payload extends Model
|
|
|
277
261
|
{
|
|
278
262
|
$this->current_waypoint_uuid = $destination->uuid;
|
|
279
263
|
|
|
280
|
-
if ($
|
|
281
|
-
$this->
|
|
264
|
+
if ($save) {
|
|
265
|
+
DB::table($this->getTable())->where('uuid', $this->uuid)->update(['current_waypoint_uuid' => $destination->uuid]);
|
|
282
266
|
}
|
|
283
267
|
|
|
284
268
|
return $this;
|
|
@@ -429,7 +413,7 @@ class Payload extends Model
|
|
|
429
413
|
}
|
|
430
414
|
|
|
431
415
|
if ($this->waypoints()->count()) {
|
|
432
|
-
return $this->waypoints->
|
|
416
|
+
return $this->waypoints->last();
|
|
433
417
|
}
|
|
434
418
|
|
|
435
419
|
return null;
|
|
@@ -449,7 +433,7 @@ class Payload extends Model
|
|
|
449
433
|
}
|
|
450
434
|
|
|
451
435
|
if ($this->waypoints()->count()) {
|
|
452
|
-
return $this->waypoints->
|
|
436
|
+
return $this->waypoints->first();
|
|
453
437
|
}
|
|
454
438
|
|
|
455
439
|
return null;
|
|
@@ -529,6 +513,19 @@ class Payload extends Model
|
|
|
529
513
|
}
|
|
530
514
|
}
|
|
531
515
|
|
|
516
|
+
// ensure all stops/waypoints are instances of Place
|
|
517
|
+
$stops = $stops->map(function ($place) {
|
|
518
|
+
if (is_array($place)) {
|
|
519
|
+
return new Place($place);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if ($place instanceof Place) {
|
|
523
|
+
return $place;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return null;
|
|
527
|
+
});
|
|
528
|
+
|
|
532
529
|
return $stops->filter();
|
|
533
530
|
}
|
|
534
531
|
|
|
@@ -557,10 +554,6 @@ class Payload extends Model
|
|
|
557
554
|
|
|
558
555
|
public function setPlace($property, Place $place, array $options = [])
|
|
559
556
|
{
|
|
560
|
-
if (!$place) {
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
557
|
$attr = $property . '_uuid';
|
|
565
558
|
$instance = Place::createFromMixed($place);
|
|
566
559
|
$save = data_get($options, 'save', false);
|
|
@@ -596,16 +589,28 @@ class Payload extends Model
|
|
|
596
589
|
return;
|
|
597
590
|
}
|
|
598
591
|
|
|
592
|
+
if (!$place instanceof Place) {
|
|
593
|
+
$place = Place::createFromMixed($place);
|
|
594
|
+
}
|
|
595
|
+
|
|
599
596
|
return $this->setPlace('pickup', $place, $options);
|
|
600
597
|
}
|
|
601
598
|
|
|
602
599
|
public function setDropoff($place, array $options = [])
|
|
603
600
|
{
|
|
601
|
+
if (!$place instanceof Place) {
|
|
602
|
+
$place = Place::createFromMixed($place);
|
|
603
|
+
}
|
|
604
|
+
|
|
604
605
|
return $this->setPlace('dropoff', $place, $options);
|
|
605
606
|
}
|
|
606
607
|
|
|
607
608
|
public function setReturn($place, array $options = [])
|
|
608
609
|
{
|
|
610
|
+
if (!$place instanceof Place) {
|
|
611
|
+
$place = Place::createFromMixed($place);
|
|
612
|
+
}
|
|
613
|
+
|
|
609
614
|
return $this->setPlace('return', $place, $options);
|
|
610
615
|
}
|
|
611
616
|
|
|
@@ -714,4 +719,70 @@ class Payload extends Model
|
|
|
714
719
|
|
|
715
720
|
return null;
|
|
716
721
|
}
|
|
722
|
+
|
|
723
|
+
public function findDestinationFromKey(string $destinationKey = null): ?Place
|
|
724
|
+
{
|
|
725
|
+
if ($destinationKey === null) {
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// if waypoint index provided
|
|
730
|
+
if (is_numeric($destinationKey)) {
|
|
731
|
+
$waypoint = $this->waypoints->values()->get($destinationKey);
|
|
732
|
+
|
|
733
|
+
if ($waypoint) {
|
|
734
|
+
return $waypoint;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// if explicitly set to pickup
|
|
739
|
+
if ($destinationKey === 'pickup' && $this->pickup) {
|
|
740
|
+
return $this->pickup;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
// if explicitly set to dropoff
|
|
744
|
+
if ($destinationKey === 'dropoff' && $this->dropoff) {
|
|
745
|
+
return $this->dropoff;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// if waypoint public_id
|
|
749
|
+
if (Utils::isPublicId($destinationKey)) {
|
|
750
|
+
$waypoint = $this->waypoints->firstWhere('public_id', $destinationKey);
|
|
751
|
+
|
|
752
|
+
// if no waypoint found from public_id check pickup/dropoff
|
|
753
|
+
if (!$waypoint) {
|
|
754
|
+
$waypoint = collect([$this->pickup, $this->dropoff])->firstWhere('public_id', $destinationKey);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
if ($waypoint) {
|
|
758
|
+
return $waypoint;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// if waypoint uuid
|
|
763
|
+
if (Str::isUuid($destinationKey)) {
|
|
764
|
+
$waypoint = $this->waypoints->firstWhere('uuid', $destinationKey);
|
|
765
|
+
|
|
766
|
+
// if no waypoint found from uuid check pickup/dropoff
|
|
767
|
+
if (!$waypoint) {
|
|
768
|
+
$waypoint = collect([$this->pickup, $this->dropoff])->firstWhere('uuid', $destinationKey);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
if ($waypoint) {
|
|
772
|
+
return $waypoint;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// confirm destination_uuid is indeed a place record
|
|
777
|
+
if (isset($attributes['destination_uuid']) && Place::where('uuid', $attributes['destination_uuid'])->doesntExist()) {
|
|
778
|
+
// search waypoints for search_uuid if any
|
|
779
|
+
$destination = Place::where('meta->search_uuid', $attributes['destination_uuid'])->first();
|
|
780
|
+
|
|
781
|
+
if ($destination instanceof Place) {
|
|
782
|
+
return $destination;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
return null;
|
|
787
|
+
}
|
|
717
788
|
}
|
|
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Models;
|
|
|
4
4
|
|
|
5
5
|
use Fleetbase\Casts\Json;
|
|
6
6
|
use Fleetbase\FleetOps\Casts\Point;
|
|
7
|
+
use Fleetbase\FleetOps\Support\Geocoding;
|
|
7
8
|
use Fleetbase\FleetOps\Support\Utils;
|
|
8
9
|
use Fleetbase\Models\Model;
|
|
9
10
|
use Fleetbase\Traits\HasApiModelBehavior;
|
|
@@ -251,8 +252,10 @@ class Place extends Model
|
|
|
251
252
|
|
|
252
253
|
/**
|
|
253
254
|
* Create a new Place instance from a Google Address instance and optionally save it to the database.
|
|
255
|
+
*
|
|
256
|
+
* @return \Fleetbase\Models\Place|null
|
|
254
257
|
*/
|
|
255
|
-
public static function createFromGoogleAddress(\Geocoder\Provider\GoogleMaps\Model\GoogleAddress $address, bool $saveInstance = false): Place
|
|
258
|
+
public static function createFromGoogleAddress(\Geocoder\Provider\GoogleMaps\Model\GoogleAddress $address, bool $saveInstance = false): ?Place
|
|
256
259
|
{
|
|
257
260
|
$instance = (new static())->fillWithGoogleAddress($address);
|
|
258
261
|
|
|
@@ -279,8 +282,10 @@ class Place extends Model
|
|
|
279
282
|
* Create a new Place instance from a geocoding lookup.
|
|
280
283
|
*
|
|
281
284
|
* @param bool $saveInstance
|
|
285
|
+
*
|
|
286
|
+
* @return \Fleetbase\Models\Place|null
|
|
282
287
|
*/
|
|
283
|
-
public static function createFromGeocodingLookup(string $address, $saveInstance = false): Place
|
|
288
|
+
public static function createFromGeocodingLookup(string $address, $saveInstance = false): ?Place
|
|
284
289
|
{
|
|
285
290
|
$results = \Geocoder\Laravel\Facades\Geocoder::geocode($address)->get();
|
|
286
291
|
|
|
@@ -291,20 +296,49 @@ class Place extends Model
|
|
|
291
296
|
return static::createFromGoogleAddress($results->first(), $saveInstance);
|
|
292
297
|
}
|
|
293
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Create a new Place instance from a geocoding lookup.
|
|
301
|
+
*
|
|
302
|
+
* @param bool $saveInstance
|
|
303
|
+
*
|
|
304
|
+
* @return \Fleetbase\Models\Place|null
|
|
305
|
+
*/
|
|
306
|
+
public static function createFromReverseGeocodingLookup(\Grimzy\LaravelMysqlSpatial\Types\Point $point, $saveInstance = false): ?Place
|
|
307
|
+
{
|
|
308
|
+
$results = Geocoding::reverseFromCoordinates($point->getLat(), $point->getLng());
|
|
309
|
+
$place = $results->first();
|
|
310
|
+
|
|
311
|
+
if (!$place) {
|
|
312
|
+
$place = (new static())->newInstance(['location' => $point]);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if ($saveInstance) {
|
|
316
|
+
$place->save();
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return $place;
|
|
320
|
+
}
|
|
321
|
+
|
|
294
322
|
/**
|
|
295
323
|
* Creates a new Place instance from given coordinates.
|
|
296
324
|
*
|
|
297
|
-
* @param array $
|
|
298
|
-
* @param bool
|
|
325
|
+
* @param \Grimzy\LaravelMysqlSpatial\Types\Point|array $coordinates
|
|
326
|
+
* @param bool $saveInstance
|
|
299
327
|
*
|
|
300
|
-
* @return Place|
|
|
328
|
+
* @return \Fleetbase\Models\Place|null
|
|
301
329
|
*/
|
|
302
|
-
public static function createFromCoordinates($coordinates, $attributes = [], $saveInstance = false)
|
|
330
|
+
public static function createFromCoordinates($coordinates, array $attributes = [], $saveInstance = false): ?Place
|
|
303
331
|
{
|
|
304
332
|
$instance = new Place();
|
|
333
|
+
$point = Utils::getPointFromMixed($coordinates);
|
|
305
334
|
|
|
306
|
-
|
|
307
|
-
|
|
335
|
+
if ($coordinates instanceof \Grimzy\LaravelMysqlSpatial\Types\Point) {
|
|
336
|
+
$latitude = $coordinates->getLat();
|
|
337
|
+
$longitude = $coordinates->getLng();
|
|
338
|
+
} elseif ($point instanceof \Grimzy\LaravelMysqlSpatial\Types\Point) {
|
|
339
|
+
$latitude = $point->getLat();
|
|
340
|
+
$longitude = $point->getLng();
|
|
341
|
+
}
|
|
308
342
|
|
|
309
343
|
$instance->setAttribute('location', new \Grimzy\LaravelMysqlSpatial\Types\Point($latitude, $longitude));
|
|
310
344
|
$instance->fill($attributes);
|
|
@@ -312,7 +346,7 @@ class Place extends Model
|
|
|
312
346
|
$results = \Geocoder\Laravel\Facades\Geocoder::reverse($latitude, $longitude)->get();
|
|
313
347
|
|
|
314
348
|
if ($results->isEmpty()) {
|
|
315
|
-
return
|
|
349
|
+
return null;
|
|
316
350
|
}
|
|
317
351
|
|
|
318
352
|
$instance->fillWithGoogleAddress($results->first());
|
|
@@ -327,15 +361,15 @@ class Place extends Model
|
|
|
327
361
|
/**
|
|
328
362
|
* Inserts a new place into the database using latitude and longitude coordinates.
|
|
329
363
|
*
|
|
364
|
+
* @param \Grimzy\LaravelMysqlSpatial\Types\Point|array $coordinates
|
|
330
365
|
* @param \Grimzy\LaravelMysqlSpatial\Types\Point|string|array $coordinates the coordinates to use for the new place
|
|
331
366
|
*
|
|
332
367
|
* @return mixed returns the UUID of the new place on success or false on failure
|
|
333
368
|
*/
|
|
334
|
-
public static function insertFromCoordinates($coordinates)
|
|
369
|
+
public static function insertFromCoordinates($coordinates, array $attributes = [])
|
|
335
370
|
{
|
|
336
|
-
$attributes = [];
|
|
337
|
-
|
|
338
|
-
$point = Utils::getPointFromMixed($coordinates);
|
|
371
|
+
$attributes = array_merge([], $attributes);
|
|
372
|
+
$point = Utils::getPointFromMixed($coordinates);
|
|
339
373
|
|
|
340
374
|
if ($coordinates instanceof \Grimzy\LaravelMysqlSpatial\Types\Point) {
|
|
341
375
|
$attributes['location'] = $coordinates;
|
|
@@ -365,10 +399,15 @@ class Place extends Model
|
|
|
365
399
|
* @param array $attributes
|
|
366
400
|
* @param bool $saveInstance
|
|
367
401
|
*
|
|
368
|
-
* @return \
|
|
402
|
+
* @return \Fleetbase\Models\Place|null
|
|
369
403
|
*/
|
|
370
|
-
public static function createFromMixed($place, $attributes = [], $saveInstance = true)
|
|
404
|
+
public static function createFromMixed($place, $attributes = [], $saveInstance = true): ?Place
|
|
371
405
|
{
|
|
406
|
+
// If place is already an instance
|
|
407
|
+
if ($place instanceof Place) {
|
|
408
|
+
return $place;
|
|
409
|
+
}
|
|
410
|
+
|
|
372
411
|
// If $place is a string
|
|
373
412
|
if (is_string($place)) {
|
|
374
413
|
// Check if $place is a valid public_id, return matching Place object if found
|
|
@@ -399,7 +438,7 @@ class Place extends Model
|
|
|
399
438
|
}
|
|
400
439
|
// If $place is an array of coordinates
|
|
401
440
|
elseif (Utils::isCoordinatesStrict($place)) {
|
|
402
|
-
return static::
|
|
441
|
+
return static::createFromCoordinates($place, $attributes, $saveInstance);
|
|
403
442
|
}
|
|
404
443
|
// If $place is an array
|
|
405
444
|
elseif (is_array($place)) {
|
|
@@ -421,7 +460,7 @@ class Place extends Model
|
|
|
421
460
|
return static::createFromGoogleAddress($place, $saveInstance);
|
|
422
461
|
}
|
|
423
462
|
|
|
424
|
-
return
|
|
463
|
+
return null;
|
|
425
464
|
}
|
|
426
465
|
|
|
427
466
|
/**
|