Skip to content

Commit 55d771c

Browse files
feat: add new get_all_cases endpoint
1 parent 794c160 commit 55d771c

File tree

7 files changed

+370
-1
lines changed

7 files changed

+370
-1
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
<?php
2+
3+
namespace ProcessMaker\Http\Controllers\Api\V1_1;
4+
5+
use Illuminate\Database\Eloquent\Builder;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Http\Response;
8+
use ProcessMaker\Http\Controllers\Controller;
9+
use ProcessMaker\Http\Requests\GetAllCasesRequest;
10+
use ProcessMaker\Http\Resources\V1_1\CaseResource;
11+
use ProcessMaker\Models\CaseStarted;
12+
13+
class CaseController extends Controller
14+
{
15+
protected $defaultFields = [
16+
'case_number',
17+
'user_id',
18+
'case_title',
19+
'case_title_formatted',
20+
'case_status',
21+
'processes',
22+
'requests',
23+
'request_tokens',
24+
'tasks',
25+
'participants',
26+
'initiated_at',
27+
'completed_at',
28+
];
29+
30+
protected $sortableFields = [
31+
'case_number',
32+
'initiated_at',
33+
'completed_at',
34+
];
35+
36+
protected $filterableFields = [
37+
'case_number',
38+
'case_title',
39+
'case_status',
40+
'processes',
41+
'requests',
42+
'request_tokens',
43+
'tasks',
44+
'participants',
45+
'initiated_at',
46+
'completed_at',
47+
];
48+
49+
protected $searchableFields = [
50+
'case_number',
51+
'case_title',
52+
];
53+
54+
protected $dateFields = [
55+
'initiated_at',
56+
'completed_at',
57+
'created_at',
58+
'updated_at',
59+
];
60+
61+
/**
62+
* Get a list of all started cases.
63+
*
64+
* @param Request $request
65+
*
66+
* @queryParam userId int Filter by user ID.
67+
* @queryParam status string Filter by case status.
68+
* @queryParam sortBy string Sort by field:asc,field2:desc,...
69+
* @queryParam filterBy array Filter by field=value&field2=value2&...
70+
* @queryParam search string Search by case number or case title.
71+
* @queryParam pageSize int Number of items per page.
72+
* @queryParam page int Page number.
73+
*
74+
* @return array
75+
*/
76+
public function getAllCases(GetAllCasesRequest $request): array
77+
{
78+
$pageSize = $request->get('pageSize', 15);
79+
80+
$query = CaseStarted::select($this->defaultFields);
81+
82+
$this->filters($request, $query);
83+
84+
$pagination = CaseResource::collection($query->paginate($pageSize));
85+
86+
return [
87+
'data' => $pagination->items(),
88+
'meta' => [
89+
'total' => $pagination->total(),
90+
'perPage' => $pagination->perPage(),
91+
'currentPage' => $pagination->currentPage(),
92+
'lastPage' => $pagination->lastPage(),
93+
],
94+
];
95+
}
96+
97+
/**
98+
* Apply filters to the query.
99+
*
100+
* @param Request $request
101+
* @param Builder $query
102+
*
103+
* @return void
104+
*/
105+
private function filters(Request $request, Builder $query): void
106+
{
107+
if ($request->has('userId')) {
108+
$query->where('user_id', $request->get('userId'));
109+
}
110+
111+
if ($request->has('status')) {
112+
$query->where('case_status', $request->get('status'));
113+
}
114+
115+
$this->search($request, $query);
116+
$this->filterBy($request, $query);
117+
$this->sortBy($request, $query);
118+
}
119+
120+
/**
121+
* Sort the query.
122+
*
123+
* @param Request $request: Query parameter format: sortBy=field:asc,field2:desc,...
124+
* @param Builder $query
125+
*
126+
* @return void
127+
*/
128+
private function sortBy(Request $request, Builder $query): void
129+
{
130+
$sort = explode(',', $request->get('sortBy'));
131+
132+
foreach ($sort as $value) {
133+
if (!preg_match('/^[a-zA-Z_]+:(asc|desc)$/', $value)) {
134+
continue;
135+
}
136+
137+
$sort = explode(':', $value);
138+
$field = $sort[0];
139+
$order = $sort[1] ?? 'asc';
140+
141+
if (in_array($field, $this->sortableFields)) {
142+
$query->orderBy($field, $order);
143+
}
144+
}
145+
}
146+
147+
/**
148+
* Filter the query.
149+
*
150+
* @param Request $request: Query parameter format: filterBy[field]=value&filterBy[field2]=value2&...
151+
* @param Builder $query
152+
* @param array $dateFields List of date fields in current model
153+
*
154+
* @return void
155+
*/
156+
private function filterBy(Request $request, Builder $query): void
157+
{
158+
if ($request->has('filterBy')) {
159+
$filterByValue = $request->get('filterBy');
160+
161+
foreach ($filterByValue as $key => $value) {
162+
if (!in_array($key, $this->filterableFields)) {
163+
continue;
164+
}
165+
166+
if (in_array($key, $this->dateFields)) {
167+
$query->whereDate($key, $value);
168+
continue;
169+
}
170+
171+
$query->where($key, $value);
172+
}
173+
}
174+
}
175+
176+
/**
177+
* Search by case number or case title.
178+
179+
* @param Request $request: Query parameter format: search=keyword
180+
* @param Builder $query
181+
*
182+
* @return void
183+
*/
184+
private function search(Request $request, Builder $query): void
185+
{
186+
if ($request->has('search')) {
187+
$search = $request->get('search');
188+
189+
$query->where(function ($q) use ($search) {
190+
foreach ($this->searchableFields as $field) {
191+
if ($field === 'case_number') {
192+
$q->orWhere($field, 'like', "%$search%");
193+
} else {
194+
$q->orWhereFullText($field, $search . '*', ['mode' => 'boolean']);
195+
}
196+
}
197+
});
198+
}
199+
}
200+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace ProcessMaker\Http\Requests;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class GetAllCasesRequest extends FormRequest
8+
{
9+
/**
10+
* Determine if the user is authorized to make this request.
11+
*/
12+
public function authorize(): bool
13+
{
14+
return true;
15+
}
16+
17+
/**
18+
* Get the validation rules that apply to the request.
19+
*
20+
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
21+
*/
22+
public function rules(): array
23+
{
24+
return [
25+
'userId' => 'sometimes|integer',
26+
'status' => 'sometimes|in:in_progress,completed',
27+
'sortBy' => 'sometimes|string',
28+
'filterBy' => 'sometimes|array',
29+
'search' => 'sometimes|string',
30+
'pageSize' => 'sometimes|integer|min:1',
31+
'page' => 'sometimes|integer|min:1',
32+
];
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace ProcessMaker\Http\Resources\V1_1;
4+
5+
use ProcessMaker\Http\Resources\ApiResource;
6+
7+
class CaseResource extends ApiResource
8+
{
9+
protected static $defaultFields = [
10+
'case_number',
11+
'user_id',
12+
'case_title',
13+
'case_title_formatted',
14+
'case_status',
15+
'processes',
16+
'requests',
17+
'request_tokens',
18+
'tasks',
19+
'participants',
20+
'initiated_at',
21+
'completed_at',
22+
];
23+
24+
public function toArray($request): array
25+
{
26+
$data = [];
27+
28+
foreach (static::$defaultFields as $field) {
29+
$data[$field] = $this->$field;
30+
}
31+
32+
return $data;
33+
}
34+
}

ProcessMaker/Models/CaseStarted.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22

33
namespace ProcessMaker\Models;
44

5+
use Database\Factories\CaseStartedFactory;
6+
use Illuminate\Database\Eloquent\Factories\HasFactory;
57
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
8+
use Illuminate\Database\Eloquent\Factories\Factory;
69
use ProcessMaker\Models\ProcessMakerModel;
710

811
class CaseStarted extends ProcessMakerModel
912
{
13+
use HasFactory;
14+
1015
protected $table = 'cases_started';
1116

1217
protected $fillable = [
@@ -35,6 +40,11 @@ class CaseStarted extends ProcessMakerModel
3540
'completed_at' => 'datetime',
3641
];
3742

43+
protected static function newFactory(): Factory
44+
{
45+
return CaseStartedFactory::new();
46+
}
47+
3848
/**
3949
* Get the user that owns the case.
4050
*/
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
namespace Database\Factories;
4+
5+
use Illuminate\Database\Eloquent\Factories\Factory;
6+
use ProcessMaker\Models\CaseStarted;
7+
8+
/**
9+
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\ProcessMaker\Models\CaseStarted>
10+
*/
11+
class CaseStartedFactory extends Factory
12+
{
13+
protected $model = CaseStarted::class;
14+
15+
/**
16+
* Define the model's default state.
17+
*
18+
* @return array<string, mixed>
19+
*/
20+
public function definition(): array
21+
{
22+
return [
23+
'case_number' => fake()->unique()->randomNumber(),
24+
'user_id' => fake()->randomElement([1, 3]),
25+
'case_title' => fake()->words(3, true),
26+
'case_title_formatted' => fake()->words(3, true),
27+
'case_status' => fake()->randomElement(['in_progress', 'completed']),
28+
'processes' => array_map(function() {
29+
return [
30+
'id' => fake()->randomNumber(),
31+
'name' => fake()->words(2, true),
32+
];
33+
}, range(1, 3)),
34+
'requests' => [
35+
[
36+
'id' => fake()->randomNumber(),
37+
'name' => fake()->words(2, true),
38+
'parent_request' => fake()->randomNumber(),
39+
],
40+
[
41+
'id' => fake()->randomNumber(),
42+
'name' => fake()->words(3, true),
43+
'parent_request' => fake()->randomNumber(),
44+
],
45+
],
46+
'request_tokens' => fake()->randomElement([fake()->randomNumber(), fake()->randomNumber(), fake()->randomNumber()]),
47+
'tasks' => [
48+
[
49+
'id' => fake()->numerify('node_####'),
50+
'name' => fake()->words(4, true),
51+
],
52+
[
53+
'id' => fake()->numerify('node_####'),
54+
'name' => fake()->words(3, true),
55+
],
56+
[
57+
'id' => fake()->numerify('node_####'),
58+
'name' => fake()->words(2, true),
59+
],
60+
],
61+
'participants' => [
62+
[
63+
'id' => fake()->randomNumber(),
64+
'name' => fake()->name(),
65+
],
66+
[
67+
'id' => fake()->randomNumber(),
68+
'name' => fake()->name(),
69+
],
70+
[
71+
'id' => fake()->randomNumber(),
72+
'name' => fake()->name(),
73+
],
74+
],
75+
'initiated_at' => fake()->dateTime(),
76+
'completed_at' => fake()->dateTime(),
77+
'keywords' => '',
78+
];
79+
}
80+
}

database/migrations/2024_09_09_181717_create_cases_started_table.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@ public function up(): void
2828
$table->text('keywords');
2929

3030
$table->foreign('user_id')->references('id')->on('users');
31+
3132
$table->index(['user_id', 'case_status', 'created_at']);
3233
$table->index(['user_id', 'case_status', 'updated_at']);
33-
$table->index(['case_title']);
34+
35+
$table->fullText('case_title');
36+
$table->fullText('keywords');
3437
});
3538
}
3639

0 commit comments

Comments
 (0)