@fleetbase/fleetops-engine 0.4.17 → 0.4.18

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.
@@ -0,0 +1,34 @@
1
+ <?php
2
+
3
+ use Fleetbase\FleetOps\Models\OrderConfig;
4
+ use Illuminate\Database\Migrations\Migration;
5
+ use Illuminate\Database\Schema\Blueprint;
6
+ use Illuminate\Support\Facades\Schema;
7
+
8
+ return new class() extends Migration {
9
+ /**
10
+ * Run the migrations.
11
+ */
12
+ public function up(): void
13
+ {
14
+ Schema::table('order_configs', function (Blueprint $table) {
15
+ $table->string('public_id')->nullable()->after('uuid')->index();
16
+ });
17
+
18
+ // Update order configs with a public id
19
+ $orderCofigs = OrderConfig::all();
20
+ foreach ($orderCofigs as $orderCofig) {
21
+ $orderCofig->update(['public_id' => OrderConfig::generatePublicId('order_config')]);
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Reverse the migrations.
27
+ */
28
+ public function down(): void
29
+ {
30
+ Schema::table('order_configs', function (Blueprint $table) {
31
+ $table->dropColumn('public_id');
32
+ });
33
+ }
34
+ };
@@ -2,10 +2,9 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Seeders;
4
4
 
5
- use Fleetbase\FleetOps\Models\OrderConfig;
5
+ use Fleetbase\FleetOps\Support\FleetOps;
6
6
  use Fleetbase\Models\Company;
7
7
  use Illuminate\Database\Seeder;
8
- use Illuminate\Support\Str;
9
8
 
10
9
  class OrderConfigSeeder extends Seeder
11
10
  {
@@ -18,134 +17,7 @@ class OrderConfigSeeder extends Seeder
18
17
  {
19
18
  $companies = Company::all();
20
19
  foreach ($companies as $company) {
21
- static::createTransportConfig($company);
20
+ FleetOps::createTransportConfig($company);
22
21
  }
23
22
  }
24
-
25
- /**
26
- * Creates or retrieves an existing transport configuration for a given company.
27
- *
28
- * This method attempts to find a transport configuration (`OrderConfig`) for the specified company.
29
- * If such a configuration exists, it's returned. Otherwise, a new configuration is created with default values,
30
- * such as the company UUID, key, core service flag, status, version, tags, and predefined workflow steps.
31
- * These steps include 'created', 'enroute', 'started', 'completed', and 'dispatched', each with specific attributes.
32
- *
33
- * @param Company $company the company for which the transport configuration is being created or retrieved
34
- *
35
- * @return OrderConfig the transport configuration associated with the specified company
36
- */
37
- public static function createTransportConfig(Company $company): OrderConfig
38
- {
39
- return OrderConfig::firstOrCreate(
40
- [
41
- 'company_uuid' => $company->uuid,
42
- 'key' => 'transport',
43
- 'namespace' => 'system:order-config:transport',
44
- ],
45
- [
46
- 'name' => 'Transport',
47
- 'key' => 'transport',
48
- 'namespace' => 'system:order-config:transport',
49
- 'description' => 'Default order configuration for transport',
50
- 'core_service' => 1,
51
- 'status' => 'private',
52
- 'version' => '0.0.1',
53
- 'tags' => ['transport', 'delivery'],
54
- 'entities' => [],
55
- 'meta' => [],
56
- 'flow' => [
57
- 'created' => [
58
- 'key' => 'created',
59
- 'code' => 'created',
60
- 'color' => '#1f2937',
61
- 'logic' => [],
62
- 'events' => [],
63
- 'status' => 'Order Created',
64
- 'actions' => [],
65
- 'details' => 'New order was created.',
66
- 'options' => [],
67
- 'complete' => false,
68
- 'entities' => [],
69
- 'sequence' => 0,
70
- 'activities' => ['dispatched'],
71
- 'internalId' => Str::uuid(),
72
- 'pod_method' => 'scan',
73
- 'require_pod' => false,
74
- ],
75
- 'enroute' => [
76
- 'key' => 'enroute',
77
- 'code' => 'enroute',
78
- 'color' => '#1f2937',
79
- 'logic' => [],
80
- 'events' => [],
81
- 'status' => 'Driver Enroute',
82
- 'actions' => [],
83
- 'details' => 'Driver is en-route.',
84
- 'options' => [],
85
- 'complete' => false,
86
- 'entities' => [],
87
- 'sequence' => 0,
88
- 'activities' => ['completed'],
89
- 'internalId' => Str::uuid(),
90
- 'pod_method' => 'scan',
91
- 'require_pod' => false,
92
- ],
93
- 'started' => [
94
- 'key' => 'started',
95
- 'code' => 'started',
96
- 'color' => '#1f2937',
97
- 'logic' => [],
98
- 'events' => [],
99
- 'status' => 'Order Started',
100
- 'actions' => [],
101
- 'details' => 'Order has been started',
102
- 'options' => [],
103
- 'complete' => false,
104
- 'entities' => [],
105
- 'sequence' => 0,
106
- 'activities' => ['enroute'],
107
- 'internalId' => Str::uuid(),
108
- 'pod_method' => 'scan',
109
- 'require_pod' => false,
110
- ],
111
- 'completed' => [
112
- 'key' => 'completed',
113
- 'code' => 'completed',
114
- 'color' => '#1f2937',
115
- 'logic' => [],
116
- 'events' => [],
117
- 'status' => 'Order Completed',
118
- 'actions' => [],
119
- 'details' => 'Order has been completed.',
120
- 'options' => [],
121
- 'complete' => true,
122
- 'entities' => [],
123
- 'sequence' => 0,
124
- 'activities' => [],
125
- 'internalId' => Str::uuid(),
126
- 'pod_method' => 'scan',
127
- 'require_pod' => false,
128
- ],
129
- 'dispatched' => [
130
- 'key' => 'dispatched',
131
- 'code' => 'dispatched',
132
- 'color' => '#1f2937',
133
- 'logic' => [],
134
- 'events' => [],
135
- 'status' => 'Order Dispatched',
136
- 'actions' => [],
137
- 'details' => 'Order has been dispatched.',
138
- 'options' => [],
139
- 'complete' => false,
140
- 'entities' => [],
141
- 'sequence' => 0,
142
- 'activities' => ['started'],
143
- 'internalId' => Str::uuid(),
144
- 'pod_method' => 'scan',
145
- 'require_pod' => false,
146
- ],
147
- ],
148
- ]
149
- );
150
- }
151
23
  }
@@ -15,6 +15,7 @@ use Fleetbase\FleetOps\Http\Resources\v1\Proof as ProofResource;
15
15
  use Fleetbase\FleetOps\Models\Driver;
16
16
  use Fleetbase\FleetOps\Models\Entity;
17
17
  use Fleetbase\FleetOps\Models\Order;
18
+ use Fleetbase\FleetOps\Models\OrderConfig;
18
19
  use Fleetbase\FleetOps\Models\Payload;
19
20
  use Fleetbase\FleetOps\Models\Place;
20
21
  use Fleetbase\FleetOps\Models\Proof;
@@ -42,7 +43,17 @@ class OrderController extends Controller
42
43
  public function create(CreateOrderRequest $request)
43
44
  {
44
45
  // get request input
45
- $input = $request->only(['internal_id', 'payload', 'service_quote', 'purchase_rate', 'adhoc', 'adhoc_distance', 'pod_method', 'pod_required', 'scheduled_at', 'type', 'status', 'meta', 'notes']);
46
+ $input = $request->only(['internal_id', 'payload', 'service_quote', 'purchase_rate', 'adhoc', 'adhoc_distance', 'pod_method', 'pod_required', 'scheduled_at', 'status', 'meta', 'notes']);
47
+
48
+ // Get order config
49
+ $orderConfig = OrderConfig::resolveFromIdentifier($request->only(['type', 'order_config']));
50
+ if (!$orderConfig) {
51
+ return response()->apiError('Invalid order `type` or `order_config` provided.');
52
+ }
53
+
54
+ // Set order config to input
55
+ $input['order_config_uuid'] = $orderConfig->uuid;
56
+ $input['type'] = $orderConfig->key;
46
57
 
47
58
  // make sure company is set
48
59
  $input['company_uuid'] = session('company');
@@ -965,9 +976,20 @@ class OrderController extends Controller
965
976
  );
966
977
  }
967
978
 
968
- $activity = $order->config()->nextActivity();
979
+ $activities = $order->config()->nextActivity();
980
+
981
+ // If activity is to complete order add proof of delivery properties if required
982
+ // This is a temporary fix until activity is updated to handle POD on it's own
983
+ $activities = $activities->map(function ($activity) use ($order) {
984
+ if ($activity->completesOrder() && $order->pod_required) {
985
+ $activity->set('require_pod', true);
986
+ $activity->set('pod_method', $order->pod_method);
987
+ }
988
+
989
+ return $activity;
990
+ });
969
991
 
970
- return response()->json($activity);
992
+ return response()->json($activities);
971
993
  }
972
994
 
973
995
  /**
@@ -2,7 +2,12 @@
2
2
 
3
3
  namespace Fleetbase\FleetOps\Http\Controllers\Internal\v1;
4
4
 
5
+ use Fleetbase\Exceptions\FleetbaseRequestValidationException;
5
6
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
7
+ use Fleetbase\FleetOps\Http\Requests\Internal\CreateOrderConfigRequest;
8
+ use Fleetbase\FleetOps\Models\OrderConfig;
9
+ use Illuminate\Http\Request;
10
+ use Illuminate\Support\Facades\Validator;
6
11
 
7
12
  class OrderConfigController extends FleetOpsController
8
13
  {
@@ -12,4 +17,60 @@ class OrderConfigController extends FleetOpsController
12
17
  * @var string
13
18
  */
14
19
  public $resource = 'order-config';
20
+
21
+ /**
22
+ * Creates a record with request payload.
23
+ *
24
+ * @return \Illuminate\Http\Response
25
+ */
26
+ public function createRecord(Request $request)
27
+ {
28
+ // Create validation request
29
+ $createOrderRequest = CreateOrderConfigRequest::createFrom($request);
30
+ $rules = $createOrderRequest->rules();
31
+
32
+ // Manually validate request
33
+ $validator = Validator::make($request->input('orderConfig'), $rules);
34
+ if ($validator->fails()) {
35
+ return $createOrderRequest->responseWithErrors($validator);
36
+ }
37
+
38
+ try {
39
+ $record = $this->model->createRecordFromRequest($request);
40
+
41
+ return ['order_config' => new $this->resource($record)];
42
+ } catch (\Exception $e) {
43
+ return response()->error($e->getMessage());
44
+ } catch (\Illuminate\Database\QueryException $e) {
45
+ return response()->error($e->getMessage());
46
+ } catch (FleetbaseRequestValidationException $e) {
47
+ return response()->error($e->getErrors());
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Delete's an order config.
53
+ *
54
+ * @return \Illuminate\Http\Response
55
+ */
56
+ public function deleteRecord($id, Request $request)
57
+ {
58
+ $orderConfig = OrderConfig::where('uuid', $id)->first();
59
+ if (!$orderConfig) {
60
+ return response()->error('No order config found.');
61
+ }
62
+
63
+ // `core_service` order configs cannot be deleted
64
+ if ($orderConfig->core_service) {
65
+ return response()->error('Core service order config\'s cannot be deleted.');
66
+ }
67
+
68
+ if ($orderConfig) {
69
+ $orderConfig->delete();
70
+
71
+ $this->resource::wrap($this->resourceSingularlName);
72
+
73
+ return new $this->resource($orderConfig);
74
+ }
75
+ }
15
76
  }
@@ -9,6 +9,7 @@ use Fleetbase\FleetOps\Events\OrderStarted;
9
9
  use Fleetbase\FleetOps\Flow\Activity;
10
10
  use Fleetbase\FleetOps\Http\Controllers\FleetOpsController;
11
11
  use Fleetbase\FleetOps\Http\Requests\CancelOrderRequest;
12
+ use Fleetbase\FleetOps\Http\Requests\Internal\CreateOrderRequest;
12
13
  use Fleetbase\FleetOps\Imports\OrdersImport;
13
14
  use Fleetbase\FleetOps\Models\Driver;
14
15
  use Fleetbase\FleetOps\Models\Entity;
@@ -25,6 +26,7 @@ use Fleetbase\Models\File;
25
26
  use Fleetbase\Models\Type;
26
27
  use Illuminate\Http\Request;
27
28
  use Illuminate\Support\Facades\DB;
29
+ use Illuminate\Support\Facades\Validator;
28
30
  use Illuminate\Support\Str;
29
31
  use Maatwebsite\Excel\Facades\Excel;
30
32
 
@@ -44,9 +46,17 @@ class OrderController extends FleetOpsController
44
46
  */
45
47
  public function createRecord(Request $request)
46
48
  {
47
- try {
48
- $this->validateRequest($request);
49
+ // Create validation request
50
+ $createOrderRequest = CreateOrderRequest::createFrom($request);
51
+ $rules = $createOrderRequest->rules();
52
+
53
+ // Manually validate request
54
+ $validator = Validator::make($request->input('order'), $rules);
55
+ if ($validator->fails()) {
56
+ return $createOrderRequest->responseWithErrors($validator);
57
+ }
49
58
 
59
+ try {
50
60
  $record = $this->model->createRecordFromRequest(
51
61
  $request,
52
62
  function ($request, &$input) {
@@ -0,0 +1,40 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Requests\Internal;
4
+
5
+ use Fleetbase\Http\Requests\FleetbaseRequest;
6
+ use Illuminate\Validation\Rule;
7
+
8
+ class CreateOrderConfigRequest extends FleetbaseRequest
9
+ {
10
+ /**
11
+ * Determine if the user is authorized to make this request.
12
+ *
13
+ * @return bool
14
+ */
15
+ public function authorize()
16
+ {
17
+ return request()->session()->has('company');
18
+ }
19
+
20
+ /**
21
+ * Get the validation rules that apply to the request.
22
+ *
23
+ * @return array
24
+ */
25
+ public function rules()
26
+ {
27
+ return [
28
+ 'name' => [
29
+ 'required',
30
+ Rule::unique('order_configs', 'name')
31
+ ->where('company_uuid', request()->session()->get('company'))->whereNull('deleted_at'),
32
+ ],
33
+ 'key' => [
34
+ 'required',
35
+ Rule::unique('order_configs', 'key')
36
+ ->where('company_uuid', request()->session()->get('company'))->whereNull('deleted_at'),
37
+ ],
38
+ ];
39
+ }
40
+ }
@@ -0,0 +1,66 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Requests\Internal;
4
+
5
+ use Fleetbase\Http\Requests\FleetbaseRequest;
6
+ use Fleetbase\Rules\ExistsInAny;
7
+
8
+ class CreateOrderRequest extends FleetbaseRequest
9
+ {
10
+ /**
11
+ * Determine if the user is authorized to make this request.
12
+ *
13
+ * @return bool
14
+ */
15
+ public function authorize()
16
+ {
17
+ return request()->session()->has('company');
18
+ }
19
+
20
+ /**
21
+ * Get the validation rules that apply to the request.
22
+ *
23
+ * @return array
24
+ */
25
+ public function rules()
26
+ {
27
+ $validations = [
28
+ 'order_config_uuid' => 'required',
29
+ // 'adhoc' => 'in:true,false,1,0',
30
+ 'dispatch' => ['nullable', 'boolean'],
31
+ // 'adhoc_distance' => 'numeric',
32
+ 'pod_required' => 'in:true,false,1,0',
33
+ 'pod_method' => 'in:' . config('api.pod_methods'),
34
+ 'scheduled_at' => ['nullable', 'date'],
35
+ 'driver' => 'nullable|exists:drivers,uuid',
36
+ 'service_quote' => 'nullable|exists:service_quotes,uuid',
37
+ 'purchase_rate' => 'nullable|exists:purchase_rates,uuid',
38
+ 'facilitator' => ['nullable', new ExistsInAny(['vendors', 'contacts', 'integrated_vendors'], ['uuid', 'provider'])],
39
+ 'customer' => ['nullable', new ExistsInAny(['vendors', 'contacts'], 'uuid')],
40
+ 'status' => 'nullable|string',
41
+ 'type' => 'string',
42
+ ];
43
+
44
+ if ($this->has('payload')) {
45
+ $validations['payload.entities'] = 'array';
46
+ $validations['payload.waypoints'] = 'array';
47
+
48
+ if ($this->isArray('payload')) {
49
+ $validations['payload'] = 'required';
50
+
51
+ if ($this->missing('payload.waypoints')) {
52
+ $validations['payload.pickup_uuid'] = 'required';
53
+ $validations['payload.dropoff_uuid'] = 'required';
54
+ }
55
+
56
+ if ($this->missing(['payload.pickup', 'payload.dropoff'])) {
57
+ $validations['payload.waypoints'] = 'required|array|min:2';
58
+ }
59
+
60
+ $validations['payload.return_uuid'] = 'nullable';
61
+ }
62
+ }
63
+
64
+ return $validations;
65
+ }
66
+ }
@@ -39,7 +39,7 @@ class Order extends FleetbaseResource
39
39
  'service_quote_uuid' => $this->when(Http::isInternalRequest(), $this->service_quote_uuid),
40
40
  'has_driver_assigned' => $this->when(Http::isInternalRequest(), $this->has_driver_assigned),
41
41
  'is_scheduled' => $this->when(Http::isInternalRequest(), $this->is_scheduled),
42
- 'order_config' => $this->when(Http::isInternalRequest(), $this->whenLoaded('orderConfig', $this->orderConfig)),
42
+ 'order_config' => $this->when(Http::isInternalRequest(), $this->whenLoaded('orderConfig', $this->orderConfig), data_get($this->orderConfig, 'public_id')),
43
43
  'custom_field_values' => $this->when(Http::isInternalRequest(), $this->customFieldValues),
44
44
  'customer' => $this->setCustomerType(Resolve::resourceForMorph($this->customer_type, $this->customer_uuid)),
45
45
  'payload' => new Payload($this->payload),
@@ -5,10 +5,12 @@ namespace Fleetbase\FleetOps\Models;
5
5
  use Fleetbase\Casts\Json;
6
6
  use Fleetbase\FleetOps\Casts\OrderConfigEntities;
7
7
  use Fleetbase\FleetOps\Flow\Activity;
8
+ use Fleetbase\Models\Company;
8
9
  use Fleetbase\Models\Model;
9
10
  use Fleetbase\Support\Auth;
10
11
  use Fleetbase\Traits\HasApiModelBehavior;
11
12
  use Fleetbase\Traits\HasMetaAttributes;
13
+ use Fleetbase\Traits\HasPublicId;
12
14
  use Fleetbase\Traits\HasUuid;
13
15
  use Fleetbase\Traits\Searchable;
14
16
  use Illuminate\Support\Collection;
@@ -17,6 +19,7 @@ use Illuminate\Support\Str;
17
19
  class OrderConfig extends Model
18
20
  {
19
21
  use HasUuid;
22
+ use HasPublicId;
20
23
  use Searchable;
21
24
  use HasMetaAttributes;
22
25
  use HasApiModelBehavior;
@@ -28,6 +31,13 @@ class OrderConfig extends Model
28
31
  */
29
32
  protected $table = 'order_configs';
30
33
 
34
+ /**
35
+ * The type of public Id to generate.
36
+ *
37
+ * @var string
38
+ */
39
+ protected $publicIdType = 'order_config';
40
+
31
41
  /**
32
42
  * These attributes that can be queried.
33
43
  *
@@ -41,6 +51,7 @@ class OrderConfig extends Model
41
51
  * @var array
42
52
  */
43
53
  protected $fillable = [
54
+ 'public_id',
44
55
  'company_uuid',
45
56
  'author_uuid',
46
57
  'category_uuid',
@@ -416,4 +427,41 @@ class OrderConfig extends Model
416
427
  'complete' => false,
417
428
  ], $this->flow);
418
429
  }
430
+
431
+ /**
432
+ * Resolves an OrderConfig from a given identifier or an array of identifiers within an optional company context.
433
+ *
434
+ * @param string|array $orderConfigIdentifier the identifier(s) for the OrderConfig (namespace, public_id, or key)
435
+ * @param Company|null $company the company context, if any, to narrow down the search
436
+ *
437
+ * @return OrderConfig|null the found OrderConfig or null if none found
438
+ */
439
+ public static function resolveFromIdentifier($orderConfigIdentifier, ?Company $company = null): ?OrderConfig
440
+ {
441
+ $query = static::query();
442
+
443
+ if ($company instanceof Company) {
444
+ $query->where('company_uuid', $company->uuid);
445
+ } else {
446
+ $companyUuid = session('company');
447
+ if ($companyUuid) {
448
+ $query->where('company_uuid', $companyUuid);
449
+ }
450
+ }
451
+
452
+ $identifiers = is_array($orderConfigIdentifier) ? $orderConfigIdentifier : [$orderConfigIdentifier];
453
+ foreach ($identifiers as $identifier) {
454
+ $orderConfig = $query->where(function ($query) use ($identifier) {
455
+ $query->where('namespace', $identifier)
456
+ ->orWhere('public_id', $identifier)
457
+ ->orWhere('key', $identifier);
458
+ })->first();
459
+
460
+ if ($orderConfig) {
461
+ return $orderConfig;
462
+ }
463
+ }
464
+
465
+ return null;
466
+ }
419
467
  }
@@ -0,0 +1,20 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Observers;
4
+
5
+ use Fleetbase\FleetOps\Support\FleetOps;
6
+ use Fleetbase\Models\Company;
7
+
8
+ class CompanyObserver
9
+ {
10
+ /**
11
+ * Handle the Company "created" event.
12
+ *
13
+ * @return void
14
+ */
15
+ public function created(Company $company)
16
+ {
17
+ // Add the default transport order config
18
+ FleetOps::createTransportConfig($company);
19
+ }
20
+ }
@@ -34,6 +34,7 @@ class FleetOpsServiceProvider extends CoreServiceProvider
34
34
  \Fleetbase\FleetOps\Models\Vehicle::class => \Fleetbase\FleetOps\Observers\VehicleObserver::class,
35
35
  \Fleetbase\FleetOps\Models\Fleet::class => \Fleetbase\FleetOps\Observers\FleetObserver::class,
36
36
  \Fleetbase\Models\User::class => \Fleetbase\FleetOps\Observers\UserObserver::class,
37
+ \Fleetbase\Models\Company::class => \Fleetbase\FleetOps\Observers\CompanyObserver::class,
37
38
  ];
38
39
 
39
40
  /**