@fleetbase/fleetops-engine 0.4.16 → 0.4.17

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 (218) hide show
  1. package/.php-cs-fixer.php +2 -0
  2. package/addon/components/activity-event-selector.hbs +35 -0
  3. package/addon/components/activity-event-selector.js +85 -0
  4. package/addon/components/activity-form-panel.hbs +23 -0
  5. package/addon/components/activity-form-panel.js +90 -0
  6. package/addon/components/activity-logic-builder.hbs +80 -0
  7. package/addon/components/activity-logic-builder.js +260 -0
  8. package/addon/components/contact-form-panel.hbs +1 -1
  9. package/addon/components/contact-panel.hbs +1 -1
  10. package/addon/components/custom-entity-form-panel.hbs +43 -0
  11. package/addon/components/custom-entity-form-panel.js +129 -0
  12. package/addon/components/custom-field-form-panel/options-input.hbs +12 -0
  13. package/addon/components/custom-field-form-panel/options-input.js +139 -0
  14. package/addon/components/custom-field-form-panel.hbs +77 -0
  15. package/addon/components/custom-field-form-panel.js +144 -0
  16. package/addon/components/custom-field.hbs +63 -41
  17. package/addon/components/custom-field.js +123 -25
  18. package/addon/components/driver-form-panel.hbs +1 -1
  19. package/addon/components/driver-panel.hbs +1 -1
  20. package/addon/components/edit-order-route-panel.hbs +1 -1
  21. package/addon/components/fleet-form-panel.hbs +1 -1
  22. package/addon/components/fleet-panel.hbs +1 -1
  23. package/addon/components/fuel-report-form-panel.hbs +1 -1
  24. package/addon/components/fuel-report-panel.hbs +1 -1
  25. package/addon/components/issue-form-panel.hbs +1 -1
  26. package/addon/components/issue-panel.hbs +1 -1
  27. package/addon/components/joint-graph.hbs +1 -0
  28. package/addon/components/joint-graph.js +103 -0
  29. package/addon/components/layout/fleet-ops-sidebar.hbs +3 -3
  30. package/addon/components/layout/fleet-ops-sidebar.js +1 -0
  31. package/addon/components/live-map.js +71 -28
  32. package/addon/components/modals/new-custom-field-group.hbs +5 -0
  33. package/addon/components/modals/new-order-config.hbs +3 -3
  34. package/addon/components/modals/order-new-activity.hbs +1 -1
  35. package/addon/components/order-config-manager/activity-flow.hbs +11 -0
  36. package/addon/components/order-config-manager/activity-flow.js +964 -0
  37. package/addon/components/order-config-manager/custom-fields.hbs +50 -0
  38. package/addon/components/order-config-manager/custom-fields.js +276 -0
  39. package/addon/components/order-config-manager/details.hbs +23 -0
  40. package/addon/components/order-config-manager/details.js +97 -0
  41. package/addon/components/order-config-manager/entities.hbs +54 -0
  42. package/addon/components/order-config-manager/entities.js +227 -0
  43. package/addon/components/order-config-manager-overlay.hbs +26 -0
  44. package/addon/components/order-config-manager-overlay.js +60 -0
  45. package/addon/components/order-config-manager.hbs +15 -0
  46. package/addon/components/order-config-manager.js +285 -0
  47. package/addon/components/order-flow.hbs +1 -0
  48. package/addon/components/order-flow.js +3 -0
  49. package/addon/components/place-form-panel.hbs +1 -1
  50. package/addon/components/place-panel.hbs +1 -1
  51. package/addon/components/vehicle-form-panel.hbs +1 -1
  52. package/addon/components/vehicle-panel.hbs +1 -1
  53. package/addon/components/vendor-form-panel.hbs +1 -1
  54. package/addon/components/vendor-panel.hbs +1 -1
  55. package/addon/controllers/application.js +5 -1
  56. package/addon/controllers/operations/order-config.js +42 -0
  57. package/addon/controllers/operations/orders/index/new.js +125 -21
  58. package/addon/controllers/operations/orders/index/view.js +87 -4
  59. package/addon/controllers/operations/orders/index.js +2 -2
  60. package/addon/engine.js +10 -1
  61. package/addon/initializers/load-jointjs.js +16 -0
  62. package/addon/routes/application.js +1 -1
  63. package/addon/routes/operations/order-config.js +28 -0
  64. package/addon/routes/operations/orders/index/new.js +2 -3
  65. package/addon/routes/operations/orders/index/view.js +1 -1
  66. package/addon/routes.js +1 -0
  67. package/addon/services/context-panel.js +65 -3
  68. package/addon/styles/fleetops-engine.css +268 -0
  69. package/addon/templates/application.hbs +1 -1
  70. package/addon/templates/operations/order-config.hbs +55 -0
  71. package/addon/templates/operations/orders/index/new.hbs +98 -339
  72. package/addon/templates/operations/orders/index/view.hbs +36 -96
  73. package/addon/templates/operations/orders/index.hbs +0 -1
  74. package/addon/utils/apply-context-component-arguments.js +4 -2
  75. package/addon/utils/create-custom-entity.js +22 -0
  76. package/addon/utils/create-flow-activity.js +31 -0
  77. package/addon/utils/get-custom-field-type-map.js +34 -0
  78. package/app/components/activity-event-selector.js +1 -0
  79. package/app/components/activity-form-panel.js +1 -0
  80. package/app/components/activity-logic-builder.js +1 -0
  81. package/app/components/custom-entity-form-panel.js +1 -0
  82. package/app/components/custom-field-form-panel/options-input.js +1 -0
  83. package/app/components/custom-field-form-panel.js +1 -0
  84. package/app/components/joint-graph.js +1 -0
  85. package/app/components/modals/new-custom-field-group.js +1 -0
  86. package/app/components/order-config-manager/activity-flow.js +1 -0
  87. package/app/components/order-config-manager/custom-fields.js +1 -0
  88. package/app/components/order-config-manager/details.js +1 -0
  89. package/app/components/order-config-manager/entities.js +1 -0
  90. package/app/components/order-config-manager-overlay.js +1 -0
  91. package/app/components/order-config-manager.js +1 -0
  92. package/app/components/order-flow.js +1 -0
  93. package/app/controllers/operations/order-config.js +1 -0
  94. package/app/routes/operations/order-config.js +1 -0
  95. package/app/templates/operations/order-config.js +1 -0
  96. package/app/utils/create-custom-entity.js +1 -0
  97. package/app/utils/create-flow-activity.js +1 -0
  98. package/app/utils/get-custom-field-type-map.js +1 -0
  99. package/composer.json +4 -3
  100. package/config/environment.js +1 -0
  101. package/extension.json +1 -1
  102. package/index.js +20 -0
  103. package/package.json +7 -5
  104. package/server/migrations/2023_04_27_053456_create_contacts_table.php +1 -2
  105. package/server/migrations/2023_04_27_053456_create_drivers_table.php +1 -2
  106. package/server/migrations/2023_04_27_053456_create_entities_table.php +1 -2
  107. package/server/migrations/2023_04_27_053456_create_fleet_drivers_table.php +1 -2
  108. package/server/migrations/2023_04_27_053456_create_fleets_table.php +1 -2
  109. package/server/migrations/2023_04_27_053456_create_fuel_reports_table.php +1 -2
  110. package/server/migrations/2023_04_27_053456_create_integrated_vendors_table.php +1 -2
  111. package/server/migrations/2023_04_27_053456_create_issues_table.php +1 -2
  112. package/server/migrations/2023_04_27_053456_create_orders_table.php +1 -2
  113. package/server/migrations/2023_04_27_053456_create_payloads_table.php +1 -2
  114. package/server/migrations/2023_04_27_053456_create_places_table.php +1 -2
  115. package/server/migrations/2023_04_27_053456_create_positions_table.php +1 -2
  116. package/server/migrations/2023_04_27_053456_create_proofs_table.php +1 -2
  117. package/server/migrations/2023_04_27_053456_create_purchase_rates_table.php +1 -2
  118. package/server/migrations/2023_04_27_053456_create_routes_table.php +1 -2
  119. package/server/migrations/2023_04_27_053456_create_service_areas_table.php +1 -2
  120. package/server/migrations/2023_04_27_053456_create_service_quote_items_table.php +1 -2
  121. package/server/migrations/2023_04_27_053456_create_service_quotes_table.php +1 -2
  122. package/server/migrations/2023_04_27_053456_create_service_rate_fees_table.php +1 -2
  123. package/server/migrations/2023_04_27_053456_create_service_rate_parcel_fees_table.php +1 -2
  124. package/server/migrations/2023_04_27_053456_create_service_rates_table.php +1 -2
  125. package/server/migrations/2023_04_27_053456_create_tracking_numbers_table.php +1 -2
  126. package/server/migrations/2023_04_27_053456_create_tracking_statuses_table.php +1 -2
  127. package/server/migrations/2023_04_27_053456_create_vehicles_table.php +1 -2
  128. package/server/migrations/2023_04_27_053456_create_vendors_table.php +1 -2
  129. package/server/migrations/2023_04_27_053456_create_waypoints_table.php +1 -2
  130. package/server/migrations/2023_04_27_053456_create_zones_table.php +1 -2
  131. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_companies_table.php +1 -2
  132. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_contacts_table.php +1 -2
  133. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_drivers_table.php +1 -2
  134. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_entities_table.php +1 -2
  135. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleet_drivers_table.php +1 -2
  136. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleets_table.php +1 -2
  137. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fuel_reports_table.php +1 -2
  138. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_integrated_vendors_table.php +1 -2
  139. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_issues_table.php +1 -2
  140. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_orders_table.php +1 -2
  141. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_payloads_table.php +1 -2
  142. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_places_table.php +1 -2
  143. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_positions_table.php +1 -2
  144. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_proofs_table.php +1 -2
  145. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_purchase_rates_table.php +1 -2
  146. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_routes_table.php +1 -2
  147. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_areas_table.php +1 -2
  148. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quote_items_table.php +1 -2
  149. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quotes_table.php +1 -2
  150. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_fees_table.php +1 -2
  151. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_parcel_fees_table.php +1 -2
  152. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rates_table.php +1 -2
  153. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_numbers_table.php +1 -2
  154. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_statuses_table.php +1 -2
  155. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vehicles_table.php +1 -2
  156. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vendors_table.php +1 -2
  157. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_waypoints_table.php +1 -2
  158. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_zones_table.php +1 -2
  159. package/server/migrations/2023_09_14_074512_update_vehicles_table.php +1 -2
  160. package/server/migrations/2023_09_14_074619_create_vehicle_devices_table.php +35 -36
  161. package/server/migrations/2023_09_26_071205_add_online_column_to_vehicles_table.php +1 -2
  162. package/server/migrations/2023_09_26_083957_create_fleet_vehicles_table.php +1 -2
  163. package/server/migrations/2023_09_27_023757_add_column_to_fleets_table.php +1 -2
  164. package/server/migrations/2023_10_05_074811_update_vehicle.php +1 -2
  165. package/server/migrations/2023_10_25_093014_create_vehicle_device_events_table.php +1 -2
  166. package/server/migrations/2023_11_03_072503_refactor_issues_table_columns.php +1 -2
  167. package/server/migrations/2023_11_06_040645_refactor_fuel_reports_table.php +1 -2
  168. package/server/migrations/2023_11_09_041807_add_status_column_to_fuel_reports_table.php +1 -2
  169. package/server/migrations/2023_11_15_062814_add_comments_column_and_resolved_at_column_to_vehicle_device_events_table.php +1 -2
  170. package/server/migrations/2023_11_17_053001_add_category_uuid_to_entities_table.php +1 -2
  171. package/server/migrations/2023_11_28_074244_add_supplier_uuid_column_to_entities_table.php +1 -2
  172. package/server/migrations/2023_12_14_100209_add_meta_column_on_driver_table copy.php +1 -2
  173. package/server/migrations/2024_02_18_100209_add_avatar_url_columns_table.php +3 -4
  174. package/server/migrations/2024_02_27_093648_create_order_configs_table.php +43 -0
  175. package/server/migrations/2024_03_07_075508_add_order_config_uuid_column_to_orders_table.php +28 -0
  176. package/server/seeders/OrderConfigSeeder.php +151 -0
  177. package/server/src/Casts/OrderConfigEntities.php +53 -0
  178. package/server/src/Console/Commands/FixLegacyOrderConfigs.php +66 -0
  179. package/server/src/Events/DriverLocationChanged.php +1 -1
  180. package/server/src/Events/DriverSimulatedLocationChanged.php +1 -1
  181. package/server/src/Flow/Activity.php +232 -6
  182. package/server/src/Flow/Condition.php +84 -0
  183. package/server/src/Flow/Event.php +88 -0
  184. package/server/src/Flow/Flow.php +50 -0
  185. package/server/src/Flow/FlowResource.php +143 -0
  186. package/server/src/Flow/Logic.php +57 -1
  187. package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -2
  188. package/server/src/Http/Controllers/Api/v1/IssueController.php +132 -0
  189. package/server/src/Http/Controllers/Api/v1/OrderController.php +130 -57
  190. package/server/src/Http/Controllers/Api/v1/OrganizationController.php +27 -0
  191. package/server/src/Http/Controllers/Api/v1/PlaceController.php +2 -3
  192. package/server/src/Http/Controllers/Controller.php +9 -0
  193. package/server/src/Http/Controllers/FleetOpsController.php +7 -0
  194. package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +5 -259
  195. package/server/src/Http/Controllers/Internal/v1/OrderController.php +46 -26
  196. package/server/src/Http/Controllers/Internal/v1/SettingController.php +20 -0
  197. package/server/src/Http/Filter/OrderConfigFilter.php +13 -0
  198. package/server/src/Http/Requests/CreateIssueRequest.php +19 -0
  199. package/server/src/Http/Requests/UpdateIssueRequest.php +7 -0
  200. package/server/src/Http/Resources/v1/Order.php +3 -0
  201. package/server/src/Listeners/HandleOrderCanceled.php +8 -4
  202. package/server/src/Listeners/HandleOrderDispatched.php +14 -12
  203. package/server/src/Models/Order.php +527 -31
  204. package/server/src/Models/OrderConfig.php +419 -0
  205. package/server/src/Models/Payload.php +6 -7
  206. package/server/src/Notifications/OrderAssigned.php +1 -1
  207. package/server/src/Notifications/OrderCanceled.php +1 -1
  208. package/server/src/Notifications/OrderDispatchFailed.php +1 -1
  209. package/server/src/Notifications/OrderDispatched.php +1 -1
  210. package/server/src/Notifications/OrderPing.php +1 -1
  211. package/server/src/Providers/FleetOpsServiceProvider.php +3 -1
  212. package/server/src/Providers/NotificationServiceProvider.php +2 -1
  213. package/server/src/Support/Utils.php +17 -0
  214. package/server/src/Traits/HasTrackingNumber.php +9 -9
  215. package/server/src/routes.php +19 -11
  216. package/translations/en-us.yaml +137 -0
  217. package/server/src/Flow/Config.php +0 -7
  218. package/server/src/Support/Flow.php +0 -653
@@ -5,6 +5,7 @@ namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
5
5
  use Fleetbase\FleetOps\Events\OrderDispatchFailed;
6
6
  use Fleetbase\FleetOps\Events\OrderReady;
7
7
  use Fleetbase\FleetOps\Events\OrderStarted;
8
+ use Fleetbase\FleetOps\Flow\Activity;
8
9
  use Fleetbase\FleetOps\Http\Requests\CreateOrderRequest;
9
10
  use Fleetbase\FleetOps\Http\Requests\ScheduleOrderRequest;
10
11
  use Fleetbase\FleetOps\Http\Requests\UpdateOrderRequest;
@@ -19,7 +20,6 @@ use Fleetbase\FleetOps\Models\Place;
19
20
  use Fleetbase\FleetOps\Models\Proof;
20
21
  use Fleetbase\FleetOps\Models\ServiceQuote;
21
22
  use Fleetbase\FleetOps\Models\Waypoint;
22
- use Fleetbase\FleetOps\Support\Flow;
23
23
  use Fleetbase\FleetOps\Support\Utils;
24
24
  use Fleetbase\Http\Controllers\Controller;
25
25
  use Fleetbase\Models\Company;
@@ -35,7 +35,7 @@ class OrderController extends Controller
35
35
  /**
36
36
  * Creates a new Fleetbase Order resource.
37
37
  *
38
- * @param \Illuminate\Http\Request|\Fleetbase\Http\Requests\CreateOrderRequest $request
38
+ * @param Request|\Fleetbase\Http\Requests\CreateOrderRequest $request
39
39
  *
40
40
  * @return \Fleetbase\Http\Resources\Order
41
41
  */
@@ -779,23 +779,21 @@ class OrderController extends Controller
779
779
  return response()->apiError('No driver assigned to order.');
780
780
  }
781
781
 
782
- // get the next order activity
783
- $flow = $activity = Flow::getNextActivity($order);
782
+ // Get the order config
783
+ $orderConfig = $order->config();
784
784
 
785
- // order is not dispatched if next activity code is dispatch or order is not flagged as dispatched
786
- $isNotDispatched = $activity['code'] === 'dispatched' || $order->isNotDispatched;
785
+ // Get the order started activity
786
+ $activity = $orderConfig->getStartedActivity();
787
787
 
788
- // if order is not dispatched yet $activity['code'] === 'dispatched' || $order->dispatched === true
788
+ // Order is not dispatched if next activity code is dispatch or order is not flagged as dispatched
789
+ $isNotDispatched = $order->isNotDispatched;
790
+
791
+ // If order is not dispatched yet $activity->is('dispatched') || $order->dispatched === true
789
792
  // and not skipping throw order not dispatched error
790
793
  if ($isNotDispatched && !$skipDispatch) {
791
794
  return response()->apiError('Order has not been dispatched yet and cannot be started.');
792
795
  }
793
796
 
794
- // if we're going to skip the dispatch get the next activity status and flow and continue
795
- if ($isNotDispatched && $skipDispatch) {
796
- $flow = $activity = Flow::getAfterNextActivity($order);
797
- }
798
-
799
797
  // set order to started
800
798
  $order->started = true;
801
799
  $order->started_at = now();
@@ -816,7 +814,7 @@ class OrderController extends Controller
816
814
  $order->setRelation('payload', $payload);
817
815
 
818
816
  // update order activity
819
- $updateActivityRequest = new Request(['activity' => $flow]);
817
+ $updateActivityRequest = new Request(['activity' => $activity->serialize()]);
820
818
 
821
819
  // update activity
822
820
  return $this->updateActivity($order, $updateActivityRequest);
@@ -869,15 +867,20 @@ class OrderController extends Controller
869
867
  return response()->apiError('Order is already completed.');
870
868
  }
871
869
 
872
- $activity = $request->input('activity', Flow::getNextActivity($order));
870
+ // Get the order config
871
+ $orderConfig = $order->config();
872
+ $activity = $request->array('activity');
873
+ if (!Utils::isActivity($activity)) {
874
+ $activity = new Activity($activity, $order->getConfigFlow());
875
+ }
873
876
 
874
877
  // if we're going to skip the dispatch get the next activity status and flow and continue
875
- if (is_array($activity) && $activity['code'] === 'dispatched' && $skipDispatch) {
876
- $activity = Flow::getAfterNextActivity($order);
878
+ if (Utils::isActivity($activity) && $activity->is('dispatched') && $skipDispatch) {
879
+ $activity = $orderConfig->getStartedActivity();
877
880
  }
878
881
 
879
882
  // handle pickup/dropoff order activity update as normal
880
- if (is_array($activity) && $activity['code'] === 'dispatched') {
883
+ if (Utils::isActivity($activity) && $activity->is('dispatched')) {
881
884
  // make sure driver is assigned if not trigger failed dispatch
882
885
  if (!$order->hasDriverAssigned && !$order->adhoc) {
883
886
  event(new OrderDispatchFailed($order, 'No driver assigned for order to dispatch to.'));
@@ -898,7 +901,7 @@ class OrderController extends Controller
898
901
  $order->payload->setFirstWaypoint($activity, $location);
899
902
  }
900
903
 
901
- if (is_array($activity) && $activity['code'] === 'completed' && $order->payload->isMultipleDropOrder) {
904
+ if (Utils::isActivity($activity) && $activity->completesOrder() && $order->payload->isMultipleDropOrder) {
902
905
  // confirm every waypoint is completed
903
906
  $isCompleted = $order->payload->waypointMarkers->every(function ($waypoint) {
904
907
  return $waypoint->status_code === 'COMPLETED';
@@ -921,24 +924,26 @@ class OrderController extends Controller
921
924
  }
922
925
  }
923
926
 
924
- if (is_array($activity) && $activity['code'] === 'completed' && $order->driverAssigned) {
925
- // unset from driver current job
926
- $order->driverAssigned->unassignCurrentOrder();
927
- $order->notifyCompleted();
928
- }
929
-
927
+ // Update activity
930
928
  $order->updateActivity($activity, $proof);
931
929
 
932
930
  // also update for each order entities if not multiple drop order
933
931
  // all entities will share the same activity status as is one drop order
934
932
  if (!$order->payload->isMultipleDropOrder) {
935
933
  foreach ($order->payload->entities as $entity) {
936
- $entity->insertActivity($activity['status'], $activity['details'] ?? '', $location, $activity['code'], $proof);
934
+ $entity->insertActivity($activity, $location, $proof);
937
935
  }
938
936
  } else {
939
937
  $order->payload->updateWaypointActivity($activity, $location);
940
938
  }
941
939
 
940
+ // Handle order completion
941
+ if (Utils::isActivity($activity) && $activity->completesOrder()) {
942
+ // unset from driver current job
943
+ $order->driverAssigned->unassignCurrentOrder();
944
+ $order->complete();
945
+ }
946
+
942
947
  return new OrderResource($order);
943
948
  }
944
949
 
@@ -947,10 +952,8 @@ class OrderController extends Controller
947
952
  *
948
953
  * @return \Illuminate\Http\Response
949
954
  */
950
- public function getNextActivity(string $id, Request $request)
955
+ public function getNextActivity(string $id)
951
956
  {
952
- $waypointId = $request->input('waypoint');
953
-
954
957
  try {
955
958
  $order = Order::findRecordOrFail($id, ['payload']);
956
959
  } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
@@ -962,22 +965,7 @@ class OrderController extends Controller
962
965
  );
963
966
  }
964
967
 
965
- $isMultipleDropOrder = $order->payload->isMultipleDropOrder;
966
-
967
- if ($waypointId && $isMultipleDropOrder) {
968
- $waypoint = Waypoint::where('payload_uuid', $order->payload_uuid)->where(function ($q) use ($waypointId) {
969
- $q->whereHas('place', function ($q) use ($waypointId) {
970
- $q->where('public_id', $waypointId);
971
- });
972
- $q->orWhere('public_id', $waypointId);
973
- })->withoutGlobalScopes()->first();
974
-
975
- $activity = Flow::getOrderWaypointFlow($order, $waypoint);
976
-
977
- return response()->json($activity);
978
- }
979
-
980
- $activity = Flow::getOrderFlow($order);
968
+ $activity = $order->config()->nextActivity();
981
969
 
982
970
  return response()->json($activity);
983
971
  }
@@ -1010,24 +998,17 @@ class OrderController extends Controller
1010
998
  return response()->apiError('Not all waypoints completed for order.');
1011
999
  }
1012
1000
 
1013
- $activity = [
1014
- 'status' => 'Order completed',
1015
- 'details' => 'Driver has completed order for all waypoints',
1016
- 'code' => 'completed',
1017
- ];
1018
-
1001
+ $activity = $order->config()->getCompletedActivity();
1019
1002
  if ($order->driverAssigned) {
1020
1003
  // unset from driver current job
1021
1004
  $order->driverAssigned->unassignCurrentOrder();
1022
1005
  }
1023
1006
 
1024
- $order->notifyCompleted();
1025
-
1026
1007
  /** @var \Fleetbase\LaravelMysqlSpatial\Types\Point */
1027
1008
  $location = $order->getLastLocation();
1028
-
1029
- $order->setStatus($activity['code']);
1030
- $order->insertActivity($activity['status'], $activity['details'] ?? '', $location, $activity['code']);
1009
+ $order->setStatus($activity->code);
1010
+ $order->insertActivity($activity, $location);
1011
+ $order->notifyCompleted();
1031
1012
 
1032
1013
  return new OrderResource($order);
1033
1014
  }
@@ -1112,7 +1093,7 @@ class OrderController extends Controller
1112
1093
  *
1113
1094
  * @return void
1114
1095
  */
1115
- public function captureQrScan(string $id, ?string $subjectId = null, Request $request)
1096
+ public function captureQrScan(Request $request, string $id, ?string $subjectId = null)
1116
1097
  {
1117
1098
  $code = $request->input('code');
1118
1099
  $data = $request->input('data', []);
@@ -1183,7 +1164,7 @@ class OrderController extends Controller
1183
1164
  *
1184
1165
  * @return void
1185
1166
  */
1186
- public function captureSignature(string $id, ?string $subjectId = null, Request $request)
1167
+ public function captureSignature(Request $request, string $id, ?string $subjectId = null)
1187
1168
  {
1188
1169
  $disk = $request->input('disk', config('filesystems.default'));
1189
1170
  $bucket = $request->input('bucket', config('filesystems.disks.' . $disk . '.bucket', config('filesystems.disks.s3.bucket')));
@@ -1269,4 +1250,96 @@ class OrderController extends Controller
1269
1250
 
1270
1251
  return new ProofResource($proof);
1271
1252
  }
1253
+
1254
+ /**
1255
+ * Validate a photo.
1256
+ *
1257
+ * @return void
1258
+ */
1259
+ public function capturePhoto(Request $request, string $id, ?string $subjectId = null)
1260
+ {
1261
+ $disk = $request->input('disk', config('filesystems.default'));
1262
+ $bucket = $request->input('bucket', config('filesystems.disks.' . $disk . '.bucket', config('filesystems.disks.s3.bucket')));
1263
+ $photo = $request->input('photo');
1264
+ $data = $request->input('data', []);
1265
+ $remarks = $request->input('remarks', 'Verified by Photo');
1266
+ $type = $subjectId ? strtok($subjectId, '_') : null;
1267
+
1268
+ try {
1269
+ $order = Order::findRecordOrFail($id);
1270
+ } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
1271
+ return response()->json(
1272
+ [
1273
+ 'error' => 'Order resource not found.',
1274
+ ],
1275
+ 404
1276
+ );
1277
+ }
1278
+
1279
+ if (!$photo) {
1280
+ return response()->apiError('No photo data to capture.');
1281
+ }
1282
+
1283
+ $subject = $type === null ? $order : null;
1284
+
1285
+ switch ($type) {
1286
+ case 'place':
1287
+ case 'waypoint':
1288
+ $subject = Waypoint::where('payload_uuid', $order->payload_uuid)->where(function ($q) use ($subjectId) {
1289
+ $q->whereHas('place', function ($q) use ($subjectId) {
1290
+ $q->where('public_id', $subjectId);
1291
+ });
1292
+ $q->orWhere('public_id', $subjectId);
1293
+ })->withoutGlobalScopes()->first();
1294
+ break;
1295
+
1296
+ case 'entity':
1297
+ $subject = Entity::where('public_id', $subjectId)->withoutGlobalScopes()->first();
1298
+ break;
1299
+
1300
+ default:
1301
+ break;
1302
+ }
1303
+
1304
+ if (!$subject) {
1305
+ return response()->apiError('Unable to capture photo');
1306
+ }
1307
+
1308
+ // create proof instance
1309
+ $proof = Proof::create([
1310
+ 'company_uuid' => session('company'),
1311
+ 'order_uuid' => $order->uuid,
1312
+ 'subject_uuid' => $subject->uuid,
1313
+ 'subject_type' => Utils::getModelClassName($subject),
1314
+ 'remarks' => $remarks,
1315
+ 'raw_data' => $photo,
1316
+ 'data' => $data,
1317
+ ]);
1318
+
1319
+ // set the photo storage path
1320
+ $path = 'uploads/' . session('company') . '/photos/' . $proof->public_id . '.png';
1321
+
1322
+ // upload photo
1323
+ Storage::disk($disk)->put($path, base64_decode($photo));
1324
+
1325
+ // create file record for upload
1326
+ $file = File::create([
1327
+ 'company_uuid' => session('company'),
1328
+ 'uploader_uuid' => session('user'),
1329
+ 'name' => basename($path),
1330
+ 'original_filename' => basename($path),
1331
+ 'extension' => 'png',
1332
+ 'content_type' => 'image/png',
1333
+ 'path' => $path,
1334
+ 'bucket' => $bucket,
1335
+ 'type' => 'photo',
1336
+ 'size' => Utils::getBase64ImageSize($photo),
1337
+ ])->setKey($proof);
1338
+
1339
+ // set file to proof
1340
+ $proof->file_uuid = $file->uuid;
1341
+ $proof->save();
1342
+
1343
+ return new ProofResource($proof);
1344
+ }
1272
1345
  }
@@ -0,0 +1,27 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
4
+
5
+ use Fleetbase\Http\Controllers\Controller;
6
+ use Fleetbase\Http\Resources\Organization;
7
+ use Fleetbase\Models\Company;
8
+
9
+ class OrganizationController extends Controller
10
+ {
11
+ /**
12
+ * Return List organizations.
13
+ *
14
+ * @return Organization
15
+ */
16
+ public function listOrganizations()
17
+ {
18
+ $companies = Company::whereHas('users')->take(10)->get()->map(function ($company) {
19
+ return [
20
+ 'name' => $company->name,
21
+ 'id' => $company->public_id,
22
+ ];
23
+ });
24
+
25
+ return response()->json($companies);
26
+ }
27
+ }
@@ -130,9 +130,8 @@ class PlaceController extends Controller
130
130
  ]);
131
131
 
132
132
  // check if missing location
133
- $isMissingLocation = empty($input['location']);
134
-
135
133
  // set a default location for creation
134
+ $isMissingLocation = empty($input['location']);
136
135
  if ($isMissingLocation) {
137
136
  $input['location'] = new Point(0, 0);
138
137
  }
@@ -141,7 +140,7 @@ class PlaceController extends Controller
141
140
  $place->fill($input);
142
141
 
143
142
  // attempt to find and set latitude and longitude
144
- if ($isMissingLocation || $request->missing(['latitude', 'longitude', 'location']) || $place->isMissing('country')) {
143
+ if ($isMissingLocation || $request->missing(['latitude', 'longitude', 'location']) || empty($place->country)) {
145
144
  $geocoded = Geocoder::geocode($place->toAddressString(['name']))
146
145
  ->get()
147
146
  ->first();
@@ -0,0 +1,9 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Controllers;
4
+
5
+ use Illuminate\Routing\Controller as BaseController;
6
+
7
+ class Controller extends BaseController
8
+ {
9
+ }
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers;
4
4
 
5
+ use Fleetbase\FleetOps\Models\Order;
5
6
  use Fleetbase\Http\Controllers\FleetbaseController;
6
7
 
7
8
  class FleetOpsController extends FleetbaseController
@@ -10,4 +11,10 @@ class FleetOpsController extends FleetbaseController
10
11
  * The package namespace used to resolve from.
11
12
  */
12
13
  public string $namespace = '\\Fleetbase\\FleetOps';
14
+
15
+ public function test()
16
+ {
17
+ $order = Order::where('public_id', '')->first();
18
+ dd($order->config()->getNextActivity());
19
+ }
13
20
  }
@@ -2,268 +2,14 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
- use Fleetbase\FleetOps\Models\Order;
6
- use Fleetbase\FleetOps\Support\Flow;
7
- use Fleetbase\FleetOps\Support\Utils;
8
- use Fleetbase\Http\Controllers\Controller;
9
- use Fleetbase\Models\Category;
10
- use Fleetbase\Models\Extension;
11
- use Fleetbase\Models\ExtensionInstall;
12
- use Fleetbase\Models\Type;
13
- use Illuminate\Http\Request;
14
- use Illuminate\Support\Str;
5
+ use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
15
6
 
16
- class OrderConfigController extends Controller
7
+ class OrderConfigController extends FleetOpsController
17
8
  {
18
9
  /**
19
- * Retrieve all installed or created order configurations.
10
+ * The resource to query.
20
11
  *
21
- * @return \Illuminate\Http\Response
12
+ * @var string
22
13
  */
23
- public function getInstalled(Request $request)
24
- {
25
- $key = $request->input('key');
26
- $namespace = $request->input('namespace');
27
- $single = $request->input('single', false);
28
- $installedExtensions = [];
29
-
30
- // get all installed order configs
31
- $installed = ExtensionInstall::where('company_uuid', session('company'))
32
- ->whereHas(
33
- 'extension',
34
- function ($query) {
35
- $query->where('meta_type', 'order_config');
36
- }
37
- )
38
- ->with('extension')->get();
39
-
40
- // morph installed into extensions
41
- foreach ($installed as $install) {
42
- $installedExtensions[] = $install->asExtension();
43
- }
44
-
45
- // get authored extension installs
46
- $authored = Extension::where(['author_uuid' => session('company'), 'meta_type' => 'order_config', 'status' => 'private'])->get();
47
-
48
- // create array of configs
49
- $configs = collect([...$installedExtensions, ...$authored]);
50
-
51
- // if no installed configs always place default config
52
- if ($configs->isEmpty()) {
53
- $configs = $configs->merge(Flow::getAllDefaultOrderConfigs());
54
- }
55
-
56
- // filter by key
57
- if ($key) {
58
- $configs = $configs->where('key', $key);
59
- }
60
-
61
- // filter by namespace
62
- if ($namespace) {
63
- $configs = $configs->where('namespace', $namespace);
64
- }
65
-
66
- if ($single) {
67
- return response()->json($configs->first());
68
- }
69
-
70
- return response()->json($configs->values()->toArray());
71
- }
72
-
73
- /**
74
- * Save an order extension, whether installed or authored.
75
- *
76
- * @return \Illuminate\Http\Response
77
- */
78
- public function save(Request $request)
79
- {
80
- $data = $request->input('data', []);
81
- $isInstalled = isset($data['installed']) && Utils::isTrue($data['installed']);
82
-
83
- // if the extension is from installed
84
- if ($isInstalled) {
85
- // get the extension install record
86
- $install = ExtensionInstall::where('uuid', $data['install_uuid'])->first();
87
-
88
- // update install record
89
- $overwrite = $install->overwrite ?? [];
90
- $overwrite['name'] = $data['name'];
91
- $overwrite['description'] = $data['description'];
92
-
93
- // update json fields
94
- $install->overwrite = $overwrite;
95
- $install->meta = $data['meta'];
96
-
97
- // save changes
98
- $install->save();
99
-
100
- return response()->json(['status' => 'OK']);
101
- }
102
-
103
- // get the extension record
104
- $extension = Extension::where('uuid', $data['uuid'])->first();
105
-
106
- // update extension record
107
- $extension->name = $data['name'];
108
- $extension->description = $data['description'];
109
- $extension->meta = $data['meta'];
110
-
111
- // save
112
- $extension->save();
113
-
114
- return response()->json(['status' => 'OK']);
115
- }
116
-
117
- /**
118
- * Creates a new empty order configuration.
119
- *
120
- * @return \Illuminate\Http\Response
121
- */
122
- public function new(Request $request)
123
- {
124
- $name = $request->input('name');
125
- $description = $request->input('description');
126
- $tags = $request->input('tags', []);
127
-
128
- $company = Flow::getCompanySession();
129
- $category = Category::where(['for' => 'extension', 'name' => 'Logistics'])->first();
130
- $type = Type::where(['for' => 'extension', 'key' => 'config'])->first();
131
-
132
- $orderConfig = Extension::create(
133
- [
134
- 'author_uuid' => session('company'),
135
- 'category_uuid' => $category->uuid,
136
- 'type_uuid' => $type->uuid,
137
- 'name' => $name,
138
- 'description' => $description,
139
- 'display_name' => $name,
140
- 'key' => Str::slug($name),
141
- 'tags' => $tags,
142
- 'namespace' => Extension::createNamespace($company->slug, 'order-config', $name),
143
- 'version' => '0.0.1',
144
- 'core_service' => 0,
145
- 'meta' => ['flow' => Flow::getDefaultOrderFlow()],
146
- 'meta_type' => 'order_config',
147
- 'config' => [],
148
- 'status' => 'private',
149
- ]
150
- );
151
-
152
- return response()->json($orderConfig);
153
- }
154
-
155
- /**
156
- * Clones an order configuration into a new configuration.
157
- *
158
- * @return \Illuminate\Http\Response
159
- */
160
- public function clone(Request $request)
161
- {
162
- $name = $request->input('name');
163
- $description = $request->input('description');
164
- $id = $request->input('id');
165
- $installed = $request->input('installed', false);
166
- $company = Flow::getCompanySession();
167
-
168
- if (!$id) {
169
- return response()->json(
170
- [
171
- 'errors' => ['Extension attempted to clone not found'],
172
- ],
173
- 400
174
- );
175
- }
176
-
177
- // if the extension is from installed
178
- if ($installed) {
179
- // get the extension install record
180
- $install = ExtensionInstall::where('uuid', $id)->first();
181
-
182
- // replicate the install
183
- $clonedInstall = $install->replicate();
184
- $clonedInstall->id = null;
185
- $clonedInstall->uuid = Extension::generateUuid();
186
- $clonedInstall->overwrite = [
187
- 'name' => $name,
188
- 'display_name' => $name,
189
- 'description' => $description,
190
- 'key' => Str::slug($name),
191
- 'namespace' => Extension::createNamespace($company->slug, 'order-config', $name, Str::random(5)),
192
- ];
193
-
194
- // save clone
195
- $clonedInstall->save();
196
-
197
- return response()->json($clonedInstall->asExtension());
198
- }
199
-
200
- // get the extension record
201
- $extension = Extension::where('uuid', $id)->first();
202
-
203
- // replicate the extension record
204
- $clonedExtension = $extension->replicate();
205
- $clonedExtension->id = null;
206
- $clonedExtension->uuid = Extension::generateUuid();
207
- $clonedExtension->public_id = Extension::generatePublicId('ext');
208
- $clonedExtension->name = $name;
209
- $clonedExtension->display_name = $name;
210
- $clonedExtension->description = $description;
211
- $clonedExtension->key = Str::slug($name);
212
- $clonedExtension->namespace = Extension::createNamespace($company->slug, 'order-config', $name, Str::random(5));
213
- $clonedExtension->status = 'private';
214
-
215
- // save clone
216
- $clonedExtension->save();
217
-
218
- return response()->json($clonedExtension);
219
- }
220
-
221
- /**
222
- * Pull all dynamically created meta fields throughout orders of a specific type.
223
- *
224
- * @return \Illuminate\Http\Response
225
- */
226
- public function getDynamicMetaFields(Request $request)
227
- {
228
- $type = $request->input('type', 'transport');
229
- $orders = Order::select('meta')->where('type', $type)->whereNull('deleted_at')->get();
230
- $dynamicFields = collect();
231
-
232
- foreach ($orders as $order) {
233
- $dynamicFields = $dynamicFields->merge(array_keys($order->meta));
234
- }
235
-
236
- return response()->json($dynamicFields->unique()->values());
237
- }
238
-
239
- /**
240
- * Pull all dynamically created meta fields throughout orders of a specific type.
241
- *
242
- * @return \Illuminate\Http\Response
243
- */
244
- public function delete(string $id)
245
- {
246
- $extension = Extension::where(['uuid' => $id, 'author_uuid' => session('company'), 'meta_type' => 'order_config'])->first();
247
-
248
- if ($extension) {
249
- $extension->delete();
250
-
251
- return response()->json(['status' => 'OK', 'deleted' => $extension->uuid]);
252
- }
253
-
254
- $installedExtension = ExtensionInstall::where(['uuid' => $id, 'company_uuid' => session('company')])->first();
255
-
256
- if ($installedExtension) {
257
- $installedExtension->delete();
258
-
259
- return response()->json(['status' => 'OK', 'deleted' => $installedExtension->uuid]);
260
- }
261
-
262
- return response()->json(
263
- [
264
- 'errors' => 'Unable to uninstall order configuration',
265
- ],
266
- 400
267
- );
268
- }
14
+ public $resource = 'order-config';
269
15
  }