@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.
Files changed (74) hide show
  1. package/addon/components/admin/navigator-app.hbs +6 -3
  2. package/addon/components/layout/fleet-ops-sidebar/fleet-listing.hbs +5 -1
  3. package/addon/components/layout/fleet-ops-sidebar/fleet-listing.js +98 -1
  4. package/addon/components/layout/fleet-ops-sidebar.hbs +5 -1
  5. package/addon/components/layout/fleet-ops-sidebar.js +1 -0
  6. package/addon/controllers/management/drivers/index/edit.js +0 -26
  7. package/addon/engine.js +4 -4
  8. package/addon/styles/fleetops-engine.css +17 -0
  9. package/addon/templates/operations/service-rates/index/new.hbs +1 -1
  10. package/composer.json +2 -2
  11. package/extension.json +1 -1
  12. package/package.json +1 -1
  13. package/server/config/fleetops.php +4 -1
  14. package/server/src/Casts/MultiPolygon.php +14 -3
  15. package/server/src/Casts/Point.php +12 -2
  16. package/server/src/Casts/Polygon.php +19 -4
  17. package/server/src/Http/Controllers/Api/v1/DriverController.php +34 -18
  18. package/server/src/Http/Controllers/Api/v1/EntityController.php +36 -1
  19. package/server/src/Http/Controllers/Api/v1/LabelController.php +2 -2
  20. package/server/src/Http/Controllers/Api/v1/OrderController.php +139 -59
  21. package/server/src/Http/Controllers/Api/v1/PayloadController.php +20 -12
  22. package/server/src/Http/Controllers/Api/v1/PlaceController.php +25 -3
  23. package/server/src/Http/Controllers/Api/v1/PurchaseRateController.php +1 -1
  24. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +71 -3
  25. package/server/src/Http/Controllers/Api/v1/ServiceQuoteController.php +1 -1
  26. package/server/src/Http/Controllers/Api/v1/ServiceRateController.php +3 -2
  27. package/server/src/Http/Controllers/Api/v1/TrackingNumberController.php +2 -2
  28. package/server/src/Http/Controllers/Api/v1/TrackingStatusController.php +2 -2
  29. package/server/src/Http/Controllers/Api/v1/VehicleController.php +22 -2
  30. package/server/src/Http/Controllers/Api/v1/ZoneController.php +59 -3
  31. package/server/src/Http/Controllers/Internal/v1/DriverController.php +148 -0
  32. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +38 -0
  33. package/server/src/Http/Controllers/Internal/v1/OrderController.php +11 -1
  34. package/server/src/Http/Filter/TrackingStatusFilter.php +10 -0
  35. package/server/src/Http/Requests/CancelOrderRequest.php +1 -2
  36. package/server/src/Http/Requests/CreateContactRequest.php +5 -4
  37. package/server/src/Http/Requests/CreateDriverRequest.php +13 -11
  38. package/server/src/Http/Requests/CreateEntityRequest.php +7 -4
  39. package/server/src/Http/Requests/CreateOrderRequest.php +2 -2
  40. package/server/src/Http/Requests/CreatePayloadRequest.php +1 -1
  41. package/server/src/Http/Requests/CreatePlaceRequest.php +46 -4
  42. package/server/src/Http/Requests/CreatePurchaseRateRequest.php +3 -2
  43. package/server/src/Http/Requests/CreateServiceAreaRequest.php +24 -4
  44. package/server/src/Http/Requests/CreateServiceRateRequest.php +22 -21
  45. package/server/src/Http/Requests/CreateTrackingStatusRequest.php +9 -8
  46. package/server/src/Http/Requests/CreateVehicleRequest.php +6 -4
  47. package/server/src/Http/Requests/CreateZoneRequest.php +24 -5
  48. package/server/src/Http/Requests/QueryServiceQuotesRequest.php +11 -10
  49. package/server/src/Http/Requests/ScheduleOrderRequest.php +32 -0
  50. package/server/src/Http/Requests/UpdateContactRequest.php +0 -13
  51. package/server/src/Http/Requests/UpdateServiceAreaRequest.php +1 -23
  52. package/server/src/Http/Requests/UpdateServiceQuoteRequest.php +1 -23
  53. package/server/src/Http/Requests/UpdateServiceRateRequest.php +1 -23
  54. package/server/src/Http/Requests/UpdateTrackingStatusRequest.php +1 -26
  55. package/server/src/Http/Resources/v1/DeletedResource.php +2 -9
  56. package/server/src/Http/Resources/v1/Entity.php +47 -44
  57. package/server/src/Http/Resources/v1/Order.php +1 -1
  58. package/server/src/Http/Resources/v1/ServiceArea.php +2 -2
  59. package/server/src/Http/Resources/v1/Vehicle.php +1 -3
  60. package/server/src/Http/Resources/v1/Zone.php +2 -4
  61. package/server/src/Models/Entity.php +99 -3
  62. package/server/src/Models/Order.php +75 -7
  63. package/server/src/Models/Payload.php +104 -33
  64. package/server/src/Models/Place.php +56 -17
  65. package/server/src/Models/ServiceArea.php +285 -18
  66. package/server/src/Models/ServiceRate.php +10 -6
  67. package/server/src/Models/TrackingNumber.php +18 -24
  68. package/server/src/Models/TrackingStatus.php +2 -6
  69. package/server/src/Models/Vehicle.php +2 -2
  70. package/server/src/Models/Waypoint.php +0 -10
  71. package/server/src/Models/Zone.php +132 -5
  72. package/server/src/Support/Flow.php +17 -3
  73. package/server/src/Support/Utils.php +143 -9
  74. package/server/src/routes.php +58 -3
@@ -6,6 +6,7 @@ use Fleetbase\FleetOps\Events\OrderDispatchFailed;
6
6
  use Fleetbase\FleetOps\Events\OrderReady;
7
7
  use Fleetbase\FleetOps\Events\OrderStarted;
8
8
  use Fleetbase\FleetOps\Http\Requests\CreateOrderRequest;
9
+ use Fleetbase\FleetOps\Http\Requests\ScheduleOrderRequest;
9
10
  use Fleetbase\FleetOps\Http\Requests\UpdateOrderRequest;
10
11
  use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
11
12
  use Fleetbase\FleetOps\Http\Resources\v1\Order as OrderResource;
@@ -23,6 +24,7 @@ use Fleetbase\FleetOps\Support\Utils;
23
24
  use Fleetbase\Http\Controllers\Controller;
24
25
  use Fleetbase\Models\Company;
25
26
  use Fleetbase\Models\File;
27
+ use Fleetbase\Support\Auth;
26
28
  use Illuminate\Http\Request;
27
29
  use Illuminate\Support\Carbon;
28
30
  use Illuminate\Support\Facades\Storage;
@@ -55,7 +57,7 @@ class OrderController extends Controller
55
57
  try {
56
58
  $integratedVendorOrder = $serviceQuote->integratedVendor->api()->createOrderFromServiceQuote($serviceQuote, $request);
57
59
  } catch (\Exception $e) {
58
- return response()->error($e->getMessage());
60
+ return response()->apiError($e->getMessage());
59
61
  }
60
62
  }
61
63
 
@@ -69,18 +71,18 @@ class OrderController extends Controller
69
71
  $dropoff = data_get($payloadInput, 'dropoff');
70
72
  $return = data_get($payloadInput, 'return');
71
73
 
72
- // if no pickup and dropoff extract from waypoints
73
- if (empty($pickup) && empty($dropoff) && count($waypoints)) {
74
- $pickup = array_shift($waypoints);
75
- $dropoff = array_pop($waypoints);
74
+ if ($pickup) {
75
+ $payload->setPickup($pickup, [
76
+ 'callback' => function ($pickup, $payload) {
77
+ $payload->setCurrentWaypoint($pickup);
78
+ },
79
+ ]);
80
+ }
81
+
82
+ if ($dropoff) {
83
+ $payload->setDropoff($dropoff);
76
84
  }
77
85
 
78
- $payload->setPickup($pickup, [
79
- 'callback' => function ($pickup, $payload) {
80
- $payload->setCurrentWaypoint($pickup);
81
- },
82
- ]);
83
- $payload->setDropoff($dropoff);
84
86
  if ($return) {
85
87
  $payload->setReturn($return);
86
88
  }
@@ -91,6 +93,12 @@ class OrderController extends Controller
91
93
  $payload->setWaypoints($waypoints);
92
94
  $payload->setEntities($entities);
93
95
 
96
+ // set the first / current waypoint
97
+ $firstWaypoint = $payload->getPickupOrFirstWaypoint();
98
+ if ($firstWaypoint instanceof Place) {
99
+ $payload->setCurrentWaypoint($firstWaypoint);
100
+ }
101
+
94
102
  $input['payload_uuid'] = $payload->uuid;
95
103
  } elseif ($request->isString('payload')) {
96
104
  $input['payload_uuid'] = Utils::getUuid('payloads', [
@@ -110,18 +118,18 @@ class OrderController extends Controller
110
118
  $dropoff = data_get($payloadInput, 'dropoff');
111
119
  $return = data_get($payloadInput, 'return');
112
120
 
113
- // if no pickup and dropoff extract from waypoints
114
- if (empty($pickup) && empty($dropoff) && count($waypoints)) {
115
- $pickup = array_shift($waypoints);
116
- $dropoff = array_pop($waypoints);
121
+ if ($pickup) {
122
+ $payload->setPickup($pickup, [
123
+ 'callback' => function ($pickup, $payload) {
124
+ $payload->setCurrentWaypoint($pickup);
125
+ },
126
+ ]);
127
+ }
128
+
129
+ if ($dropoff) {
130
+ $payload->setDropoff($dropoff);
117
131
  }
118
132
 
119
- $payload->setPickup($pickup, [
120
- 'callback' => function ($pickup, $payload) {
121
- $payload->setCurrentWaypoint($pickup);
122
- },
123
- ]);
124
- $payload->setDropoff($dropoff);
125
133
  if ($return) {
126
134
  $payload->setReturn($return);
127
135
  }
@@ -135,7 +143,10 @@ class OrderController extends Controller
135
143
  $input['payload_uuid'] = $payload->uuid;
136
144
 
137
145
  // set the first / current waypoint
138
- $payload->setCurrentWaypoint($payload->pickup);
146
+ $firstWaypoint = $payload->getPickupOrFirstWaypoint();
147
+ if ($firstWaypoint instanceof Place) {
148
+ $payload->setCurrentWaypoint($firstWaypoint);
149
+ }
139
150
  }
140
151
 
141
152
  // driver assignment
@@ -186,13 +197,18 @@ class OrderController extends Controller
186
197
  $input['type'] = 'default';
187
198
  }
188
199
 
200
+ // if no status is set its default to `created`
201
+ if (!isset($input['status'])) {
202
+ $input['status'] = 'created';
203
+ }
204
+
189
205
  // if adhoc set convert to sql ready boolean value 1 or 0
190
206
  if (isset($input['adhoc']) && $integratedVendorOrder === null) {
191
207
  $input['adhoc'] = Utils::isTrue($input['adhoc']) ? 1 : 0;
192
208
  }
193
209
 
194
210
  if (!isset($input['payload_uuid'])) {
195
- return response()->error('Attempted to attach invalid payload to order.');
211
+ return response()->apiError('Attempted to attach invalid payload to order.');
196
212
  }
197
213
 
198
214
  // create the order
@@ -217,7 +233,7 @@ class OrderController extends Controller
217
233
 
218
234
  // dispatch if flagged true
219
235
  if ($request->boolean('dispatch') && $integratedVendorOrder === null) {
220
- $order->dispatch();
236
+ $order->dispatchWithActivity();
221
237
  }
222
238
 
223
239
  // load required relations
@@ -657,14 +673,61 @@ class OrderController extends Controller
657
673
  }
658
674
 
659
675
  if (!$order->hasDriverAssigned && !$order->adhoc) {
660
- return response()->error('No driver assigned to dispatch!');
676
+ return response()->apiError('No driver assigned to dispatch!');
661
677
  }
662
678
 
663
679
  if ($order->dispatched) {
664
- return response()->error('Order has already been dispatched!');
680
+ return response()->apiError('Order has already been dispatched!');
665
681
  }
666
682
 
667
683
  $order->dispatch();
684
+ $order->insertDispatchActivity();
685
+
686
+ return new OrderResource($order);
687
+ }
688
+
689
+ /**
690
+ * Schedules an order using date and time.
691
+ *
692
+ * @param \Fleetbase\FleetOps\Http\Requests\ScheduleOrderRequest
693
+ *
694
+ * @return \Fleetbase\Http\Resources\v1\Order
695
+ */
696
+ public function scheduleOrder(string $id, ScheduleOrderRequest $request)
697
+ {
698
+ $dateInput = $request->input('date');
699
+ $timeInput = $request->input('time');
700
+
701
+ // get the default tz
702
+ $company = Auth::getCompany();
703
+ $defaultTz = data_get($company, 'timezone', config('app.timezone'));
704
+ $timezoneInput = $request->input('timezone', $defaultTz);
705
+
706
+ try {
707
+ $order = Order::findRecordOrFail($id);
708
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
709
+ return response()->json(
710
+ [
711
+ 'error' => 'Order resource not found.',
712
+ ],
713
+ 404
714
+ );
715
+ }
716
+
717
+ // Parse date and time
718
+ $date = Carbon::parse($dateInput);
719
+ if ($timeInput) {
720
+ $time = Carbon::parse($timeInput);
721
+ // Combine date and time
722
+ $date->setTime($time->hour, $time->minute, $time->second);
723
+ }
724
+
725
+ // Set the timezone
726
+ $date->shiftTimezone($timezoneInput);
727
+
728
+ // Update order with new date and time
729
+ $order->scheduled_at = $date;
730
+ $order->save();
668
731
 
669
732
  return new OrderResource($order);
670
733
  }
@@ -692,7 +755,7 @@ class OrderController extends Controller
692
755
  }
693
756
 
694
757
  if ($order->started) {
695
- return response()->error('Order has already started.');
758
+ return response()->apiError('Order has already started.');
696
759
  }
697
760
 
698
761
  // if the order is adhoc and the parameter of `assign` is set with a valid driver id, assign the driver and continue
@@ -707,11 +770,11 @@ class OrderController extends Controller
707
770
  $payload = Payload::where('uuid', $order->payload_uuid)->withoutGlobalScopes()->with(['waypoints', 'waypointMarkers', 'entities'])->first();
708
771
 
709
772
  if ($order->adhoc && !$driver) {
710
- return response()->error('You must send driver to accept adhoc order.');
773
+ return response()->apiError('You must send driver to accept adhoc order.');
711
774
  }
712
775
 
713
776
  if (!$driver) {
714
- return response()->error('No driver assigned to order.');
777
+ return response()->apiError('No driver assigned to order.');
715
778
  }
716
779
 
717
780
  // get the next order activity
@@ -723,7 +786,7 @@ class OrderController extends Controller
723
786
  // if order is not dispatched yet $activity['code'] === 'dispatched' || $order->dispatched === true
724
787
  // and not skipping throw order not dispatched error
725
788
  if ($isNotDispatched && !$skipDispatch) {
726
- return response()->error('Order has not been dispatched yet and cannot be started.');
789
+ return response()->apiError('Order has not been dispatched yet and cannot be started.');
727
790
  }
728
791
 
729
792
  // if we're going to skip the dispatch get the next activity status and flow and continue
@@ -760,32 +823,50 @@ class OrderController extends Controller
760
823
  /**
761
824
  * Update an order activity.
762
825
  *
763
- * @param \Fleetbase\Models\Order|string $order
764
- *
765
826
  * @return \Fleetbase\Http\Resources\v1\Order
766
827
  */
767
- public function updateActivity($order, Request $request)
828
+ public function updateActivity($id, Request $request)
768
829
  {
769
830
  $skipDispatch = $request->or(['skip_dispatch', 'skipDispatch'], false);
770
831
  $proof = $request->input('proof', null);
832
+ $order = null;
833
+
834
+ // if instance of order is passed directly to this method
835
+ if ($id instanceof Order) {
836
+ /** @var \Fleetbase\FleetOps\Models\Order $order */
837
+ $order = $id;
838
+ }
771
839
 
772
- /** @var \Fleetbase\FleetOps\Models\Order $order */
773
- $order = ($order instanceof Order) ? $order : Order::withoutGlobalScopes()
774
- ->where('public_id', $order)
775
- ->whereNull('deleted_at')
776
- ->with(['driverAssigned', 'payload.entities', 'payload.currentWaypoint', 'payload.waypoints'])
777
- ->first();
840
+ // if string $id
841
+ if (!$order) {
842
+ try {
843
+ $order = Order::findRecordOrFail($id, ['driverAssigned', 'payload.entities', 'payload.currentWaypoint', 'payload.waypoints']);
844
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
845
+ return response()->json(
846
+ [
847
+ 'error' => 'Order resource not found.',
848
+ ],
849
+ 404
850
+ );
851
+ }
852
+ }
778
853
 
854
+ // if no order found
779
855
  if (!$order) {
780
- return response()->error('No resource not found.');
856
+ return response()->apiError('No resource not found.');
781
857
  }
782
858
 
783
- // if orser is created trigger started flag
859
+ // if order is still status of `created` trigger started flag
784
860
  if ($order->status === 'created') {
785
861
  $order->started = true;
786
862
  $order->started_at = now();
787
863
  }
788
864
 
865
+ // if order is already completed
866
+ if ($order->status === 'completed') {
867
+ return response()->apiError('Order is already completed.');
868
+ }
869
+
789
870
  $activity = $request->input('activity', Flow::getNextActivity($order));
790
871
 
791
872
  // if we're going to skip the dispatch get the next activity status and flow and continue
@@ -799,7 +880,7 @@ class OrderController extends Controller
799
880
  if (!$order->hasDriverAssigned && !$order->adhoc) {
800
881
  event(new OrderDispatchFailed($order, 'No driver assigned for order to dispatch to.'));
801
882
 
802
- return response()->error('No driver assigned for order to dispatch to.');
883
+ return response()->apiError('No driver assigned for order to dispatch to.');
803
884
  }
804
885
 
805
886
  $order->dispatch();
@@ -844,8 +925,7 @@ class OrderController extends Controller
844
925
  $order->notifyCompleted();
845
926
  }
846
927
 
847
- $order->setStatus($activity['code']);
848
- $order->insertActivity($activity['status'], $activity['details'] ?? '', $location, $activity['code'], $proof);
928
+ $order->updateActivity($activity, $proof);
849
929
 
850
930
  // also update for each order entities if not multiple drop order
851
931
  // all entities will share the same activity status as is one drop order
@@ -925,7 +1005,7 @@ class OrderController extends Controller
925
1005
 
926
1006
  // if not completed respond with error
927
1007
  if (!$isCompleted) {
928
- return response()->error('Not all waypoints completed for order.');
1008
+ return response()->apiError('Not all waypoints completed for order.');
929
1009
  }
930
1010
 
931
1011
  $activity = [
@@ -994,11 +1074,10 @@ class OrderController extends Controller
994
1074
  $place = $order->payload->waypoints->firstWhere('public_id', $placeId);
995
1075
 
996
1076
  if (!$place) {
997
- return response()->error('Place resource is not a valid destination.');
1077
+ return response()->apiError('Place resource is not a valid destination.');
998
1078
  }
999
1079
 
1000
- $order->payload->update(['current_waypoint_uuid' => $place->uuid]);
1001
- $order->payload->refresh();
1080
+ $order->payload->setCurrentWaypoint($place);
1002
1081
 
1003
1082
  return new OrderResource($order);
1004
1083
  }
@@ -1050,7 +1129,7 @@ class OrderController extends Controller
1050
1129
  }
1051
1130
 
1052
1131
  if (!$code) {
1053
- return response()->error('No QR code data to capture.');
1132
+ return response()->apiError('No QR code data to capture.');
1054
1133
  }
1055
1134
 
1056
1135
  $subject = $type === null ? $order : null;
@@ -1075,7 +1154,7 @@ class OrderController extends Controller
1075
1154
  }
1076
1155
 
1077
1156
  if (!$subject) {
1078
- return response()->error('Unable to capture QR code data.');
1157
+ return response()->apiError('Unable to capture QR code data.');
1079
1158
  }
1080
1159
 
1081
1160
  // validate
@@ -1094,7 +1173,7 @@ class OrderController extends Controller
1094
1173
  return new ProofResource($proof);
1095
1174
  }
1096
1175
 
1097
- return response()->error('Unable to validate QR code data.');
1176
+ return response()->apiError('Unable to validate QR code data.');
1098
1177
  }
1099
1178
 
1100
1179
  /**
@@ -1104,11 +1183,12 @@ class OrderController extends Controller
1104
1183
  */
1105
1184
  public function captureSignature(string $id, string $subjectId = null, Request $request)
1106
1185
  {
1107
- $disk = $request->input('disk', config('filesystems.default'));
1108
- $bucket = $request->input('bucket', config('filesystems.disks.' . $disk . '.bucket', config('filesystems.disks.s3.bucket')));
1109
- $signature = $request->input('signature');
1110
- $data = $request->input('data', []);
1111
- $type = $subjectId ? strtok($subjectId, '_') : null;
1186
+ $disk = $request->input('disk', config('filesystems.default'));
1187
+ $bucket = $request->input('bucket', config('filesystems.disks.' . $disk . '.bucket', config('filesystems.disks.s3.bucket')));
1188
+ $signature = $request->input('signature');
1189
+ $data = $request->input('data', []);
1190
+ $remarks = $request->input('remarks', 'Verified by Signature');
1191
+ $type = $subjectId ? strtok($subjectId, '_') : null;
1112
1192
 
1113
1193
  try {
1114
1194
  $order = Order::findRecordOrFail($id);
@@ -1122,7 +1202,7 @@ class OrderController extends Controller
1122
1202
  }
1123
1203
 
1124
1204
  if (!$signature) {
1125
- return response()->error('No signature data to capture.');
1205
+ return response()->apiError('No signature data to capture.');
1126
1206
  }
1127
1207
 
1128
1208
  $subject = $type === null ? $order : null;
@@ -1147,7 +1227,7 @@ class OrderController extends Controller
1147
1227
  }
1148
1228
 
1149
1229
  if (!$subject) {
1150
- return response()->error('Unable to capture signature data.');
1230
+ return response()->apiError('Unable to capture signature data.');
1151
1231
  }
1152
1232
 
1153
1233
  // create proof instance
@@ -1156,7 +1236,7 @@ class OrderController extends Controller
1156
1236
  'order_uuid' => $order->uuid,
1157
1237
  'subject_uuid' => $subject->uuid,
1158
1238
  'subject_type' => Utils::getModelClassName($subject),
1159
- 'remarks' => 'Verified by Signature',
1239
+ 'remarks' => $remarks,
1160
1240
  'raw_data' => $signature,
1161
1241
  'data' => $data,
1162
1242
  ]);
@@ -7,6 +7,7 @@ use Fleetbase\FleetOps\Http\Requests\UpdatePayloadRequest;
7
7
  use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
8
8
  use Fleetbase\FleetOps\Http\Resources\v1\Payload as PayloadResource;
9
9
  use Fleetbase\FleetOps\Models\Payload;
10
+ use Fleetbase\FleetOps\Models\Place;
10
11
  use Fleetbase\Http\Controllers\Controller;
11
12
  use Illuminate\Http\Request;
12
13
  use Illuminate\Support\Arr;
@@ -37,30 +38,34 @@ class PayloadController extends Controller
37
38
  // create the payload
38
39
  $payload = new Payload(Arr::only($input, ['type', 'provider', 'meta', 'cod_amount', 'cod_currency', 'cod_payment_method']));
39
40
 
40
- // if no pickup and dropoff extract from waypoints
41
- if (empty($pickup) && empty($dropoff) && count($waypoints)) {
42
- $pickup = array_shift($waypoints);
43
- $dropoff = array_pop($waypoints);
44
- }
45
-
46
41
  // set pickup point
47
- $payload->setPickup($pickup);
42
+ if ($pickup) {
43
+ $payload->setPickup($pickup);
44
+ }
48
45
 
49
46
  // set dropoff point
50
- $payload->setDropoff($dropoff);
47
+ if ($dropoff) {
48
+ $payload->setDropoff($dropoff);
49
+ }
51
50
 
52
51
  // set return point
53
- $payload->setReturn($return);
52
+ if ($return) {
53
+ $payload->setReturn($return);
54
+ }
54
55
 
55
56
  // save payload
56
57
  $payload->save();
57
58
 
58
- // set waypoints
59
+ // set waypoints and entities after payload is saved
59
60
  $payload->setWaypoints($waypoints);
60
-
61
- // set entities
62
61
  $payload->setEntities($entities);
63
62
 
63
+ // set the first / current waypoint
64
+ $firstWaypoint = $payload->getPickupOrFirstWaypoint();
65
+ if ($firstWaypoint instanceof Place) {
66
+ $payload->setCurrentWaypoint($firstWaypoint);
67
+ }
68
+
64
69
  // response the driver resource
65
70
  return new PayloadResource($payload);
66
71
  }
@@ -126,6 +131,9 @@ class PayloadController extends Controller
126
131
  // save the payload
127
132
  $payload->save();
128
133
 
134
+ // make sure entities and waypoints is loaded
135
+ $payload->load(['entities', 'waypoints', 'pickup', 'dropoff', 'return']);
136
+
129
137
  // response the payload resource
130
138
  return new PayloadResource($payload);
131
139
  }
@@ -66,6 +66,28 @@ class PlaceController extends Controller
66
66
  }
67
67
  }
68
68
 
69
+ // if we have only latitude/longitude or location BUT no street1 do a reverse lookup
70
+ $requestHasCoordinates = $request->filled(['latitude', 'longitude']);
71
+ $requestHasLocation = $request->filled(['location']);
72
+ $requestMissingStreet = $request->missing('street1');
73
+ if ($requestMissingStreet && ($requestHasCoordinates || $requestHasLocation)) {
74
+ if ($requestHasLocation) {
75
+ $point = Utils::getPointFromMixed($request->input('location'));
76
+ }
77
+
78
+ if ($requestHasCoordinates) {
79
+ $point = Utils::getPointFromMixed($request->only(['latitude', 'longitude']));
80
+ }
81
+
82
+ if ($point instanceof Point) {
83
+ $place = Place::createFromReverseGeocodingLookup($point);
84
+
85
+ if ($place instanceof Place) {
86
+ $input = $place->toArray();
87
+ }
88
+ }
89
+ }
90
+
69
91
  // latitude / longitude
70
92
  if ($request->has(['latitude', 'longitude'])) {
71
93
  $input['location'] = Utils::getPointFromCoordinates($request->only(['latitude', 'longitude']));
@@ -141,7 +163,7 @@ class PlaceController extends Controller
141
163
  try {
142
164
  $place = Place::findRecordOrFail($id);
143
165
  } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
144
- return response()->error('Place resource not found.');
166
+ return response()->apiError('Place resource not found.');
145
167
  }
146
168
 
147
169
  // get request input
@@ -307,7 +329,7 @@ class PlaceController extends Controller
307
329
  try {
308
330
  $place = Place::findRecordOrFail($id);
309
331
  } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
310
- return response()->error('Place resource not found.');
332
+ return response()->apiError('Place resource not found.');
311
333
  }
312
334
 
313
335
  return new PlaceResource($place);
@@ -323,7 +345,7 @@ class PlaceController extends Controller
323
345
  try {
324
346
  $place = Place::findRecordOrFail($id);
325
347
  } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
326
- return response()->error('Place resource not found.');
348
+ return response()->apiError('Place resource not found.');
327
349
  }
328
350
 
329
351
  $place->delete();
@@ -97,7 +97,7 @@ class PurchaseRateController extends Controller
97
97
  try {
98
98
  $integratedVendorOrder = $serviceQuote->integratedVendor->api()->createOrderFromServiceQuote($serviceQuote, $request);
99
99
  } catch (\Exception $e) {
100
- return response()->error($e->getMessage());
100
+ return response()->apiError($e->getMessage());
101
101
  }
102
102
  }
103
103
 
@@ -7,7 +7,9 @@ use Fleetbase\FleetOps\Http\Requests\UpdateServiceAreaRequest;
7
7
  use Fleetbase\FleetOps\Http\Resources\v1\DeletedResource;
8
8
  use Fleetbase\FleetOps\Http\Resources\v1\ServiceArea as ServiceAreaResource;
9
9
  use Fleetbase\FleetOps\Models\ServiceArea;
10
+ use Fleetbase\FleetOps\Support\Utils;
10
11
  use Fleetbase\Http\Controllers\Controller;
12
+ use Grimzy\LaravelMysqlSpatial\Types\Point;
11
13
  use Illuminate\Http\Request;
12
14
 
13
15
  class ServiceAreaController extends Controller
@@ -24,13 +26,48 @@ class ServiceAreaController extends Controller
24
26
  // get request input
25
27
  $input = $request->only(['name', 'type', 'status']);
26
28
 
29
+ // get radius for creating service area border - default to 500 meters
30
+ $radius = (int) $request->input('radius', 500);
31
+
27
32
  // make sure company is set
28
33
  $input['company_uuid'] = session('company');
29
34
 
30
- // @todo some geocoding here
35
+ // if parent service area set
36
+ if ($request->filled('parent')) {
37
+ $input['parent_uuid'] = Utils::getUuid('service_areas', [
38
+ 'public_id' => $request->input('parent'),
39
+ 'company_uuid' => session('company'),
40
+ ]);
41
+ }
42
+
43
+ // if latitude and longitude is provided
44
+ if ($request->has(['latitude', 'longitude'])) {
45
+ // create a polygon given the radius
46
+ $latitude = $request->input('latitude');
47
+ $longitude = $request->input('longitude');
48
+ $point = new Point($latitude, $longitude);
49
+
50
+ if ($point instanceof Point) {
51
+ $input['border'] = ServiceArea::createMultiPolygonFromPoint($point, $radius);
52
+ }
53
+ }
54
+
55
+ // if a location is provided
56
+ if ($request->has('location')) {
57
+ $location = $request->input('location');
58
+ $point = Utils::getPointFromMixed($location);
59
+
60
+ if ($point instanceof Point) {
61
+ $input['border'] = ServiceArea::createMultiPolygonFromPoint($point, $radius);
62
+ }
63
+ }
31
64
 
32
65
  // create the serviceArea
33
- $serviceArea = ServiceArea::create($input);
66
+ try {
67
+ $serviceArea = ServiceArea::create($input);
68
+ } catch (\Throwable $e) {
69
+ dd($e->getMessage());
70
+ }
34
71
 
35
72
  // response the driver resource
36
73
  return new ServiceAreaResource($serviceArea);
@@ -61,7 +98,38 @@ class ServiceAreaController extends Controller
61
98
  // get request input
62
99
  $input = $request->only(['name', 'type', 'status']);
63
100
 
64
- // @todo some geocoding here
101
+ // get radius for creating service area border - default to 500 meters
102
+ $radius = $request->input('radius', 500);
103
+
104
+ // if parent service area set
105
+ if ($request->filled('parent')) {
106
+ $input['parent_uuid'] = Utils::getUuid('service_areas', [
107
+ 'public_id' => $request->input('parent'),
108
+ 'company_uuid' => session('company'),
109
+ ]);
110
+ }
111
+
112
+ // if latitude and longitude is provided
113
+ if ($request->has(['latitude', 'longitude'])) {
114
+ // create a polygon given the radius
115
+ $latitude = $request->input('latitude');
116
+ $longitude = $request->input('longitude');
117
+ $point = new Point($latitude, $longitude);
118
+
119
+ if ($point instanceof Point) {
120
+ $input['border'] = ServiceArea::createMultiPolygonFromPoint($point, $radius);
121
+ }
122
+ }
123
+
124
+ // if a location is provided
125
+ if ($request->has('location')) {
126
+ $location = $request->input('location');
127
+ $point = Utils::getPointFromMixed($location);
128
+
129
+ if ($point instanceof Point) {
130
+ $input['border'] = ServiceArea::createMultiPolygonFromPoint($point, $radius);
131
+ }
132
+ }
65
133
 
66
134
  // update the serviceArea
67
135
  $serviceArea->update($input);
@@ -72,7 +72,7 @@ class ServiceQuoteController extends Controller
72
72
  }
73
73
 
74
74
  // get all waypoints
75
- $waypoints = $payload->getAllStops()->mapInto(Place::class);
75
+ $waypoints = $payload->getAllStops();
76
76
 
77
77
  // if quote for single service
78
78
  if ($service && $service !== 'all') {
@@ -30,7 +30,8 @@ class ServiceRateController extends Controller
30
30
  'rate_calculation_method',
31
31
  'currency',
32
32
  'base_fee',
33
- 'per_km_flat_rate_fee',
33
+ 'per_meter_unit',
34
+ 'per_meter_flat_rate_fee',
34
35
  'meter_fees',
35
36
  'meter_fees.*.distance',
36
37
  'meter_fees.*.fee',
@@ -77,7 +78,7 @@ class ServiceRateController extends Controller
77
78
  ServiceRateFee::create([
78
79
  'service_rate_uuid' => $serviceRate->uuid,
79
80
  'distance' => Utils::get($meterFee, 'distance'),
80
- 'distance_unit' => 'm',
81
+ 'distance_unit' => $request->input('per_meter_unit', 'm'),
81
82
  'fee' => Utils::get($meterFee, 'fee'),
82
83
  'currency' => $serviceRate->currency,
83
84
  ]);
@@ -39,8 +39,8 @@ class TrackingNumberController extends Controller
39
39
  );
40
40
 
41
41
  if (is_array($owner)) {
42
- $input['owner_uuid'] = Utils::get($owner, 'uuid');
43
- $input['type'] = Utils::getModelClassName(Utils::get($owner, 'table'));
42
+ $input['owner_uuid'] = Utils::get($owner, 'uuid');
43
+ $input['owner_type'] = Utils::getModelClassName(Utils::get($owner, 'table'));
44
44
  }
45
45
  }
46
46