@fleetbase/fleetops-engine 0.4.19 → 0.4.21

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 (76) hide show
  1. package/addon/components/activity-event-selector.js +1 -1
  2. package/addon/components/activity-form-panel.js +2 -2
  3. package/addon/components/activity-logic-builder.js +1 -1
  4. package/addon/components/admin/navigator-app.hbs +77 -1
  5. package/addon/components/admin/navigator-app.js +65 -12
  6. package/addon/components/contact-form-panel.js +2 -2
  7. package/addon/components/contact-panel.js +2 -2
  8. package/addon/components/custom-field-form-panel.js +2 -2
  9. package/addon/components/driver-form-panel.js +2 -2
  10. package/addon/components/driver-panel.js +2 -2
  11. package/addon/components/edit-order-route-panel.js +2 -2
  12. package/addon/components/fleet-form-panel.js +2 -2
  13. package/addon/components/fleet-panel/driver-listing.js +1 -1
  14. package/addon/components/fleet-panel/vehicle-listing.js +1 -1
  15. package/addon/components/fleet-panel.js +2 -2
  16. package/addon/components/fuel-report-form-panel.js +2 -2
  17. package/addon/components/fuel-report-panel.js +2 -2
  18. package/addon/components/issue-form-panel.js +2 -2
  19. package/addon/components/issue-panel.js +2 -2
  20. package/addon/components/live-map-drawer.js +2 -2
  21. package/addon/components/order-config-manager/activity-flow.js +1 -1
  22. package/addon/components/order-config-manager/custom-fields.js +1 -1
  23. package/addon/components/order-config-manager/entities.js +1 -1
  24. package/addon/components/order-config-manager-overlay.js +1 -1
  25. package/addon/components/order-config-manager.js +2 -2
  26. package/addon/components/place-form-panel.js +2 -2
  27. package/addon/components/place-panel.js +2 -2
  28. package/addon/components/vehicle-form-panel.js +2 -2
  29. package/addon/components/vehicle-panel.js +2 -2
  30. package/addon/components/vendor-form-panel/create-form.js +1 -1
  31. package/addon/components/vendor-form-panel.js +2 -2
  32. package/addon/components/vendor-panel.js +2 -2
  33. package/composer.json +2 -2
  34. package/extension.json +1 -1
  35. package/package.json +2 -2
  36. package/server/config/fleetops.php +19 -0
  37. package/server/src/Console/Commands/DispatchAdhocOrders.php +44 -30
  38. package/server/src/Console/Commands/DispatchOrders.php +27 -21
  39. package/server/src/Console/Commands/FixInvalidPolymorphicRelationTypeNamespaces.php +96 -0
  40. package/server/src/Console/Commands/TrackOrderDistanceAndTime.php +30 -15
  41. package/server/src/Http/Controllers/Api/v1/DriverController.php +0 -1
  42. package/server/src/Http/Controllers/Api/v1/OrderController.php +49 -2
  43. package/server/src/Http/Controllers/Internal/v1/SettingController.php +20 -0
  44. package/server/src/Http/Filter/ContactFilter.php +5 -0
  45. package/server/src/Http/Filter/DriverFilter.php +5 -0
  46. package/server/src/Http/Filter/EntityFilter.php +18 -0
  47. package/server/src/Http/Filter/FleetFilter.php +5 -0
  48. package/server/src/Http/Filter/FuelReportFilter.php +5 -0
  49. package/server/src/Http/Filter/IssueFilter.php +5 -0
  50. package/server/src/Http/Filter/OrderConfigFilter.php +5 -0
  51. package/server/src/Http/Filter/OrderFilter.php +5 -0
  52. package/server/src/Http/Filter/PayloadFilter.php +18 -0
  53. package/server/src/Http/Filter/PlaceFilter.php +5 -0
  54. package/server/src/Http/Filter/PurchaseRateFilter.php +18 -0
  55. package/server/src/Http/Filter/ServiceAreaFilter.php +5 -0
  56. package/server/src/Http/Filter/ServiceQuoteFilter.php +5 -0
  57. package/server/src/Http/Filter/ServiceRateFilter.php +5 -0
  58. package/server/src/Http/Filter/TrackingNumberFilter.php +18 -0
  59. package/server/src/Http/Filter/TrackingStatusFilter.php +5 -0
  60. package/server/src/Http/Filter/VehicleFilter.php +5 -0
  61. package/server/src/Http/Filter/VendorFilter.php +5 -0
  62. package/server/src/Http/Filter/ZoneFilter.php +5 -0
  63. package/server/src/Http/Resources/v1/Order.php +1 -0
  64. package/server/src/Models/Driver.php +1 -1
  65. package/server/src/Models/Order.php +2 -4
  66. package/server/src/Providers/FleetOpsServiceProvider.php +4 -3
  67. package/server/src/Support/Algo.php +0 -24
  68. package/server/src/Support/DistanceMatrix.php +9 -1
  69. package/server/src/Support/OSRM.php +7 -0
  70. package/server/src/Support/Utils.php +216 -169
  71. package/server/src/routes.php +3 -3
  72. package/translations/en-us.yaml +3 -0
  73. package/addon/utils/apply-context-component-arguments.js +0 -33
  74. package/addon/utils/context-component-callback.js +0 -16
  75. package/app/utils/apply-context-component-arguments.js +0 -1
  76. package/app/utils/context-component-callback.js +0 -1
@@ -3,6 +3,7 @@
3
3
  namespace Fleetbase\FleetOps\Support;
4
4
 
5
5
  use Fleetbase\FleetOps\Flow\Activity;
6
+ use Fleetbase\LaravelMysqlSpatial\Types\Point;
6
7
  use Fleetbase\Support\Utils as FleetbaseUtils;
7
8
  use Illuminate\Support\Arr;
8
9
  use Illuminate\Support\Facades\DB;
@@ -95,11 +96,11 @@ class Utils extends FleetbaseUtils
95
96
  /**
96
97
  * Unpacks a mysql POINT column from binary to array.
97
98
  */
98
- public static function mysqlPointAsGeometry(string $rawPoint): \Fleetbase\LaravelMysqlSpatial\Types\Point
99
+ public static function mysqlPointAsGeometry(string $rawPoint): Point
99
100
  {
100
101
  $coordinates = static::unpackPoint($rawPoint);
101
102
 
102
- return new \Fleetbase\LaravelMysqlSpatial\Types\Point($coordinates['lon'], $coordinates['lat']);
103
+ return new Point($coordinates['lon'], $coordinates['lat']);
103
104
  }
104
105
 
105
106
  /**
@@ -162,7 +163,7 @@ class Utils extends FleetbaseUtils
162
163
  public static function isCoordinates($coordinates): bool
163
164
  {
164
165
  try {
165
- return static::getPointFromMixed($coordinates) instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point;
166
+ return static::getPointFromMixed($coordinates) instanceof Point;
166
167
  } catch (\Throwable $e) {
167
168
  return false;
168
169
  }
@@ -175,9 +176,9 @@ class Utils extends FleetbaseUtils
175
176
  *
176
177
  * @param mixed $coordinates the coordinates input value to extract a coordinate from
177
178
  *
178
- * @return \Fleetbase\LaravelMysqlSpatial\Types\Point the extracted Point object
179
+ * @return Point the extracted Point object
179
180
  */
180
- public static function getPointFromMixed($coordinates): ?\Fleetbase\LaravelMysqlSpatial\Types\Point
181
+ public static function getPointFromMixed($coordinates): ?Point
181
182
  {
182
183
  $latitude = null;
183
184
  $longitude = null;
@@ -199,7 +200,7 @@ class Utils extends FleetbaseUtils
199
200
  $coordinates = $coordinates->getSpatialValue();
200
201
  }
201
202
 
202
- if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
203
+ if ($coordinates instanceof Point) {
203
204
  $latitude = $coordinates->getLat();
204
205
  $longitude = $coordinates->getLng();
205
206
  } elseif (static::isGeoJson($coordinates)) {
@@ -216,7 +217,7 @@ class Utils extends FleetbaseUtils
216
217
 
217
218
  if (static::isJson($coordinatesJson)) {
218
219
  try {
219
- $coordinates = \Fleetbase\LaravelMysqlSpatial\Types\Point::fromJson($coordinatesJson);
220
+ $coordinates = Point::fromJson($coordinatesJson);
220
221
  } catch (\Throwable $e) {
221
222
  if ($coordinatesInGeoJson) {
222
223
  return static::getPointFromMixed($coordinatesInGeoJson);
@@ -312,7 +313,7 @@ class Utils extends FleetbaseUtils
312
313
  $longitude = $coords[1];
313
314
  }
314
315
 
315
- if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
316
+ if ($coordinates instanceof Point) {
316
317
  return $coordinates;
317
318
  }
318
319
 
@@ -321,7 +322,7 @@ class Utils extends FleetbaseUtils
321
322
  throw new \Exception('Attempted to resolve Point from invalid location.');
322
323
  }
323
324
 
324
- return new \Fleetbase\LaravelMysqlSpatial\Types\Point((float) $latitude, (float) $longitude);
325
+ return new Point((float) $latitude, (float) $longitude);
325
326
  }
326
327
 
327
328
  /**
@@ -334,7 +335,7 @@ class Utils extends FleetbaseUtils
334
335
  */
335
336
  public static function isCoordinatesStrict($coordinates)
336
337
  {
337
- return static::getPointFromCoordinatesStrict($coordinates) instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point;
338
+ return static::getPointFromCoordinatesStrict($coordinates) instanceof Point;
338
339
  }
339
340
 
340
341
  /**
@@ -343,15 +344,15 @@ class Utils extends FleetbaseUtils
343
344
  *
344
345
  * @param mixed $coordinates the coordinates, which can be an array, object, or string
345
346
  *
346
- * @return \Fleetbase\LaravelMysqlSpatial\Types\Point Returns the Point instance
347
+ * @return Point Returns the Point instance
347
348
  */
348
- public static function getPointFromCoordinatesStrict($coordinates): ?\Fleetbase\LaravelMysqlSpatial\Types\Point
349
+ public static function getPointFromCoordinatesStrict($coordinates): ?Point
349
350
  {
350
351
  if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Eloquent\SpatialExpression) {
351
352
  $coordinates = $coordinates->getSpatialValue();
352
353
  }
353
354
 
354
- if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
355
+ if ($coordinates instanceof Point) {
355
356
  return $coordinates;
356
357
  }
357
358
 
@@ -363,7 +364,7 @@ class Utils extends FleetbaseUtils
363
364
  }
364
365
 
365
366
  if (static::isJson($coordinatesJson)) {
366
- $coordinates = \Fleetbase\LaravelMysqlSpatial\Types\Point::fromJson($coordinatesJson);
367
+ $coordinates = Point::fromJson($coordinatesJson);
367
368
  }
368
369
  }
369
370
 
@@ -372,7 +373,7 @@ class Utils extends FleetbaseUtils
372
373
  $longitude = static::or($coordinates, ['lon', '_lon', 'long', 'lng', '_lng', '_longitude', 'longitude', 'y', '1']);
373
374
 
374
375
  if (is_numeric($latitude) && is_numeric($longitude)) {
375
- $coordinates = new \Fleetbase\LaravelMysqlSpatial\Types\Point((float) $latitude, (float) $longitude);
376
+ $coordinates = new Point((float) $latitude, (float) $longitude);
376
377
  }
377
378
  }
378
379
 
@@ -412,11 +413,11 @@ class Utils extends FleetbaseUtils
412
413
  $longitude = $coords[1];
413
414
 
414
415
  if (is_numeric($latitude) && is_numeric($longitude)) {
415
- $coordinates = new \Fleetbase\LaravelMysqlSpatial\Types\Point((float) $latitude, (float) $longitude);
416
+ $coordinates = new Point((float) $latitude, (float) $longitude);
416
417
  }
417
418
  }
418
419
 
419
- if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
420
+ if ($coordinates instanceof Point) {
420
421
  return $coordinates;
421
422
  }
422
423
 
@@ -444,7 +445,7 @@ class Utils extends FleetbaseUtils
444
445
  $coordinates = $coordinates->location;
445
446
  }
446
447
 
447
- if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
448
+ if ($coordinates instanceof Point) {
448
449
  $latitude = $coordinates->getLat();
449
450
  $longitude = $coordinates->getLng();
450
451
  } elseif (is_array($coordinates) || is_object($coordinates)) {
@@ -534,22 +535,22 @@ class Utils extends FleetbaseUtils
534
535
  *
535
536
  * @param mixed $coordinates the input value representing a location or set of coordinates
536
537
  *
537
- * @return \Fleetbase\LaravelMysqlSpatial\Types\Point the extracted point value
538
+ * @return Point the extracted point value
538
539
  */
539
- public static function getPointFromCoordinates($coordinates): \Fleetbase\LaravelMysqlSpatial\Types\Point
540
+ public static function getPointFromCoordinates($coordinates): Point
540
541
  {
541
- if ($coordinates instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
542
+ if ($coordinates instanceof Point) {
542
543
  return $coordinates;
543
544
  }
544
545
 
545
546
  if (is_null($coordinates) || !static::isCoordinates($coordinates)) {
546
- return new \Fleetbase\LaravelMysqlSpatial\Types\Point(0, 0);
547
+ return new Point(0, 0);
547
548
  }
548
549
 
549
550
  $latitude = static::getLatitudeFromCoordinates($coordinates);
550
551
  $longitude = static::getLongitudeFromCoordinates($coordinates);
551
552
 
552
- return new \Fleetbase\LaravelMysqlSpatial\Types\Point($latitude, $longitude);
553
+ return new Point($latitude, $longitude);
553
554
  }
554
555
 
555
556
  /**
@@ -563,19 +564,19 @@ class Utils extends FleetbaseUtils
563
564
  {
564
565
  $wkt = 'POINT(0 0)';
565
566
 
566
- if ($point instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point) {
567
+ if ($point instanceof Point) {
567
568
  $wkt = $point->toWKT();
568
569
  }
569
570
 
570
571
  if (is_array($point)) {
571
572
  $json = json_encode($point);
572
- $p = \Fleetbase\LaravelMysqlSpatial\Types\Point::fromJson($json);
573
+ $p = Point::fromJson($json);
573
574
 
574
575
  $wkt = $p->toWkt();
575
576
  }
576
577
 
577
578
  if (is_string($point)) {
578
- $p = \Fleetbase\LaravelMysqlSpatial\Types\Point::fromString($point);
579
+ $p = Point::fromString($point);
579
580
 
580
581
  $wkt = $p->toWKT();
581
582
  }
@@ -605,107 +606,75 @@ class Utils extends FleetbaseUtils
605
606
  *
606
607
  * @param string $data the binary string representing the point
607
608
  *
608
- * @return \Fleetbase\LaravelMysqlSpatial\Types\Point the Laravel MySQL Spatial Point instance
609
+ * @return Point the Laravel MySQL Spatial Point instance
609
610
  */
610
- public static function rawPointToPoint(string $data): \Fleetbase\LaravelMysqlSpatial\Types\Point
611
+ public static function rawPointToPoint(string $data): Point
611
612
  {
612
613
  // Use the `unpack` function to extract the X, Y, and SRID values from the binary string.
613
614
  $res = unpack('lSRID/CByteOrder/lTypeInfo/dX/dY', $data);
614
615
 
615
616
  // Return a new Laravel MySQL Spatial Point instance with the X, Y, and SRID values.
616
- return new \Fleetbase\LaravelMysqlSpatial\Types\Point($res['X'], $res['Y'], $res['SRID']);
617
+ return new Point($res['X'], $res['Y'], $res['SRID']);
617
618
  }
618
619
 
619
620
  /**
620
- * Calculates driving distance and time using Google distance matrix.
621
- * Returns distance in meters and time in seconds.
621
+ * Calculates the driving distance and time between two points.
622
622
  *
623
- * @param \Fleetbase\FleetOps\Models\Place|\Fleetbase\LaravelMysqlSpatial\Types\Point|array $origin
624
- * @param \Fleetbase\FleetOps\Models\Place|\Fleetbase\LaravelMysqlSpatial\Types\Point|array $destination
623
+ * This function attempts to find the driving distance and time from the origin to the destination
624
+ * using various map APIs. It first attempts to resolve the origin and destination from various input types
625
+ * into geographical coordinates. Then, based on the provider specified in the options or defaulting to configured provider,
626
+ * it queries the respective service for the driving distance and time. The result is returned as a DistanceMatrix
627
+ * object with the distance in meters and the time in seconds.
628
+ *
629
+ * @param mixed $origin The origin of the journey. Can be a Place model, a string, or an array with latitude and longitude.
630
+ * @param mixed $destination The destination of the journey. Similar to the origin, it accepts multiple input types.
631
+ *
632
+ * @return DistanceMatrix an object containing the distance and time of the journey
633
+ *
634
+ * @throws \Throwable throws any exception encountered during the resolution of points or API calls
625
635
  */
626
- public static function getDrivingDistanceAndTime($origin, $destination): DistanceMatrix
636
+ public static function getDrivingDistanceAndTime($origin, $destination, $options = []): DistanceMatrix
627
637
  {
628
- if ($origin instanceof \Fleetbase\FleetOps\Models\Place) {
629
- $origin = static::createObject(
630
- [
631
- 'latitude' => $origin->location->getLat(),
632
- 'longitude' => $origin->location->getLng(),
633
- ]
634
- );
635
- } else {
636
- $point = static::getPointFromMixed($origin);
637
- $origin = static::createObject(
638
- [
639
- 'latitude' => $point->getLat(),
640
- 'longitude' => $point->getLng(),
641
- ]
642
- );
643
- }
644
-
645
- if ($destination instanceof \Fleetbase\FleetOps\Models\Place) {
646
- $destination = static::createObject(
647
- [
648
- 'latitude' => $destination->location->getLat(),
649
- 'longitude' => $destination->location->getLng(),
650
- ]
651
- );
652
- } else {
653
- $point = static::getPointFromMixed($destination);
654
- $destination = static::createObject(
655
- [
656
- 'latitude' => $point->getLat(),
657
- 'longitude' => $point->getLng(),
658
- ]
659
- );
638
+ $origin = static::getPointFromMixed($origin);
639
+ $destination = static::getPointFromMixed($destination);
640
+ $origins = $origin->getLat() . ',' . $origin->getLng();
641
+ $destinations = $destination->getLat() . ',' . $destination->getLng();
642
+
643
+ // Create empty distance matric
644
+ $distanceMatrix = new DistanceMatrix(0, 0);
645
+ $provider = data_get($options, 'provider', config('fleetops.distance_matrix.provider'));
646
+ switch ($provider) {
647
+ case 'calculate':
648
+ $distanceMatrix = static::calculateDrivingDistanceAndTime($origins, $destinations);
649
+ break;
650
+
651
+ case 'osrm':
652
+ $distanceMatrix = static::getDistanceMatrixFromOSRM($origins, $destinations);
653
+ break;
654
+
655
+ case 'google':
656
+ default:
657
+ $distanceMatrix = static::getDistanceMatrixFromGoogle($origins, $destinations);
658
+ break;
660
659
  }
661
660
 
662
- $cacheKey = $origin->latitude . ':' . $origin->longitude . ':' . $destination->latitude . ':' . $destination->longitude;
663
-
664
- // check cache for results
665
- $cachedResult = Redis::get($cacheKey);
666
-
667
- if ($cachedResult) {
668
- $json = json_decode($cachedResult);
669
-
670
- if (!empty($json->distance) && !empty($json->time)) {
671
- return new DistanceMatrix($json->distance, $json->time);
672
- }
673
- }
674
-
675
- $response = Http::get(
676
- 'https://maps.googleapis.com/maps/api/distancematrix/json',
677
- [
678
- 'origins' => $origin->latitude . ',' . $origin->longitude,
679
- 'destinations' => $destination->latitude . ',' . $destination->longitude,
680
- 'mode' => 'driving',
681
- 'key' => env('GOOGLE_MAPS_API_KEY'),
682
- ]
683
- )->json();
684
-
685
- $distance = data_get($response, 'rows.0.elements.0.distance.value');
686
- $time = data_get($response, 'rows.0.elements.0.duration.value');
687
-
688
- $result = static::createObject(
689
- [
690
- 'distance' => $distance,
691
- 'time' => $time,
692
- ]
693
- );
694
-
695
- // cache result
696
- Redis::set($cacheKey, json_encode($result));
697
-
698
- return new DistanceMatrix($distance, $time);
661
+ return $distanceMatrix;
699
662
  }
700
663
 
701
664
  /**
702
- * Calculates driving distance and time using Google distance matrix for multiple origins or destinations.
703
- * Returns distance in meters and time in seconds.
665
+ * Computes a distance matrix for multiple origins and destinations.
704
666
  *
705
- * @param Place|Point|array $origins
706
- * @param Place|Point|array $destinations
667
+ * This function is designed to handle arrays of origins and destinations to calculate a distance matrix.
668
+ * It converts the input arrays into a string format suitable for the map API request. The provider specified
669
+ * in the options (default is Google) determines which map service API is used for the calculations.
670
+ *
671
+ * @param array|\Illuminate\Support\Collection $origins array or collection of origin points
672
+ * @param array|\Illuminate\Support\Collection $destinations array or collection of destination points
673
+ * @param array $options options for API calls, like the provider and mode of transport
674
+ *
675
+ * @return DistanceMatrix an object representing the distance and time between the furthest origins and destinations
707
676
  */
708
- public static function distanceMatrix($origins = [], $destinations = []): DistanceMatrix
677
+ public static function distanceMatrix($origins = [], $destinations = [], $options = []): DistanceMatrix
709
678
  {
710
679
  if ($origins instanceof \Illuminate\Support\Collection) {
711
680
  $origins = $origins->all();
@@ -715,57 +684,83 @@ class Utils extends FleetbaseUtils
715
684
  $destinations = $destinations->all();
716
685
  }
717
686
 
718
- $origins = array_map(
719
- function ($origin) {
720
- $point = static::getPointFromMixed($origin);
721
- $origin = static::createObject(
722
- [
723
- 'latitude' => $point->getLat(),
724
- 'longitude' => $point->getLng(),
725
- ]
726
- );
727
-
728
- return $origin;
729
- },
730
- $origins
731
- );
687
+ // Convert origins and destinatinos to string
688
+ $origins = static::createCoordinateStringFromPlacesArray($origins);
689
+ $destinations = static::createCoordinateStringFromPlacesArray($destinations);
690
+
691
+ // Create empty distance matric
692
+ $distanceMatrix = new DistanceMatrix(0, 0);
693
+ $provider = data_get($options, 'provider', config('fleetops.distance_matrix.provider'));
694
+ switch ($provider) {
695
+ case 'calculate':
696
+ $distanceMatrix = static::calculateDrivingDistanceAndTime($origins, $destinations);
697
+ break;
698
+
699
+ case 'osrm':
700
+ $distanceMatrix = static::getDistanceMatrixFromOSRM($origins, $destinations);
701
+ break;
702
+
703
+ case 'google':
704
+ default:
705
+ $distanceMatrix = static::getDistanceMatrixFromGoogle($origins, $destinations);
706
+ break;
707
+ }
732
708
 
733
- $destinations = array_map(
734
- function ($destination) {
735
- $point = static::getPointFromMixed($destination);
736
- $destination = static::createObject(
737
- [
738
- 'latitude' => $point->getLat(),
739
- 'longitude' => $point->getLng(),
740
- ]
741
- );
742
-
743
- return $destination;
744
- },
745
- $destinations
746
- );
709
+ return $distanceMatrix;
710
+ }
747
711
 
748
- // get url ready string for origins
749
- $originsString = implode('|', array_map(
750
- function ($origin) {
751
- return $origin->latitude . ',' . $origin->longitude;
712
+ /**
713
+ * Converts an array of places into a coordinate string.
714
+ *
715
+ * Accepts an array of places (or any type that can be converted into geographical points)
716
+ * and converts each into a 'latitude,longitude' format. These coordinates are then concatenated into a single string,
717
+ * separated by the specified separator. The function gracefully handles any errors in the conversion process.
718
+ *
719
+ * @param array $places array of places to be converted into coordinates
720
+ * @param string $separator separator used to concatenate the coordinates into a single string
721
+ *
722
+ * @return string a concatenated string of coordinates
723
+ */
724
+ public static function createCoordinateStringFromPlacesArray(array $places = [], $separator = '|'): string
725
+ {
726
+ $coordinates = array_map(
727
+ function ($place) {
728
+ try {
729
+ $point = static::getPointFromMixed($place);
730
+ } catch (\Throwable $e) {
731
+ $point = new Point(0, 0);
732
+ }
733
+
734
+ return $point;
752
735
  },
753
- $origins
754
- ));
736
+ $places
737
+ );
755
738
 
756
- // get url ready string for origins
757
- $destinationString = implode('|', array_map(
758
- function ($destination) {
759
- return $destination->latitude . ',' . $destination->longitude;
739
+ return implode($separator, array_map(
740
+ function ($point) {
741
+ return $point->getLat() . ',' . $point->getLng();
760
742
  },
761
- $destinations
743
+ $coordinates
762
744
  ));
745
+ }
763
746
 
764
- $cacheKey = md5($originsString . '_' . $destinationString);
765
-
766
- // check cache for results
747
+ /**
748
+ * Retrieves a distance matrix using the Google Distance Matrix API.
749
+ *
750
+ * This function calculates the distance and time between origins and destinations using the Google API.
751
+ * It first checks if there is a cached result in Redis and, if not, performs an API call to Google.
752
+ * The results are then cached in Redis and returned as a DistanceMatrix object.
753
+ *
754
+ * @param string $origins a string of origins in 'latitude,longitude' format, separated by a specified delimiter
755
+ * @param string $destinations a string of destinations in a similar format to origins
756
+ * @param array $options additional options for the API call, like the mode of transport
757
+ *
758
+ * @return DistanceMatrix the distance and time between the given origins and destinations
759
+ */
760
+ public static function getDistanceMatrixFromGoogle(string $origins, string $destinations, $options = []): DistanceMatrix
761
+ {
762
+ $cacheKey = md5($origins . '_' . $destinations);
767
763
  $cachedResult = Redis::get($cacheKey);
768
-
769
764
  if ($cachedResult) {
770
765
  $json = json_decode($cachedResult);
771
766
 
@@ -777,9 +772,9 @@ class Utils extends FleetbaseUtils
777
772
  $response = Http::withOptions(['verify' => false])->get(
778
773
  'https://maps.googleapis.com/maps/api/distancematrix/json',
779
774
  [
780
- 'origins' => $originsString,
781
- 'destinations' => $destinationString,
782
- 'mode' => 'driving',
775
+ 'origins' => $origins,
776
+ 'destinations' => $destinations,
777
+ 'mode' => data_get($options, 'mode', 'driving'),
783
778
  'key' => env('GOOGLE_MAPS_API_KEY'),
784
779
  ]
785
780
  )->json();
@@ -787,17 +782,69 @@ class Utils extends FleetbaseUtils
787
782
  $distance = (float) data_get($response, 'rows.0.elements.0.distance.value', 0);
788
783
  $time = (float) data_get($response, 'rows.0.elements.0.duration.value', 0);
789
784
 
790
- $result = static::createObject(
791
- [
792
- 'distance' => $distance,
793
- 'time' => $time,
794
- ]
795
- );
785
+ // Create distance matrix
786
+ $distanceMatrix = new DistanceMatrix($distance, $time);
796
787
 
797
- // cache result
798
- Redis::set($cacheKey, json_encode($result));
788
+ // Cache distance matrix
789
+ Redis::set($cacheKey, json_encode($distanceMatrix));
799
790
 
800
- return new DistanceMatrix($distance, $time);
791
+ return $distanceMatrix;
792
+ }
793
+
794
+ /**
795
+ * Calculates distance and time between points using the OSRM API.
796
+ *
797
+ * Similar to the Google Distance Matrix function, this uses the OSRM (Open Source Routing Machine) API.
798
+ * It first checks for cached results before making a new API request. The origins and destinations are
799
+ * reformatted to the OSRM API requirement and the response is parsed into a DistanceMatrix object.
800
+ *
801
+ * @param string $origins comma-separated string of origin coordinates
802
+ * @param string $destinations comma-separated string of destination coordinates
803
+ *
804
+ * @return DistanceMatrix an object containing the distance and time for the specified journey
805
+ */
806
+ public static function getDistanceMatrixFromOSRM(string $origins, string $destinations): DistanceMatrix
807
+ {
808
+ $cacheKey = md5($origins . '_' . $destinations);
809
+ $cachedResult = Redis::get($cacheKey);
810
+ if ($cachedResult) {
811
+ $json = json_decode($cachedResult);
812
+
813
+ if (!empty($json->distance) && !empty($json->time)) {
814
+ return new DistanceMatrix($json->distance, $json->time);
815
+ }
816
+ }
817
+
818
+ // OSRM uses semi-colon to delimit coordinates so replace any `|` as we typically use with `;`
819
+ $origins = Str::replace('|', ';', $origins);
820
+ $destinations = Str::replace('|', ';', $destinations);
821
+ $coordinatesString = $origins . ';' . $destinations;
822
+ // Split the string into individual coordinates
823
+ $coordinatesArray = explode(';', $coordinatesString);
824
+
825
+ // Reverse the latitude and longitude in each coordinate
826
+ $reversedCoordinates = array_map(function ($coordinate) {
827
+ $parts = explode(',', $coordinate);
828
+ if (count($parts) == 2) {
829
+ return $parts[1] . ',' . $parts[0]; // Swap latitude and longitude
830
+ }
831
+
832
+ return $coordinate; // Return original if it's not a valid coordinate
833
+ }, $coordinatesArray);
834
+
835
+ // Join the reversed coordinates back into a string
836
+ $reversedCoordinatesString = implode(';', $reversedCoordinates);
837
+ $response = OSRM::getRouteFromCoordinatesString($reversedCoordinatesString);
838
+ $distance = (float) data_get($response, 'routes.0.distance', 0);
839
+ $time = (float) data_get($response, 'routes.0.duration', 0);
840
+
841
+ // Create distance matrix
842
+ $distanceMatrix = new DistanceMatrix($distance, $time);
843
+
844
+ // Cache distance matrix
845
+ Redis::set($cacheKey, json_encode($distanceMatrix));
846
+
847
+ return $distanceMatrix;
801
848
  }
802
849
 
803
850
  /**
@@ -857,13 +904,13 @@ class Utils extends FleetbaseUtils
857
904
  * https://en.wikipedia.org/wiki/Great-circle_distance#Formulas
858
905
  * https://en.wikipedia.org/wiki/Antipodal_point
859
906
  *
860
- * @param \Fleetbase\LaravelMysqlSpatial\Types\Point Starting point
861
- * @param \Fleetbase\LaravelMysqlSpatial\Types\Point Ending point
907
+ * @param Point Starting point
908
+ * @param Point Ending point
862
909
  * @param float $earthRadius Mean earth radius in [m]
863
910
  *
864
911
  * @return float Distance between points in [m] (same as earthRadius)
865
912
  */
866
- public static function vincentyGreatCircleDistance(\Fleetbase\LaravelMysqlSpatial\Types\Point $from, \Fleetbase\LaravelMysqlSpatial\Types\Point $to, float $earthRadius = 6371000): float
913
+ public static function vincentyGreatCircleDistance(Point $from, Point $to, float $earthRadius = 6371000): float
867
914
  {
868
915
  // convert from degrees to radians
869
916
  $latFrom = deg2rad($from->getLat());
@@ -884,7 +931,7 @@ class Utils extends FleetbaseUtils
884
931
  /**
885
932
  * Finds the nearest timezone for a given coordinate point.
886
933
  */
887
- public static function getNearestTimezone(\Fleetbase\LaravelMysqlSpatial\Types\Point $location, string $countryCode = ''): string
934
+ public static function getNearestTimezone(Point $location, string $countryCode = ''): string
888
935
  {
889
936
  $timezoneIds = \DateTimeZone::listIdentifiers(\DateTimeZone::PER_COUNTRY, $countryCode);
890
937
  $lat = $location->getLat();
@@ -984,7 +1031,7 @@ class Utils extends FleetbaseUtils
984
1031
 
985
1032
  public static function isPoint($point): bool
986
1033
  {
987
- return $point instanceof \Fleetbase\LaravelMysqlSpatial\Types\Point;
1034
+ return $point instanceof Point;
988
1035
  }
989
1036
 
990
1037
  /**
@@ -1249,7 +1296,7 @@ class Utils extends FleetbaseUtils
1249
1296
  *
1250
1297
  * @return float the heading in degrees from the starting point to the ending point
1251
1298
  */
1252
- public static function calculateHeading(\Fleetbase\LaravelMysqlSpatial\Types\Point $point1, \Fleetbase\LaravelMysqlSpatial\Types\Point $point2): float
1299
+ public static function calculateHeading(Point $point1, Point $point2): float
1253
1300
  {
1254
1301
  // Extract latitude and longitude from Point objects
1255
1302
  $lat1 = $point1->getLat();
@@ -12,9 +12,6 @@ use Illuminate\Support\Facades\Route;
12
12
  | is assigned the "api" middleware group. Enjoy building your API!
13
13
  |
14
14
  */
15
-
16
- Route::get('fleet-ops-test', 'Fleetbase\FleetOps\Http\Controllers\Controller@test');
17
-
18
15
  Route::prefix(config('fleetops.api.routing.prefix', null))->namespace('Fleetbase\FleetOps\Http\Controllers')->group(
19
16
  function ($router) {
20
17
  /*
@@ -84,6 +81,7 @@ Route::prefix(config('fleetops.api.routing.prefix', null))->namespace('Fleetbase
84
81
  $router->post('{id}/capture-photo/{subjectId?}', 'OrderController@capturePhoto');
85
82
  $router->put('{id}', 'OrderController@update');
86
83
  $router->delete('{id}', 'OrderController@delete');
84
+ $router->get('{id}/editable-entity-fields', 'OrderController@getEditableEntityFields');
87
85
  });
88
86
  // entities routes
89
87
  $router->group(['prefix' => 'entities'], function () use ($router) {
@@ -435,6 +433,8 @@ Route::prefix(config('fleetops.api.routing.prefix', null))->namespace('Fleetbase
435
433
  function ($router) {
436
434
  $router->get('visibility', 'SettingController@getVisibilitySettings');
437
435
  $router->post('visibility', 'SettingController@saveVisibilitySettings');
436
+ $router->get('entity-editing-settings', 'SettingController@getEntityEditingSettings');
437
+ $router->post('entity-editing-settings', 'SettingController@saveEntityEditingSettings');
438
438
  }
439
439
  );
440
440
  $router->group(
@@ -236,6 +236,9 @@ fleet-ops:
236
236
  title: Navigator App
237
237
  name: Instance Linking URL
238
238
  message: Use this URL to link the official Navigator app to this {companyName} instance. Opening this URL on a mobile device will open the Navigator app and update it's configuration and branding.
239
+ settings: Entity Settings
240
+ select-input: Allow driver to update entity details
241
+
239
242
  visibility-controls:
240
243
  title: Visibility Controls
241
244
  message: Visibility controls allow you to disable sections of Fleet-Ops. Toggle the checkbox to enable or disable sections to hide in Fleet-ops.