diff --git a/ProcessMaker/Http/Controllers/Api/TaskController.php b/ProcessMaker/Http/Controllers/Api/TaskController.php index 99ca6acea9..929f3da72d 100644 --- a/ProcessMaker/Http/Controllers/Api/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/TaskController.php @@ -170,32 +170,35 @@ public function indexCase(Request $request, User $user = null) $user = Auth::user(); } - // Review the 'case_number' + // Validate the inputs, including optional ones $request->validate([ 'case_number' => 'required|integer', + 'status' => 'nullable|string|in:ACTIVE,COMPLETED', + 'order_by' => 'nullable|string|in:id,element_name,due_at,user.lastname,process.name', + 'order_direction' => 'nullable|string|in:asc,desc', + 'page' => 'nullable|integer|min:1', + 'per_page' => 'nullable|integer', ]); - $caseNumber = $request->input('case_number'); // Get only the columns defined $query = ProcessRequestToken::select($this->defaultCase); // Filter by case_number - $query->whereHas('processRequest', function ($query) use ($caseNumber) { - $query->where('case_number', $caseNumber); - }); - // Filter the status - $query->where('status', 'ACTIVE'); + $query->filterByCaseNumber($request); + // Filter by status + $query->filterByStatus($request); // Return the process information - $query->with(['process' => function ($query) { - $query->select('id', 'name'); - }]); + $query->getProcess(); // Return the user information - $query->with(['user' => function ($query) { - $query->select('id', 'firstname', 'lastname', 'username', 'avatar'); - }]); + $query->getUser(); // Filter only the task related to the user $this->applyForCurrentUser($query, $user); + // Exclude non visible task + $this->excludeNonVisibleTasks($query, $request); + // Apply ordering only if a valid order_by field is provided + $query->applyOrdering($request); + try { - $response = $query->paginate($request->input('per_page', 10)); + $response = $query->applyPagination($request); $response->inOverdue = 0; } catch (QueryException $e) { return $this->handleQueryException($e); diff --git a/ProcessMaker/Models/ProcessRequestToken.php b/ProcessMaker/Models/ProcessRequestToken.php index 1b88fe7ca6..0a0b8c32c3 100644 --- a/ProcessMaker/Models/ProcessRequestToken.php +++ b/ProcessMaker/Models/ProcessRequestToken.php @@ -288,6 +288,70 @@ public function assignableUsers() return new TokenAssignableUsers($query, $this); } + /** + * Scope to filter by case_number through the processRequest relationship + */ + public function scopeFilterByCaseNumber($query, $request) + { + $caseNumber = $request->input('case_number'); + + return $query->whereHas('processRequest', function ($query) use ($caseNumber) { + $query->where('case_number', $caseNumber); + }); + } + + /** + * Scope to filter by status + */ + public function scopeFilterByStatus($query, $request) + { + $status = $request->input('status', 'ACTIVE'); + + return $query->where('status', $status); + } + + /** + * Scope get process information + */ + public function scopeGetProcess($query) + { + return $query->with(['process' => function ($query) { + $query->select('id', 'name'); + }]); + } + + /** + * Scope get user information + */ + public function scopeGetUser($query) + { + return $query->with(['user' => function ($query) { + $query->select('id', 'firstname', 'lastname', 'username', 'avatar'); + }]); + } + + /** + * Scope apply order + */ + public function scopeApplyOrdering($query, $request) + { + $orderBy = $request->input('order_by', 'due_at'); + $orderDirection = $request->input('order_direction', 'asc'); + + return $query->orderBy($orderBy, $orderDirection); + } + + /** + * Scope apply pagination + */ + public function scopeApplyPagination($query, $request) + { + $page = $request->input('page', 1); + $perPage = $request->input('per_page', 10); + + return $query->paginate($perPage); + } + /** * Returns either the owner element or its properties * diff --git a/tests/Feature/Api/TaskControllerTest.php b/tests/Feature/Api/TaskControllerTest.php index 5022b999a8..ead180bc0d 100644 --- a/tests/Feature/Api/TaskControllerTest.php +++ b/tests/Feature/Api/TaskControllerTest.php @@ -16,6 +16,15 @@ class TaskControllerTest extends TestCase const API_TASK_BY_CASE = '/tasks-by-case'; + const TASK_BY_CASE_STRUCTURE = [ + 'id', + 'element_name', + 'user_id', + 'process_id', + 'due_at', + 'process_request_id', + ]; + /** * Test indexCase without case_number. * @@ -36,31 +45,66 @@ public function test_index_case_requires_case_number() } /** - * Test indexCase returns tasks related to the case_number. + * Test indexCase returns active tasks related to the case_number. * * @return void */ - public function test_index_case_returns_tasks_for_case_number() + public function test_index_case_returns_active_tasks_for_case_number() { // Simulate an authenticated user $user = User::factory()->create(); Auth::login($user); // Create a ProcessRequestToken associated with a specific case_number - $processRequest = ProcessRequest::factory()->create([ - 'case_number' => 81, - ]); - $processRequestToken = ProcessRequestToken::factory()->create([ + $processRequest = ProcessRequest::factory()->create(); + ProcessRequestToken::factory()->create([ 'user_id' => $user->id, 'status' => 'ACTIVE', 'process_request_id' => $processRequest->id, // id del ProcessRequest ]); // Call the endpoint with the 'case_number' parameter - $response = $this->apiCall('GET', self::API_TASK_BY_CASE . '?case_number=81'); + $filter = "?case_number=$processRequest->case_number"; + $response = $this->apiCall('GET', self::API_TASK_BY_CASE . $filter); + + // Check if the response is successful and contains the expected tasks + $response->assertStatus(200); + $this->assertCount(1, $response->json('data')); + $response->assertJsonStructure([ + 'data' => ['*' => self::TASK_BY_CASE_STRUCTURE], + 'meta', + ]); + } + + /** + * Test indexCase returns completed tasks related to the case_number. + * + * @return void + */ + public function test_index_case_returns_inactive_tasks_for_case_number() + { + // Simulate an authenticated user + $user = User::factory()->create(); + Auth::login($user); + + // Create a ProcessRequestToken associated with a specific case_number + $processRequest = ProcessRequest::factory()->create(); + ProcessRequestToken::factory()->create([ + 'user_id' => $user->id, + 'status' => 'COMPLETED', + 'process_request_id' => $processRequest->id, // id del ProcessRequest + ]); + + // Call the endpoint with the 'case_number' parameter + $filter = "?case_number=$processRequest->case_number&status=COMPLETED"; + $response = $this->apiCall('GET', self::API_TASK_BY_CASE . $filter); // Check if the response is successful and contains the expected tasks $response->assertStatus(200); - $this->assertCount(0, $response->json('data')); + $this->assertCount(1, $response->json('data')); + $response->assertJsonStructure([ + 'data' => ['*' => self::TASK_BY_CASE_STRUCTURE], + 'meta', + ]); } }