From 3ca2e300710010575994a6125c46a714deb2b712 Mon Sep 17 00:00:00 2001 From: paulis Date: Wed, 25 Sep 2024 22:06:00 -0400 Subject: [PATCH 1/3] FOUR-18135 --- .../Http/Controllers/Api/TaskController.php | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/TaskController.php b/ProcessMaker/Http/Controllers/Api/TaskController.php index 99ca6acea9..adccc6eb5c 100644 --- a/ProcessMaker/Http/Controllers/Api/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/TaskController.php @@ -170,11 +170,19 @@ 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,INACTIVE', + 'per_page' => 'nullable|integer', + 'order_by' => 'nullable|string|in:id,element_name,due_at,user.lastname,process.name', + 'order_direction' => 'nullable|string|in:asc,desc', ]); $caseNumber = $request->input('case_number'); + $status = $request->input('status', 'ACTIVE'); // Default status to ACTIVE + $perPage = $request->input('per_page', 10); // Default items per page + $orderBy = $request->input('order_by', 'due_at'); + $orderDirection = $request->input('order_direction', 'asc'); // Default order direction to 'asc' // Get only the columns defined $query = ProcessRequestToken::select($this->defaultCase); @@ -182,8 +190,8 @@ public function indexCase(Request $request, User $user = null) $query->whereHas('processRequest', function ($query) use ($caseNumber) { $query->where('case_number', $caseNumber); }); - // Filter the status - $query->where('status', 'ACTIVE'); + // Filter by status + $query->where('status', $status); // Return the process information $query->with(['process' => function ($query) { $query->select('id', 'name'); @@ -194,8 +202,12 @@ public function indexCase(Request $request, User $user = null) }]); // Filter only the task related to the user $this->applyForCurrentUser($query, $user); + + // Apply ordering only if a valid order_by field is provided + $query->orderBy($orderBy, $orderDirection); + try { - $response = $query->paginate($request->input('per_page', 10)); + $response = $query->paginate($perPage); $response->inOverdue = 0; } catch (QueryException $e) { return $this->handleQueryException($e); From ddfc31df8d5f8c4df3123b152e065bf2a32c526f Mon Sep 17 00:00:00 2001 From: Paula Quispe Date: Thu, 26 Sep 2024 15:12:35 -0400 Subject: [PATCH 2/3] Improve the scopes --- .../Http/Controllers/Api/TaskController.php | 27 +++----- ProcessMaker/Models/ProcessRequestToken.php | 64 +++++++++++++++++++ tests/Feature/Api/TaskControllerTest.php | 23 +++++-- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/TaskController.php b/ProcessMaker/Http/Controllers/Api/TaskController.php index adccc6eb5c..4bc77843cc 100644 --- a/ProcessMaker/Http/Controllers/Api/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/TaskController.php @@ -174,40 +174,29 @@ public function indexCase(Request $request, User $user = null) $request->validate([ 'case_number' => 'required|integer', 'status' => 'nullable|string|in:ACTIVE,INACTIVE', - 'per_page' => 'nullable|integer', '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'); - $status = $request->input('status', 'ACTIVE'); // Default status to ACTIVE - $perPage = $request->input('per_page', 10); // Default items per page - $orderBy = $request->input('order_by', 'due_at'); - $orderDirection = $request->input('order_direction', 'asc'); // Default order direction to 'asc' // 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); - }); + $query->filterByCaseNumber($request); // Filter by status - $query->where('status', $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); - // Apply ordering only if a valid order_by field is provided - $query->orderBy($orderBy, $orderDirection); + $query->applyOrdering($request); try { - $response = $query->paginate($perPage); + $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..6290c6c9c0 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. * @@ -47,20 +56,22 @@ public function test_index_case_returns_tasks_for_case_number() 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'); + $response = $this->apiCall('GET', self::API_TASK_BY_CASE . "?case_number=$processRequest->case_number"); // 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', + ]); } } From a755c6aadbc83f514a1976ea754091a4219b7065 Mon Sep 17 00:00:00 2001 From: Paula Quispe Date: Thu, 26 Sep 2024 21:27:05 -0400 Subject: [PATCH 3/3] adding more test --- .../Http/Controllers/Api/TaskController.php | 4 +- tests/Feature/Api/TaskControllerTest.php | 39 +++++++++++++++++-- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/TaskController.php b/ProcessMaker/Http/Controllers/Api/TaskController.php index 4bc77843cc..929f3da72d 100644 --- a/ProcessMaker/Http/Controllers/Api/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/TaskController.php @@ -173,7 +173,7 @@ public function indexCase(Request $request, User $user = null) // Validate the inputs, including optional ones $request->validate([ 'case_number' => 'required|integer', - 'status' => 'nullable|string|in:ACTIVE,INACTIVE', + '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', @@ -192,6 +192,8 @@ public function indexCase(Request $request, User $user = null) $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); diff --git a/tests/Feature/Api/TaskControllerTest.php b/tests/Feature/Api/TaskControllerTest.php index 6290c6c9c0..ead180bc0d 100644 --- a/tests/Feature/Api/TaskControllerTest.php +++ b/tests/Feature/Api/TaskControllerTest.php @@ -45,11 +45,11 @@ 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(); @@ -64,7 +64,40 @@ public function test_index_case_returns_tasks_for_case_number() ]); // Call the endpoint with the 'case_number' parameter - $response = $this->apiCall('GET', self::API_TASK_BY_CASE . "?case_number=$processRequest->case_number"); + $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);