Skip to content

Commit

Permalink
feat: add new get_all_cases endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
devmiguelangel committed Sep 11, 2024
1 parent 794c160 commit 55d771c
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 1 deletion.
200 changes: 200 additions & 0 deletions ProcessMaker/Http/Controllers/Api/V1_1/CaseController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
<?php

namespace ProcessMaker\Http\Controllers\Api\V1_1;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use ProcessMaker\Http\Controllers\Controller;
use ProcessMaker\Http\Requests\GetAllCasesRequest;
use ProcessMaker\Http\Resources\V1_1\CaseResource;
use ProcessMaker\Models\CaseStarted;

class CaseController extends Controller
{
protected $defaultFields = [
'case_number',
'user_id',
'case_title',
'case_title_formatted',
'case_status',
'processes',
'requests',
'request_tokens',
'tasks',
'participants',
'initiated_at',
'completed_at',
];

protected $sortableFields = [
'case_number',
'initiated_at',
'completed_at',
];

protected $filterableFields = [
'case_number',
'case_title',
'case_status',
'processes',
'requests',
'request_tokens',
'tasks',
'participants',
'initiated_at',
'completed_at',
];

protected $searchableFields = [
'case_number',
'case_title',
];

protected $dateFields = [
'initiated_at',
'completed_at',
'created_at',
'updated_at',
];

/**
* Get a list of all started cases.
*
* @param Request $request
*
* @queryParam userId int Filter by user ID.
* @queryParam status string Filter by case status.
* @queryParam sortBy string Sort by field:asc,field2:desc,...
* @queryParam filterBy array Filter by field=value&field2=value2&...
* @queryParam search string Search by case number or case title.
* @queryParam pageSize int Number of items per page.
* @queryParam page int Page number.
*
* @return array
*/
public function getAllCases(GetAllCasesRequest $request): array
{
$pageSize = $request->get('pageSize', 15);

$query = CaseStarted::select($this->defaultFields);

$this->filters($request, $query);

$pagination = CaseResource::collection($query->paginate($pageSize));

return [
'data' => $pagination->items(),
'meta' => [
'total' => $pagination->total(),
'perPage' => $pagination->perPage(),
'currentPage' => $pagination->currentPage(),
'lastPage' => $pagination->lastPage(),
],
];
}

/**
* Apply filters to the query.
*
* @param Request $request
* @param Builder $query
*
* @return void
*/
private function filters(Request $request, Builder $query): void
{
if ($request->has('userId')) {
$query->where('user_id', $request->get('userId'));
}

if ($request->has('status')) {
$query->where('case_status', $request->get('status'));
}

$this->search($request, $query);
$this->filterBy($request, $query);
$this->sortBy($request, $query);
}

/**
* Sort the query.
*
* @param Request $request: Query parameter format: sortBy=field:asc,field2:desc,...
* @param Builder $query
*
* @return void
*/
private function sortBy(Request $request, Builder $query): void
{
$sort = explode(',', $request->get('sortBy'));

foreach ($sort as $value) {
if (!preg_match('/^[a-zA-Z_]+:(asc|desc)$/', $value)) {
continue;
}

$sort = explode(':', $value);
$field = $sort[0];
$order = $sort[1] ?? 'asc';

if (in_array($field, $this->sortableFields)) {
$query->orderBy($field, $order);
}
}
}

/**
* Filter the query.
*
* @param Request $request: Query parameter format: filterBy[field]=value&filterBy[field2]=value2&...
* @param Builder $query
* @param array $dateFields List of date fields in current model
*
* @return void
*/
private function filterBy(Request $request, Builder $query): void
{
if ($request->has('filterBy')) {
$filterByValue = $request->get('filterBy');

foreach ($filterByValue as $key => $value) {
if (!in_array($key, $this->filterableFields)) {
continue;
}

if (in_array($key, $this->dateFields)) {
$query->whereDate($key, $value);
continue;
}

$query->where($key, $value);
}
}
}

/**
* Search by case number or case title.
* @param Request $request: Query parameter format: search=keyword
* @param Builder $query
*
* @return void
*/
private function search(Request $request, Builder $query): void
{
if ($request->has('search')) {
$search = $request->get('search');

$query->where(function ($q) use ($search) {
foreach ($this->searchableFields as $field) {
if ($field === 'case_number') {
$q->orWhere($field, 'like', "%$search%");
} else {
$q->orWhereFullText($field, $search . '*', ['mode' => 'boolean']);
}
}
});
}
}
}
34 changes: 34 additions & 0 deletions ProcessMaker/Http/Requests/GetAllCasesRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace ProcessMaker\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class GetAllCasesRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'userId' => 'sometimes|integer',
'status' => 'sometimes|in:in_progress,completed',
'sortBy' => 'sometimes|string',
'filterBy' => 'sometimes|array',
'search' => 'sometimes|string',
'pageSize' => 'sometimes|integer|min:1',
'page' => 'sometimes|integer|min:1',
];
}
}
34 changes: 34 additions & 0 deletions ProcessMaker/Http/Resources/V1_1/CaseResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace ProcessMaker\Http\Resources\V1_1;

use ProcessMaker\Http\Resources\ApiResource;

class CaseResource extends ApiResource
{
protected static $defaultFields = [
'case_number',
'user_id',
'case_title',
'case_title_formatted',
'case_status',
'processes',
'requests',
'request_tokens',
'tasks',
'participants',
'initiated_at',
'completed_at',
];

public function toArray($request): array
{
$data = [];

foreach (static::$defaultFields as $field) {
$data[$field] = $this->$field;
}

return $data;
}
}
10 changes: 10 additions & 0 deletions ProcessMaker/Models/CaseStarted.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

namespace ProcessMaker\Models;

use Database\Factories\CaseStartedFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Factories\Factory;
use ProcessMaker\Models\ProcessMakerModel;

class CaseStarted extends ProcessMakerModel
{
use HasFactory;

protected $table = 'cases_started';

protected $fillable = [
Expand Down Expand Up @@ -35,6 +40,11 @@ class CaseStarted extends ProcessMakerModel
'completed_at' => 'datetime',
];

protected static function newFactory(): Factory
{
return CaseStartedFactory::new();
}

/**
* Get the user that owns the case.
*/
Expand Down
80 changes: 80 additions & 0 deletions database/factories/CaseStartedFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use ProcessMaker\Models\CaseStarted;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\ProcessMaker\Models\CaseStarted>
*/
class CaseStartedFactory extends Factory
{
protected $model = CaseStarted::class;

/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'case_number' => fake()->unique()->randomNumber(),
'user_id' => fake()->randomElement([1, 3]),
'case_title' => fake()->words(3, true),
'case_title_formatted' => fake()->words(3, true),
'case_status' => fake()->randomElement(['in_progress', 'completed']),
'processes' => array_map(function() {
return [
'id' => fake()->randomNumber(),
'name' => fake()->words(2, true),
];
}, range(1, 3)),
'requests' => [
[
'id' => fake()->randomNumber(),
'name' => fake()->words(2, true),
'parent_request' => fake()->randomNumber(),
],
[
'id' => fake()->randomNumber(),
'name' => fake()->words(3, true),
'parent_request' => fake()->randomNumber(),
],
],
'request_tokens' => fake()->randomElement([fake()->randomNumber(), fake()->randomNumber(), fake()->randomNumber()]),
'tasks' => [
[
'id' => fake()->numerify('node_####'),
'name' => fake()->words(4, true),
],
[
'id' => fake()->numerify('node_####'),
'name' => fake()->words(3, true),
],
[
'id' => fake()->numerify('node_####'),
'name' => fake()->words(2, true),
],
],
'participants' => [
[
'id' => fake()->randomNumber(),
'name' => fake()->name(),
],
[
'id' => fake()->randomNumber(),
'name' => fake()->name(),
],
[
'id' => fake()->randomNumber(),
'name' => fake()->name(),
],
],
'initiated_at' => fake()->dateTime(),
'completed_at' => fake()->dateTime(),
'keywords' => '',
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ public function up(): void
$table->text('keywords');

$table->foreign('user_id')->references('id')->on('users');

$table->index(['user_id', 'case_status', 'created_at']);
$table->index(['user_id', 'case_status', 'updated_at']);
$table->index(['case_title']);

$table->fullText('case_title');
$table->fullText('keywords');
});
}

Expand Down
Loading

0 comments on commit 55d771c

Please sign in to comment.