@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.
- package/addon/components/customer/create-order-form.hbs +2 -2
- package/addon/components/customer/form.hbs +2 -2
- package/addon/components/customer/order-form.hbs +2 -2
- package/addon/components/customer/orders.hbs +2 -2
- package/addon/components/display-place.hbs +2 -2
- package/addon/components/map/google-live-map.js +6 -2
- package/addon/components/map/leaflet-live-map.hbs +48 -14
- package/addon/components/map/leaflet-live-map.js +184 -20
- package/addon/components/modals/order-change-destination.hbs +46 -0
- package/addon/components/modals/order-change-destination.js +106 -0
- package/addon/components/modals/stop-activity.hbs +28 -0
- package/addon/components/modals/stop-activity.js +52 -0
- package/addon/components/modals/update-order-activity.hbs +45 -3
- package/addon/components/modals/update-order-activity.js +143 -5
- package/addon/components/orchestrator/resource-panel.hbs +0 -10
- package/addon/components/orchestrator/resource-panel.js +2 -4
- package/addon/components/order/activity-list.hbs +2 -2
- package/addon/components/order/activity-timeline.hbs +31 -29
- package/addon/components/order/details/activity.hbs +3 -3
- package/addon/components/order/details/activity.js +11 -0
- package/addon/components/order/details/documents.js +2 -0
- package/addon/components/order/details/purchase-rate.hbs +2 -2
- package/addon/components/order/details/route.hbs +11 -3
- package/addon/components/order/details/route.js +91 -14
- package/addon/components/order/details/tracking.hbs +101 -72
- package/addon/components/order/details/tracking.js +149 -2
- package/addon/components/order/form/details.hbs +3 -3
- package/addon/components/order/form/documents.js +11 -4
- package/addon/components/order/form/route.hbs +108 -104
- package/addon/components/order/form/route.js +37 -1
- package/addon/components/order/form/service-rate.hbs +2 -2
- package/addon/components/order-config-manager/activity-flow.hbs +4 -1
- package/addon/components/order-config-manager/activity-flow.js +178 -12
- package/addon/components/place/address.js +1 -1
- package/addon/components/route-list.hbs +17 -17
- package/addon/components/route-list.js +42 -10
- package/addon/components/service-rate/details.hbs +41 -0
- package/addon/components/service-rate/form.hbs +118 -0
- package/addon/components/service-rate/form.js +55 -0
- package/addon/components/vehicle/form.js +1 -1
- package/addon/components/vehicle/pill.hbs +1 -1
- package/addon/controllers/management/vehicles/index/new.js +1 -1
- package/addon/controllers/operations/orders/index/details.js +4 -4
- package/addon/controllers/operations/orders/index.js +14 -0
- package/addon/helpers/place-address-html.js +2 -2
- package/addon/routes/operations/service-rates/index.js +1 -1
- package/addon/services/geofence.js +163 -19
- package/addon/services/leaflet-contextmenu-manager.js +27 -0
- package/addon/services/vehicle-actions.js +1 -1
- package/addon/styles/fleetops-engine.css +91 -1
- package/addon/utils/fleet-ops-options.js +2 -1
- package/addon/utils/normalize-order-config-flow.js +41 -0
- package/addon/utils/place-address-html.js +3 -2
- package/addon/utils/route-visualization.js +54 -7
- package/app/components/modals/order-change-destination.js +1 -0
- package/app/components/modals/stop-activity.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +3 -3
- package/server/migrations/2026_05_21_000001_add_geographic_rules_to_service_rate_fees_table.php +37 -0
- package/server/migrations/2026_05_25_000001_add_endpoint_tracking_refs_to_payloads_table.php +50 -0
- package/server/migrations/2026_05_27_000001_default_driver_vehicle_statuses_to_available.php +48 -0
- package/server/resources/views/labels/default.php +57 -49
- package/server/resources/views/labels/waypoint-label.php +27 -20
- package/server/seeders/Testing/ConnectivitySeeder.php +1 -0
- package/server/seeders/Testing/FleetSeeder.php +22 -22
- package/server/seeders/Testing/OrdersSeeder.php +6 -22
- package/server/seeders/Testing/VroomOrchestrationSeeder.php +21 -21
- package/server/src/Console/Commands/AuditCustomerUserConflicts.php +75 -0
- package/server/src/Exceptions/CustomerUserConflictException.php +13 -0
- package/server/src/Http/Controllers/Api/v1/ContactController.php +17 -2
- package/server/src/Http/Controllers/Api/v1/CustomerController.php +876 -0
- package/server/src/Http/Controllers/Api/v1/DriverController.php +1 -1
- package/server/src/Http/Controllers/Api/v1/OrderConfigController.php +54 -0
- package/server/src/Http/Controllers/Api/v1/OrderController.php +98 -70
- package/server/src/Http/Controllers/Api/v1/ServiceAreaController.php +2 -2
- package/server/src/Http/Controllers/Api/v1/VehicleController.php +20 -3
- package/server/src/Http/Controllers/Internal/v1/ContactController.php +19 -0
- package/server/src/Http/Controllers/Internal/v1/LiveController.php +101 -66
- package/server/src/Http/Controllers/Internal/v1/OrderController.php +429 -26
- package/server/src/Http/Controllers/Internal/v1/ServiceQuoteController.php +1 -1
- package/server/src/Http/Controllers/Internal/v1/SettingController.php +2 -2
- package/server/src/Http/Controllers/Internal/v1/VehicleController.php +54 -1
- package/server/src/Http/Middleware/AuthenticateCustomerToken.php +34 -0
- package/server/src/Http/Requests/CreateCustomerOrderRequest.php +63 -0
- package/server/src/Http/Requests/CreateCustomerRequest.php +48 -0
- package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
- package/server/src/Http/Requests/CreateVehicleRequest.php +25 -1
- package/server/src/Http/Requests/Internal/CreateDriverRequest.php +1 -1
- package/server/src/Http/Requests/VerifyCreateCustomerRequest.php +29 -0
- package/server/src/Http/Resources/Internal/v1/OrderConfig.php +41 -0
- package/server/src/Http/Resources/v1/Customer.php +79 -0
- package/server/src/Http/Resources/v1/OrderConfig.php +74 -0
- package/server/src/Http/Resources/v1/Payload.php +23 -20
- package/server/src/Http/Resources/v1/ServiceArea.php +33 -19
- package/server/src/Http/Resources/v1/ServiceRateFee.php +7 -0
- package/server/src/Listeners/HandleOrderDispatched.php +2 -2
- package/server/src/Models/Contact.php +92 -15
- package/server/src/Models/Customer.php +64 -0
- package/server/src/Models/Driver.php +12 -3
- package/server/src/Models/Entity.php +2 -2
- package/server/src/Models/Order.php +29 -4
- package/server/src/Models/Payload.php +17 -1
- package/server/src/Models/ServiceRate.php +273 -1
- package/server/src/Models/ServiceRateFee.php +39 -9
- package/server/src/Models/TrackingNumber.php +8 -2
- package/server/src/Models/Vehicle.php +18 -2
- package/server/src/Models/Waypoint.php +2 -2
- package/server/src/Notifications/LateDeparture.php +2 -2
- package/server/src/Notifications/ProlongedStoppage.php +2 -2
- package/server/src/Notifications/RouteDeviation.php +2 -2
- package/server/src/Observers/ContactObserver.php +2 -0
- package/server/src/Observers/ServiceRateObserver.php +6 -6
- package/server/src/Orchestration/Engines/VroomOrchestrationEngine.php +1 -1
- package/server/src/Providers/FleetOpsServiceProvider.php +1 -0
- package/server/src/Support/Analytics/AbstractAnalytics.php +6 -6
- package/server/src/Support/Analytics/FuelEfficiency.php +2 -2
- package/server/src/Support/Analytics/OrdersByStatus.php +1 -1
- package/server/src/Support/Analytics/RevenueTrend.php +0 -1
- package/server/src/Support/Analytics/TopDrivers.php +1 -1
- package/server/src/Support/CustomerAuth.php +98 -0
- package/server/src/Support/LabelPdf.php +52 -0
- package/server/src/Support/Metrics/AbstractMetric.php +4 -4
- package/server/src/Support/ResolvesOrderServiceStops.php +512 -0
- package/server/src/Tracking/TrackingContextBuilder.php +41 -38
- package/server/src/Tracking/TrackingIntelligenceService.php +109 -9
- package/server/src/Tracking/TrackingStop.php +13 -11
- package/server/src/routes.php +43 -9
- package/server/tests/CapacityAllocationEngineTest.php +10 -10
- package/server/tests/CustomerContactIdentitySafetyTest.php +54 -0
- package/server/tests/CustomerEndpointTest.php +199 -0
- package/server/tests/DriverVehicleStatusDefaultTest.php +39 -0
- package/server/tests/LabelPdfRenderingTest.php +23 -0
- package/server/tests/LiveControllerViewportTest.php +60 -0
- package/server/tests/MetricsRegistryTest.php +4 -8
- package/server/tests/OrchestrationPayloadBuilderTest.php +2 -2
- package/server/tests/OrderConfigEndpointTest.php +86 -0
- package/server/tests/OrderFileAttachmentTest.php +20 -0
- package/server/tests/ServiceAreaZoneApiShapeTest.php +34 -0
- package/server/tests/VehicleDriverAssignmentTest.php +18 -0
- package/translations/en-us.yaml +1 -0
- 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' =>
|
|
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'
|
|
26
|
-
'uuid'
|
|
27
|
-
'public_id'
|
|
28
|
-
'current_waypoint_uuid'
|
|
29
|
-
'pickup_uuid'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'
|
|
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'
|
|
21
|
-
'uuid'
|
|
22
|
-
'public_id'
|
|
23
|
-
'name'
|
|
24
|
-
'type'
|
|
25
|
-
'center'
|
|
26
|
-
'border'
|
|
27
|
-
'zones'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
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'
|
|
43
|
-
'name'
|
|
44
|
-
'type'
|
|
45
|
-
'center'
|
|
46
|
-
'border'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
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' => '
|
|
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' => '
|
|
76
|
+
$q->where(['status' => 'available', 'online' => 1]);
|
|
77
77
|
$q->whereNull('deleted_at');
|
|
78
78
|
});
|
|
79
79
|
});
|