@fleetbase/fleetops-engine 0.6.49 → 0.6.50

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 (142) hide show
  1. package/addon/components/customer/create-order-form.hbs +2 -2
  2. package/addon/components/customer/form.hbs +2 -2
  3. package/addon/components/customer/order-form.hbs +2 -2
  4. package/addon/components/customer/orders.hbs +2 -2
  5. package/addon/components/display-place.hbs +2 -2
  6. package/addon/components/map/google-live-map.js +6 -2
  7. package/addon/components/map/leaflet-live-map.hbs +48 -14
  8. package/addon/components/map/leaflet-live-map.js +184 -20
  9. package/addon/components/modals/order-change-destination.hbs +46 -0
  10. package/addon/components/modals/order-change-destination.js +106 -0
  11. package/addon/components/modals/stop-activity.hbs +28 -0
  12. package/addon/components/modals/stop-activity.js +52 -0
  13. package/addon/components/modals/update-order-activity.hbs +45 -3
  14. package/addon/components/modals/update-order-activity.js +143 -5
  15. package/addon/components/orchestrator/resource-panel.hbs +0 -10
  16. package/addon/components/orchestrator/resource-panel.js +2 -4
  17. package/addon/components/order/activity-list.hbs +2 -2
  18. package/addon/components/order/activity-timeline.hbs +31 -29
  19. package/addon/components/order/details/activity.hbs +3 -3
  20. package/addon/components/order/details/activity.js +11 -0
  21. package/addon/components/order/details/documents.js +2 -0
  22. package/addon/components/order/details/purchase-rate.hbs +2 -2
  23. package/addon/components/order/details/route.hbs +11 -3
  24. package/addon/components/order/details/route.js +91 -14
  25. package/addon/components/order/details/tracking.hbs +101 -72
  26. package/addon/components/order/details/tracking.js +149 -2
  27. package/addon/components/order/form/details.hbs +3 -3
  28. package/addon/components/order/form/documents.js +11 -4
  29. package/addon/components/order/form/route.hbs +108 -104
  30. package/addon/components/order/form/route.js +37 -1
  31. package/addon/components/order/form/service-rate.hbs +2 -2
  32. package/addon/components/order-config-manager/activity-flow.hbs +4 -1
  33. package/addon/components/order-config-manager/activity-flow.js +178 -12
  34. package/addon/components/place/address.js +1 -1
  35. package/addon/components/route-list.hbs +17 -17
  36. package/addon/components/route-list.js +42 -10
  37. package/addon/components/service-rate/details.hbs +41 -0
  38. package/addon/components/service-rate/form.hbs +118 -0
  39. package/addon/components/service-rate/form.js +55 -0
  40. package/addon/components/vehicle/form.js +1 -1
  41. package/addon/components/vehicle/pill.hbs +1 -1
  42. package/addon/controllers/management/vehicles/index/new.js +1 -1
  43. package/addon/controllers/operations/orders/index/details.js +4 -4
  44. package/addon/controllers/operations/orders/index.js +14 -0
  45. package/addon/helpers/place-address-html.js +2 -2
  46. package/addon/routes/operations/service-rates/index.js +1 -1
  47. package/addon/services/geofence.js +163 -19
  48. package/addon/services/leaflet-contextmenu-manager.js +27 -0
  49. package/addon/services/vehicle-actions.js +1 -1
  50. package/addon/styles/fleetops-engine.css +91 -1
  51. package/addon/utils/fleet-ops-options.js +2 -1
  52. package/addon/utils/normalize-order-config-flow.js +41 -0
  53. package/addon/utils/place-address-html.js +3 -2
  54. package/addon/utils/route-visualization.js +54 -7
  55. package/app/components/modals/order-change-destination.js +1 -0
  56. package/app/components/modals/stop-activity.js +1 -0
  57. package/composer.json +1 -1
  58. package/extension.json +1 -1
  59. package/package.json +3 -3
  60. package/server/migrations/2026_05_21_000001_add_geographic_rules_to_service_rate_fees_table.php +37 -0
  61. package/server/migrations/2026_05_25_000001_add_endpoint_tracking_refs_to_payloads_table.php +50 -0
  62. package/server/migrations/2026_05_27_000001_default_driver_vehicle_statuses_to_available.php +48 -0
  63. package/server/resources/views/labels/default.php +57 -49
  64. package/server/resources/views/labels/waypoint-label.php +27 -20
  65. package/server/seeders/Testing/ConnectivitySeeder.php +1 -0
  66. package/server/seeders/Testing/FleetSeeder.php +22 -22
  67. package/server/seeders/Testing/OrdersSeeder.php +6 -22
  68. package/server/seeders/Testing/VroomOrchestrationSeeder.php +21 -21
  69. package/server/src/Console/Commands/AuditCustomerUserConflicts.php +75 -0
  70. package/server/src/Exceptions/CustomerUserConflictException.php +13 -0
  71. package/server/src/Http/Controllers/Api/v1/ContactController.php +17 -2
  72. package/server/src/Http/Controllers/Api/v1/CustomerController.php +876 -0
  73. package/server/src/Http/Controllers/Api/v1/DriverController.php +1 -1
  74. package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +54 -0
  75. package/server/src/Http/Controllers/Api/v1/OrderController.php +98 -70
  76. package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -2
  77. package/server/src/Http/Controllers/Api/v1/VehicleController.php +20 -3
  78. package/server/src/Http/Controllers/Internal/v1/ContactController.php +19 -0
  79. package/server/src/Http/Controllers/Internal/v1/LiveController.php +101 -66
  80. package/server/src/Http/Controllers/Internal/v1/OrderController.php +429 -26
  81. package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
  82. package/server/src/Http/Controllers/Internal/v1/SettingController.php +2 -2
  83. package/server/src/Http/Controllers/Internal/v1/VehicleController.php +54 -1
  84. package/server/src/Http/Middleware/AuthenticateCustomerToken.php +34 -0
  85. package/server/src/Http/Requests/CreateCustomerOrderRequest.php +63 -0
  86. package/server/src/Http/Requests/CreateCustomerRequest.php +48 -0
  87. package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
  88. package/server/src/Http/Requests/CreateVehicleRequest.php +25 -1
  89. package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -1
  90. package/server/src/Http/Requests/VerifyCreateCustomerRequest.php +29 -0
  91. package/server/src/Http/Resources/Internal/v1/OrderConfig.php +41 -0
  92. package/server/src/Http/Resources/v1/Customer.php +79 -0
  93. package/server/src/Http/Resources/v1/OrderConfig.php +74 -0
  94. package/server/src/Http/Resources/v1/Payload.php +23 -20
  95. package/server/src/Http/Resources/v1/ServiceArea.php +33 -19
  96. package/server/src/Http/Resources/v1/ServiceRateFee.php +7 -0
  97. package/server/src/Listeners/HandleOrderDispatched.php +2 -2
  98. package/server/src/Models/Contact.php +92 -15
  99. package/server/src/Models/Customer.php +64 -0
  100. package/server/src/Models/Driver.php +12 -3
  101. package/server/src/Models/Entity.php +2 -2
  102. package/server/src/Models/Order.php +29 -4
  103. package/server/src/Models/Payload.php +17 -1
  104. package/server/src/Models/ServiceRate.php +273 -1
  105. package/server/src/Models/ServiceRateFee.php +39 -9
  106. package/server/src/Models/TrackingNumber.php +8 -2
  107. package/server/src/Models/Vehicle.php +18 -2
  108. package/server/src/Models/Waypoint.php +2 -2
  109. package/server/src/Notifications/LateDeparture.php +2 -2
  110. package/server/src/Notifications/ProlongedStoppage.php +2 -2
  111. package/server/src/Notifications/RouteDeviation.php +2 -2
  112. package/server/src/Observers/ContactObserver.php +2 -0
  113. package/server/src/Observers/ServiceRateObserver.php +6 -6
  114. package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +1 -1
  115. package/server/src/Providers/FleetOpsServiceProvider.php +1 -0
  116. package/server/src/Support/Analytics/AbstractAnalytics.php +6 -6
  117. package/server/src/Support/Analytics/FuelEfficiency.php +2 -2
  118. package/server/src/Support/Analytics/OrdersByStatus.php +1 -1
  119. package/server/src/Support/Analytics/RevenueTrend.php +0 -1
  120. package/server/src/Support/Analytics/TopDrivers.php +1 -1
  121. package/server/src/Support/CustomerAuth.php +98 -0
  122. package/server/src/Support/LabelPdf.php +52 -0
  123. package/server/src/Support/Metrics/AbstractMetric.php +4 -4
  124. package/server/src/Support/ResolvesOrderServiceStops.php +512 -0
  125. package/server/src/Tracking/TrackingContextBuilder.php +41 -38
  126. package/server/src/Tracking/TrackingIntelligenceService.php +109 -9
  127. package/server/src/Tracking/TrackingStop.php +13 -11
  128. package/server/src/routes.php +43 -9
  129. package/server/tests/CapacityAllocationEngineTest.php +10 -10
  130. package/server/tests/CustomerContactIdentitySafetyTest.php +54 -0
  131. package/server/tests/CustomerEndpointTest.php +199 -0
  132. package/server/tests/DriverVehicleStatusDefaultTest.php +39 -0
  133. package/server/tests/LabelPdfRenderingTest.php +23 -0
  134. package/server/tests/LiveControllerViewportTest.php +60 -0
  135. package/server/tests/MetricsRegistryTest.php +4 -8
  136. package/server/tests/OrchestrationPayloadBuilderTest.php +2 -2
  137. package/server/tests/OrderConfigEndpointTest.php +86 -0
  138. package/server/tests/OrderFileAttachmentTest.php +20 -0
  139. package/server/tests/ServiceAreaZoneApiShapeTest.php +34 -0
  140. package/server/tests/VehicleDriverAssignmentTest.php +18 -0
  141. package/translations/en-us.yaml +1 -0
  142. package/server/migrations/2026_05_13_000001_repair_customer_contact_user_types.php +0 -86
@@ -0,0 +1,63 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Requests;
4
+
5
+ use Fleetbase\Http\Requests\FleetbaseRequest;
6
+
7
+ /**
8
+ * Validates the body of `POST /v1/customers/orders`.
9
+ *
10
+ * Mirrors the canonical Fleet-Ops Order create shape used by the operator
11
+ * `POST /v1/orders` endpoint: `type` / `order_config`, `scheduled_at`,
12
+ * `notes`, `meta`, and either a nested `payload` or top-level
13
+ * `pickup` / `dropoff` / `return` / `waypoints` / `entities`. Place and
14
+ * Entity sub-objects accept the standard Fleet-Ops Place / Entity field
15
+ * shapes — no client-portal aliases are recognized.
16
+ *
17
+ * `customer` is intentionally not accepted: the controller forces
18
+ * `customer_uuid` from the authenticated Customer-Token. `status`,
19
+ * `driver`, `vehicle`, `facilitator`, `dispatch` and similar operator-tier
20
+ * fields are also out of scope for the customer surface.
21
+ */
22
+ class CreateCustomerOrderRequest extends FleetbaseRequest
23
+ {
24
+ public function authorize(): bool
25
+ {
26
+ return request()->session()->has('api_credential')
27
+ || request()->session()->has('is_sanctum_token');
28
+ }
29
+
30
+ public function rules(): array
31
+ {
32
+ return [
33
+ 'type' => 'nullable|string',
34
+ 'order_config' => 'nullable|string',
35
+ 'scheduled_at' => 'nullable|date',
36
+ 'notes' => 'nullable|string|max:2000',
37
+ 'internal_id' => 'nullable|string|max:191',
38
+ 'meta' => 'nullable|array',
39
+ // Optional ServiceQuote reference (uuid or `sqte_…` public_id).
40
+ // Resolved server-side via `ServiceQuote::resolveFromRequest` and
41
+ // consumed by `$order->purchaseServiceQuote()` after creation.
42
+ 'service_quote' => 'nullable|string',
43
+
44
+ // payload may be an object OR a payload public_id string
45
+ 'payload' => 'nullable',
46
+
47
+ // Top-level alternatives when `payload` is not provided. Each
48
+ // Place sub-object accepts the standard Place fillable shape.
49
+ 'pickup' => 'nullable',
50
+ 'dropoff' => 'nullable',
51
+ 'return' => 'nullable',
52
+ 'waypoints' => 'nullable|array',
53
+ 'entities' => 'nullable|array',
54
+ 'entities.*.name' => 'nullable|string',
55
+ 'entities.*.description' => 'nullable|string',
56
+ 'entities.*.weight' => 'nullable|numeric|min:0',
57
+ 'entities.*.weight_unit' => 'nullable|string',
58
+ 'entities.*.declared_value' => 'nullable|numeric|min:0',
59
+ 'entities.*.currency' => 'nullable|string|size:3',
60
+ 'entities.*.meta' => 'nullable|array',
61
+ ];
62
+ }
63
+ }
@@ -0,0 +1,48 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Requests;
4
+
5
+ use Fleetbase\Http\Requests\FleetbaseRequest;
6
+ use Illuminate\Validation\Rule;
7
+
8
+ /**
9
+ * Validates the body of `POST /v1/customers` (final account creation step).
10
+ *
11
+ * Expects the verification code previously requested via
12
+ * `POST /v1/customers/request-creation-code`.
13
+ */
14
+ class CreateCustomerRequest extends FleetbaseRequest
15
+ {
16
+ public function authorize(): bool
17
+ {
18
+ return request()->session()->has('api_credential')
19
+ || request()->session()->has('is_sanctum_token');
20
+ }
21
+
22
+ public function rules(): array
23
+ {
24
+ return [
25
+ 'identity' => 'required|string',
26
+ 'code' => 'required|exists:verification_codes,code',
27
+ 'name' => 'required|string',
28
+ 'password' => 'required|string|min:8',
29
+ 'email' => [
30
+ 'email', 'nullable',
31
+ Rule::unique('contacts')->where(function ($query) {
32
+ $query->where('company_uuid', session('company'));
33
+
34
+ return $query->whereNull('deleted_at');
35
+ }),
36
+ ],
37
+ 'phone' => [
38
+ 'nullable', 'string',
39
+ Rule::unique('contacts')->where(function ($query) {
40
+ $query->where('company_uuid', session('company'));
41
+
42
+ return $query->whereNull('deleted_at');
43
+ }),
44
+ ],
45
+ 'meta' => 'nullable|array',
46
+ ];
47
+ }
48
+ }
@@ -35,7 +35,7 @@ class CreateDriverRequest extends FleetbaseRequest
35
35
  'country' => 'nullable|size:2',
36
36
  'city' => 'nullable|string',
37
37
  'vehicle' => 'nullable|string|starts_with:vehicle_|exists:vehicles,public_id',
38
- 'status' => 'nullable|string|in:active,inactive',
38
+ 'status' => 'nullable|string|in:active,available,inactive',
39
39
  'vendor' => 'nullable|exists:vendors,public_id',
40
40
  'job' => 'nullable|exists:orders,public_id',
41
41
  'location' => ['nullable', new ResolvablePoint()],
@@ -4,6 +4,7 @@ namespace Fleetbase\FleetOps\Http\Requests;
4
4
 
5
5
  use Fleetbase\FleetOps\Rules\ResolvablePoint;
6
6
  use Fleetbase\Http\Requests\FleetbaseRequest;
7
+ use Illuminate\Validation\Rule;
7
8
 
8
9
  class CreateVehicleRequest extends FleetbaseRequest
9
10
  {
@@ -25,7 +26,30 @@ class CreateVehicleRequest extends FleetbaseRequest
25
26
  public function rules()
26
27
  {
27
28
  return [
28
- 'status' => 'nullable|in:operational,maintenance,decommissioned',
29
+ 'status' => [
30
+ 'nullable',
31
+ Rule::in([
32
+ 'active',
33
+ 'available',
34
+ 'in_use',
35
+ 'maintenance',
36
+ 'out_of_service',
37
+ 'reserved',
38
+ 'retired',
39
+ 'staging',
40
+ 'on_route',
41
+ 'idle',
42
+ 'cleaning',
43
+ 'awaiting_parts',
44
+ 'inspection_due',
45
+ 'inspection_failed',
46
+ 'accident',
47
+ 'compliance_hold',
48
+ 'stolen',
49
+ 'operational',
50
+ 'decommissioned',
51
+ ]),
52
+ ],
29
53
  'vendor' => 'nullable|exists:vendors,public_id',
30
54
  'driver' => 'nullable|exists:drivers,public_id',
31
55
  'location' => ['nullable', new ResolvablePoint()],
@@ -51,7 +51,7 @@ class CreateDriverRequest extends CreateDriverApiRequest
51
51
  'country' => 'nullable|string|size:2',
52
52
  'city' => 'nullable|string|max:255',
53
53
  'vehicle' => ['nullable', new ResolvableVehicle()],
54
- 'status' => 'nullable|string|in:active,inactive',
54
+ 'status' => 'nullable|string|in:active,available,inactive',
55
55
  'vendor' => 'nullable|exists:vendors,public_id',
56
56
  'job' => 'nullable|exists:orders,public_id',
57
57
  'location' => ['nullable', new ResolvablePoint()],
@@ -0,0 +1,29 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Requests;
4
+
5
+ use Fleetbase\Http\Requests\FleetbaseRequest;
6
+
7
+ /**
8
+ * Validates the body of `POST /v1/customers/request-creation-code`.
9
+ */
10
+ class VerifyCreateCustomerRequest extends FleetbaseRequest
11
+ {
12
+ public function authorize(): bool
13
+ {
14
+ return request()->session()->has('api_credential')
15
+ || request()->session()->has('is_sanctum_token');
16
+ }
17
+
18
+ public function rules(): array
19
+ {
20
+ return [
21
+ 'mode' => 'required|in:email,sms',
22
+ 'identity' => 'required|string',
23
+ // Optional profile context — when provided, used to greet the
24
+ // customer in the verification email and pre-seed the User row.
25
+ 'name' => 'nullable|string|max:255',
26
+ 'phone' => 'nullable|string|max:32',
27
+ ];
28
+ }
29
+ }
@@ -0,0 +1,41 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Resources\Internal\v1;
4
+
5
+ use Fleetbase\Http\Resources\FleetbaseResource;
6
+
7
+ class OrderConfig extends FleetbaseResource
8
+ {
9
+ /**
10
+ * Transform the resource into an array.
11
+ *
12
+ * @param \Illuminate\Http\Request $request
13
+ */
14
+ public function toArray($request): array
15
+ {
16
+ return [
17
+ 'id' => $this->id,
18
+ 'uuid' => $this->uuid,
19
+ 'public_id' => $this->public_id,
20
+ 'company_uuid' => $this->company_uuid,
21
+ 'author_uuid' => $this->author_uuid,
22
+ 'category_uuid' => $this->category_uuid,
23
+ 'icon_uuid' => $this->icon_uuid,
24
+ 'name' => $this->name,
25
+ 'namespace' => $this->namespace,
26
+ 'description' => $this->description,
27
+ 'key' => $this->key,
28
+ 'status' => $this->status,
29
+ 'version' => $this->version,
30
+ 'core_service' => (bool) $this->core_service,
31
+ 'flow' => $this->flow ?? [],
32
+ 'entities' => $this->entities ?? [],
33
+ 'tags' => $this->tags ?? [],
34
+ 'meta' => $this->meta ?? [],
35
+ 'created_at' => $this->created_at,
36
+ 'updated_at' => $this->updated_at,
37
+ 'deleted_at' => $this->deleted_at,
38
+ 'type' => 'order-config',
39
+ ];
40
+ }
41
+ }
@@ -0,0 +1,79 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Resources\v1;
4
+
5
+ use Fleetbase\FleetOps\Models\Order;
6
+ use Fleetbase\FleetOps\Support\Utils;
7
+ use Fleetbase\Http\Resources\FleetbaseResource;
8
+ use Fleetbase\Models\Company;
9
+ use Fleetbase\Support\Http;
10
+ use Illuminate\Http\Request;
11
+ use Illuminate\Support\Str;
12
+
13
+ /**
14
+ * Public API resource for FleetOps customers.
15
+ *
16
+ * Wraps a {@see \Fleetbase\FleetOps\Models\Contact} of `type='customer'` and
17
+ * exposes the auth `token` field that login/signup endpoints attach.
18
+ */
19
+ class Customer extends FleetbaseResource
20
+ {
21
+ public function toArray($request): array
22
+ {
23
+ $this->loadMissing(['place', 'places']);
24
+
25
+ return [
26
+ 'id' => $this->when(Http::isInternalRequest(), $this->id, Str::replaceFirst('contact', 'customer', $this->public_id)),
27
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
28
+ 'user_uuid' => $this->when(Http::isInternalRequest(), $this->user_uuid),
29
+ 'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
30
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
31
+ 'internal_id' => $this->internal_id,
32
+ 'name' => $this->name,
33
+ 'title' => $this->title,
34
+ 'photo_url' => $this->photo_url,
35
+ 'email' => $this->email,
36
+ 'phone' => $this->phone,
37
+ 'address' => data_get($this, 'place.address'),
38
+ 'addresses' => $this->whenLoaded('places', fn () => Place::collection($this->places)),
39
+ 'token' => $this->when($this->token, $this->token),
40
+ 'orders_count' => $this->getOrdersCount($request),
41
+ 'company' => $this->when($this->company_uuid, fn () => $this->buildCompanyPayload()),
42
+ 'meta' => data_get($this, 'meta', Utils::createObject()),
43
+ 'slug' => $this->slug,
44
+ 'created_at' => $this->created_at,
45
+ 'updated_at' => $this->updated_at,
46
+ ];
47
+ }
48
+
49
+ private function getOrdersCount(Request $request): int
50
+ {
51
+ return Order::where('customer_uuid', $this->uuid)
52
+ ->whereNull('deleted_at')
53
+ ->withoutGlobalScopes()
54
+ ->count();
55
+ }
56
+
57
+ /**
58
+ * Public-safe projection of the customer's company. Returns the same
59
+ * fields any caller could fetch through other public endpoints — name,
60
+ * resolved currency, country, phone — plus the company's public id.
61
+ * Currency falls back through company.currency → ledger base_currency
62
+ * → "USD" via {@see Utils::getCompanyTransactionCurrency}.
63
+ */
64
+ private function buildCompanyPayload(): ?array
65
+ {
66
+ $company = Company::find($this->company_uuid);
67
+ if (!$company) {
68
+ return null;
69
+ }
70
+
71
+ return [
72
+ 'id' => $company->public_id,
73
+ 'name' => $company->name,
74
+ 'currency' => Utils::getCompanyTransactionCurrency($company),
75
+ 'country' => $company->country,
76
+ 'phone' => $company->phone,
77
+ ];
78
+ }
79
+ }
@@ -0,0 +1,74 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Resources\v1;
4
+
5
+ use Fleetbase\Http\Resources\FleetbaseResource;
6
+ use Fleetbase\Support\Http;
7
+
8
+ /**
9
+ * Public, read-only projection of an OrderConfig.
10
+ *
11
+ * Exposes the activity `flow` so consumers can render status filter chips,
12
+ * activity labels, and progress UI without learning the internal config
13
+ * schema. Internal-only fields (entities JSON, version, namespace columns
14
+ * that aren't part of the public contract) are filtered out.
15
+ */
16
+ class OrderConfig extends FleetbaseResource
17
+ {
18
+ /**
19
+ * Transform the resource into an array.
20
+ *
21
+ * @param \Illuminate\Http\Request $request
22
+ */
23
+ public function toArray($request): array
24
+ {
25
+ return [
26
+ 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
27
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
28
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
29
+ 'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
30
+ 'key' => $this->key,
31
+ 'name' => $this->name,
32
+ 'namespace' => $this->namespace,
33
+ 'description' => $this->description,
34
+ 'tags' => $this->tags,
35
+ 'status' => $this->status,
36
+ 'version' => $this->version,
37
+ 'flow' => $this->projectFlow(),
38
+ 'created_at' => $this->created_at,
39
+ 'updated_at' => $this->updated_at,
40
+ ];
41
+ }
42
+
43
+ /**
44
+ * Project the flow JSON into an ordered list of activities, keeping only
45
+ * the public-safe per-activity fields. `code` and `status` (the label)
46
+ * are the contract; `complete`, `color`, `details`, `pod_method`, and
47
+ * `require_pod` are useful UI hints that can ride along.
48
+ */
49
+ protected function projectFlow(): array
50
+ {
51
+ $flow = $this->flow;
52
+ if (!is_array($flow) || empty($flow)) {
53
+ return [];
54
+ }
55
+
56
+ $activities = [];
57
+ foreach ($flow as $activity) {
58
+ if (!is_array($activity)) {
59
+ continue;
60
+ }
61
+ $activities[] = [
62
+ 'code' => $activity['code'] ?? ($activity['key'] ?? null),
63
+ 'status' => $activity['status'] ?? null,
64
+ 'details' => $activity['details'] ?? null,
65
+ 'color' => $activity['color'] ?? null,
66
+ 'complete' => (bool) ($activity['complete'] ?? false),
67
+ 'pod_method' => $activity['pod_method'] ?? null,
68
+ 'require_pod' => (bool) ($activity['require_pod'] ?? false),
69
+ ];
70
+ }
71
+
72
+ return $activities;
73
+ }
74
+ }
@@ -22,26 +22,29 @@ class Payload extends FleetbaseResource
22
22
  $withRouteETA = $request->has('with_route_eta');
23
23
 
24
24
  return [
25
- 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
26
- 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
27
- 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
28
- 'current_waypoint_uuid' => $this->when(Http::isInternalRequest(), $this->current_waypoint_uuid),
29
- 'pickup_uuid' => $this->when(Http::isInternalRequest(), $this->pickup_uuid),
30
- 'dropoff_uuid' => $this->when(Http::isInternalRequest(), $this->dropoff_uuid),
31
- 'return_uuid' => $this->when(Http::isInternalRequest(), $this->return_uuid),
32
- 'current_waypoint' => $this->when(Http::isPublicRequest() && $this->currentWaypoint, data_get($this, 'currentWaypoint.public_id')),
33
- 'pickup' => $this->getPlace($this->pickup),
34
- 'dropoff' => $this->getPlace($this->dropoff),
35
- 'return' => new Place($this->return),
36
- 'waypoints' => Waypoint::collection($this->getWaypoints($withRouteETA)),
37
- 'entities' => Entity::collection($this->entities),
38
- 'cod_amount' => $this->cod_amount ?? null,
39
- 'cod_currency' => $this->cod_currency ?? null,
40
- 'cod_payment_method' => $this->cod_payment_method ?? null,
41
- 'payment_method' => $this->payment_method ?? null,
42
- 'meta' => data_get($this, 'meta', Utils::createObject()),
43
- 'updated_at' => $this->updated_at,
44
- 'created_at' => $this->created_at,
25
+ 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
26
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
27
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
28
+ 'current_waypoint_uuid' => $this->when(Http::isInternalRequest(), $this->current_waypoint_uuid),
29
+ 'pickup_uuid' => $this->when(Http::isInternalRequest(), $this->pickup_uuid),
30
+ 'pickup_tracking_number_uuid' => $this->when(Http::isInternalRequest(), $this->pickup_tracking_number_uuid),
31
+ 'dropoff_uuid' => $this->when(Http::isInternalRequest(), $this->dropoff_uuid),
32
+ 'dropoff_tracking_number_uuid' => $this->when(Http::isInternalRequest(), $this->dropoff_tracking_number_uuid),
33
+ 'return_uuid' => $this->when(Http::isInternalRequest(), $this->return_uuid),
34
+ 'return_tracking_number_uuid' => $this->when(Http::isInternalRequest(), $this->return_tracking_number_uuid),
35
+ 'current_waypoint' => $this->when(Http::isPublicRequest() && $this->currentWaypoint, data_get($this, 'currentWaypoint.public_id')),
36
+ 'pickup' => $this->getPlace($this->pickup),
37
+ 'dropoff' => $this->getPlace($this->dropoff),
38
+ 'return' => new Place($this->return),
39
+ 'waypoints' => Waypoint::collection($this->getWaypoints($withRouteETA)),
40
+ 'entities' => Entity::collection($this->entities),
41
+ 'cod_amount' => $this->cod_amount ?? null,
42
+ 'cod_currency' => $this->cod_currency ?? null,
43
+ 'cod_payment_method' => $this->cod_payment_method ?? null,
44
+ 'payment_method' => $this->payment_method ?? null,
45
+ 'meta' => data_get($this, 'meta', Utils::createObject()),
46
+ 'updated_at' => $this->updated_at,
47
+ 'created_at' => $this->created_at,
45
48
  ];
46
49
  }
47
50
 
@@ -17,17 +17,24 @@ class ServiceArea extends FleetbaseResource
17
17
  public function toArray($request)
18
18
  {
19
19
  return $this->withCustomFields([
20
- 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
21
- 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
22
- 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
23
- 'name' => $this->name,
24
- 'type' => $this->type,
25
- 'center' => $this->location,
26
- 'border' => $this->border,
27
- 'zones' => $this->whenLoaded('zones', fn () => Zone::collection($this->zones)),
28
- 'status' => $this->status,
29
- 'updated_at' => $this->updated_at,
30
- 'created_at' => $this->created_at,
20
+ 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
21
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
22
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
23
+ 'name' => $this->name,
24
+ 'type' => $this->type,
25
+ 'center' => $this->location,
26
+ 'border' => $this->border,
27
+ 'zones' => $this->whenLoaded('zones', fn () => Zone::collection($this->zones)),
28
+ 'color' => $this->color,
29
+ 'stroke_color' => $this->stroke_color,
30
+ 'trigger_on_entry' => $this->trigger_on_entry,
31
+ 'trigger_on_exit' => $this->trigger_on_exit,
32
+ 'dwell_threshold_minutes' => $this->dwell_threshold_minutes,
33
+ 'speed_limit_kmh' => $this->speed_limit_kmh,
34
+ 'country' => $this->country,
35
+ 'status' => $this->status,
36
+ 'updated_at' => $this->updated_at,
37
+ 'created_at' => $this->created_at,
31
38
  ]);
32
39
  }
33
40
 
@@ -39,14 +46,21 @@ class ServiceArea extends FleetbaseResource
39
46
  public function toWebhookPayload()
40
47
  {
41
48
  return [
42
- 'id' => $this->public_id,
43
- 'name' => $this->name,
44
- 'type' => $this->type,
45
- 'center' => $this->location,
46
- 'border' => $this->border,
47
- 'status' => $this->status,
48
- 'updated_at' => $this->updated_at,
49
- 'created_at' => $this->created_at,
49
+ 'id' => $this->public_id,
50
+ 'name' => $this->name,
51
+ 'type' => $this->type,
52
+ 'center' => $this->location,
53
+ 'border' => $this->border,
54
+ 'color' => $this->color,
55
+ 'stroke_color' => $this->stroke_color,
56
+ 'trigger_on_entry' => $this->trigger_on_entry,
57
+ 'trigger_on_exit' => $this->trigger_on_exit,
58
+ 'dwell_threshold_minutes' => $this->dwell_threshold_minutes,
59
+ 'speed_limit_kmh' => $this->speed_limit_kmh,
60
+ 'country' => $this->country,
61
+ 'status' => $this->status,
62
+ 'updated_at' => $this->updated_at,
63
+ 'created_at' => $this->created_at,
50
64
  ];
51
65
  }
52
66
  }
@@ -20,6 +20,13 @@ class ServiceRateFee extends FleetbaseResource
20
20
  'id' => $this->when(Http::isInternalRequest(), $this->id),
21
21
  'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
22
22
  'service_rate_uuid' => $this->when(Http::isInternalRequest(), $this->service_rate_uuid),
23
+ 'service_area_uuid' => $this->when(Http::isInternalRequest(), $this->service_area_uuid),
24
+ 'zone_uuid' => $this->when(Http::isInternalRequest(), $this->zone_uuid),
25
+ 'service_area' => $this->whenLoaded('serviceArea', fn () => new ServiceArea($this->serviceArea)),
26
+ 'zone' => $this->whenLoaded('zone', fn () => new Zone($this->zone)),
27
+ 'label' => $this->label,
28
+ 'priority' => $this->priority,
29
+ 'is_fallback' => (bool) $this->is_fallback,
23
30
  'fee' => $this->fee,
24
31
  'currency' => $this->currency,
25
32
  'min' => $this->min,
@@ -69,11 +69,11 @@ class HandleOrderDispatched implements ShouldQueue
69
69
  return;
70
70
  }
71
71
 
72
- $drivers = Driver::where(['status' => 'active', 'online' => 1])
72
+ $drivers = Driver::where(['status' => 'available', 'online' => 1])
73
73
  ->whereHas('company', function ($q) {
74
74
  $q->whereHas('users', function ($q) {
75
75
  $q->whereHas('driver', function ($q) {
76
- $q->where(['status' => 'active', 'online' => 1]);
76
+ $q->where(['status' => 'available', 'online' => 1]);
77
77
  $q->whereNull('deleted_at');
78
78
  });
79
79
  });