Skip to content

Commit 0aaa088

Browse files
authored
Merge pull request #8830 from ProcessMaker/task/FOUR-31219
Change the Processes I Manage saved search from IN PROGRESS to IN PROGRESS AND COMPLETED
2 parents 664bc3f + ca8e8ee commit 0aaa088

3 files changed

Lines changed: 176 additions & 26 deletions

File tree

ProcessMaker/Http/Controllers/Api/TaskController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public function index(Request $request, $getTotal = false, User $user = null)
156156

157157
// Apply process manager filter BEFORE PMQL to avoid conflicts with is_self_service filtering
158158
if ($request->input('processesIManage') === 'true') {
159-
$this->applyProcessManager($query, $user);
159+
$this->applyProcessManager($query, $user, $request);
160160
} else {
161161
$this->applyForCurrentUser($query, $user);
162162
}

ProcessMaker/Traits/TaskControllerIndexMethods.php

Lines changed: 72 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
trait TaskControllerIndexMethods
2121
{
22+
private const SELF_SERVICE_STATUS = 'self service';
23+
2224
private function indexBaseQuery($request)
2325
{
2426
// Parse the includes parameter
@@ -291,6 +293,19 @@ private function applyStatusFilter($query, $request)
291293
}
292294
}
293295

296+
private function requestHasStatusFilter($request): bool
297+
{
298+
if ($request->filled('status') || $request->filled('statusfilter')) {
299+
return true;
300+
}
301+
302+
if ($this->advancedFilterHasStatus($request)) {
303+
return true;
304+
}
305+
306+
return preg_match('/(?:^|[\s(])status\s*(?:=|!=|<>)/i', $request->input('pmql', '')) === 1;
307+
}
308+
294309
private function applyPmql($query, $request, $user)
295310
{
296311
$pmql = $request->input('pmql', '');
@@ -327,7 +342,7 @@ private function advancedFilterHasSelfServiceStatus($request): bool
327342
foreach ($this->getAdvancedFilterArray($request) as $filter) {
328343
$values = (array) ($filter['value'] ?? []);
329344
foreach ($values as $v) {
330-
if (mb_strtolower($v) === 'self service') {
345+
if (mb_strtolower($v) === self::SELF_SERVICE_STATUS) {
331346
return true;
332347
}
333348
}
@@ -384,34 +399,62 @@ private function applyAdvancedFilter($query, $request)
384399
// If processesIManage is active, handle "Self Service" status filter specially
385400
if ($isProcessManager && is_array($filterArray)) {
386401
$hasSelfServiceFilter = false;
387-
$filteredArray = [];
402+
$nonStatusFilters = [];
403+
$statusFilters = [];
388404

389405
foreach ($filterArray as $filter) {
390-
// Check if this is a "Self Service" status filter
391-
if (isset($filter['subject']['type']) &&
392-
$filter['subject']['type'] === 'Status' &&
393-
isset($filter['value']) &&
394-
mb_strtolower($filter['value']) === 'self service') {
395-
$hasSelfServiceFilter = true;
396-
// Don't add this filter to the array - we'll handle it manually
406+
$isStatusFilter = isset($filter['subject']['type']) && $filter['subject']['type'] === 'Status';
407+
if (!$isStatusFilter) {
408+
$nonStatusFilters[] = $filter;
397409
continue;
398410
}
399-
$filteredArray[] = $filter;
411+
412+
$values = is_array($filter['value']) ? $filter['value'] : [$filter['value']];
413+
$hasSelfServiceValue = in_array(
414+
self::SELF_SERVICE_STATUS,
415+
array_map(fn ($value) => is_string($value) ? mb_strtolower($value) : $value, $values),
416+
true
417+
);
418+
419+
if ($hasSelfServiceValue) {
420+
$hasSelfServiceFilter = true;
421+
$values = array_values(array_filter($values, function ($value) {
422+
return !is_string($value) || mb_strtolower($value) !== self::SELF_SERVICE_STATUS;
423+
}));
424+
425+
if (empty($values)) {
426+
continue;
427+
}
428+
429+
$filter['value'] = is_array($filter['value']) ? $values : $values[0];
430+
}
431+
432+
$statusFilters[] = $filter;
400433
}
401434

402-
// Apply the filtered advanced_filter (without Self Service)
403-
if (!empty($filteredArray)) {
404-
Filter::filter($query, $filteredArray);
435+
if (!$hasSelfServiceFilter) {
436+
Filter::filter($query, $filterArray);
437+
438+
return;
405439
}
406440

407-
// Manually apply the Self Service filter for process managers
408-
if ($hasSelfServiceFilter) {
409-
$selfServiceTaskIds = ProcessRequestToken::select(['id'])
410-
->whereIn('process_id', $processManagerIds)
411-
->where('is_self_service', 1)
412-
->whereNull('user_id')
413-
->where('status', 'ACTIVE');
441+
if (!empty($nonStatusFilters)) {
442+
Filter::filter($query, $nonStatusFilters);
443+
}
414444

445+
// Manually apply the Self Service filter for process managers
446+
$selfServiceTaskIds = ProcessRequestToken::select(['id'])
447+
->whereIn('process_id', $processManagerIds)
448+
->where('is_self_service', 1)
449+
->whereNull('user_id')
450+
->where('status', 'ACTIVE');
451+
452+
if (!empty($statusFilters)) {
453+
$query->where(function ($query) use ($statusFilters, $selfServiceTaskIds) {
454+
Filter::filter($query, $statusFilters);
455+
$query->orWhereIn('process_request_tokens.id', $selfServiceTaskIds);
456+
});
457+
} else {
415458
$query->whereIn('process_request_tokens.id', $selfServiceTaskIds);
416459
}
417460
} else {
@@ -453,7 +496,7 @@ private function applyForCurrentUser($query, $user)
453496
});
454497
}
455498

456-
public function applyProcessManager($query, $user)
499+
public function applyProcessManager($query, $user, $request)
457500
{
458501
$ids = Process::select(['id'])
459502
->where(function ($subQuery) use ($user) {
@@ -472,17 +515,21 @@ public function applyProcessManager($query, $user)
472515
return;
473516
}
474517

475-
// Show tasks from processes the user manages that are ACTIVE
518+
// Show tasks from processes the user manages. Default to ACTIVE unless the request
519+
// already has an explicit status filter that will be applied later.
476520
// OR show self-service tasks from those processes
477521
// Store the process IDs in the query so we can use them later to add self-service tasks
478522
// We'll add self-service tasks after PMQL is applied to avoid the is_self_service = 0 filter
479523
$query->getQuery()->processManagerIds = $ids;
480524

481525
// Apply condition for regular tasks from managed processes
482526
// Self-service tasks will be added after PMQL to avoid conflicts
483-
$query->where(function ($query) use ($ids) {
484-
$query->whereIn('process_request_tokens.process_id', $ids)
485-
->where('process_request_tokens.status', 'ACTIVE');
527+
$query->where(function ($query) use ($ids, $request) {
528+
$query->whereIn('process_request_tokens.process_id', $ids);
529+
530+
if (!$this->requestHasStatusFilter($request)) {
531+
$query->where('process_request_tokens.status', 'ACTIVE');
532+
}
486533
});
487534
}
488535

tests/Feature/Api/TasksTest.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,109 @@ public function testAdvancedStatusFilterOverridesPmqlStatus()
870870
$this->assertNotContains($activeTask->id, $returnedIds);
871871
}
872872

873+
public function testProcessManagerAdvancedStatusFilterCanReturnCompletedTasks()
874+
{
875+
$manager = User::factory()->create();
876+
$process = Process::factory()->create([
877+
'properties' => ['manager_id' => $manager->id],
878+
]);
879+
$unmanagedProcess = Process::factory()->create();
880+
$request = ProcessRequest::factory()->create(['process_id' => $process->id]);
881+
882+
$activeTask = ProcessRequestToken::factory()->create([
883+
'status' => 'ACTIVE',
884+
'element_type' => 'task',
885+
'process_id' => $process->id,
886+
'process_request_id' => $request->id,
887+
'is_self_service' => 0,
888+
]);
889+
890+
$completedTask = ProcessRequestToken::factory()->create([
891+
'status' => 'CLOSED',
892+
'element_type' => 'task',
893+
'process_id' => $process->id,
894+
'process_request_id' => $request->id,
895+
'is_self_service' => 0,
896+
]);
897+
898+
$unmanagedCompletedTask = ProcessRequestToken::factory()->create([
899+
'status' => 'CLOSED',
900+
'element_type' => 'task',
901+
'process_id' => $unmanagedProcess->id,
902+
'is_self_service' => 0,
903+
]);
904+
905+
$statusFilter = json_encode([
906+
[
907+
'subject' => ['type' => 'Status'],
908+
'operator' => '=',
909+
'value' => 'Completed',
910+
],
911+
]);
912+
913+
$response = $this->actingAs($manager, 'api')->get(route('api.tasks.index', [
914+
'processesIManage' => 'true',
915+
'advanced_filter' => $statusFilter,
916+
]));
917+
918+
$response->assertStatus(200);
919+
$returnedIds = collect($response->json('data'))->pluck('id')->toArray();
920+
921+
$this->assertContains($completedTask->id, $returnedIds);
922+
$this->assertNotContains($activeTask->id, $returnedIds);
923+
$this->assertNotContains($unmanagedCompletedTask->id, $returnedIds);
924+
}
925+
926+
public function testProcessManagerAdvancedStatusFilterCanReturnInProgressCompletedAndSelfServiceTasks()
927+
{
928+
$manager = User::factory()->create();
929+
$process = Process::factory()->create([
930+
'properties' => ['manager_id' => $manager->id],
931+
]);
932+
933+
$activeTask = ProcessRequestToken::factory()->create([
934+
'status' => 'ACTIVE',
935+
'element_type' => 'task',
936+
'process_id' => $process->id,
937+
'is_self_service' => 0,
938+
]);
939+
940+
$completedTask = ProcessRequestToken::factory()->create([
941+
'status' => 'CLOSED',
942+
'element_type' => 'task',
943+
'process_id' => $process->id,
944+
'is_self_service' => 0,
945+
]);
946+
947+
$selfServiceTask = ProcessRequestToken::factory()->create([
948+
'status' => 'ACTIVE',
949+
'element_type' => 'task',
950+
'process_id' => $process->id,
951+
'user_id' => null,
952+
'is_self_service' => 1,
953+
]);
954+
955+
$statusFilter = json_encode([
956+
[
957+
'subject' => ['type' => 'Status'],
958+
'operator' => '=',
959+
'value' => ['In Progress', 'Completed', 'Self Service'],
960+
],
961+
]);
962+
963+
$response = $this->actingAs($manager, 'api')->get(route('api.tasks.index', [
964+
'processesIManage' => 'true',
965+
'advanced_filter' => $statusFilter,
966+
]));
967+
968+
$response->assertStatus(200);
969+
$returnedIds = collect($response->json('data'))->pluck('id')->toArray();
970+
971+
$this->assertContains($activeTask->id, $returnedIds);
972+
$this->assertContains($completedTask->id, $returnedIds);
973+
$this->assertContains($selfServiceTask->id, $returnedIds);
974+
}
975+
873976
public function testPmqlStatusPreservedWhenNoAdvancedStatusFilter()
874977
{
875978
$user = User::factory()->create(['is_administrator' => true]);

0 commit comments

Comments
 (0)