From 998673066575407a07cca382d835932d22f32106 Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Tue, 24 Feb 2026 09:21:58 -0400 Subject: [PATCH 1/7] Enhance TaskController validation to support multiple statuses and improve filtering logic in TaskControllerIndexMethods. Update CompletedForms component to reflect new status handling. --- .../Http/Controllers/Api/TaskController.php | 20 ++++++++++++++++++- .../Traits/TaskControllerIndexMethods.php | 11 +++++++--- .../casesDetail/components/CompletedForms.vue | 2 +- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/TaskController.php b/ProcessMaker/Http/Controllers/Api/TaskController.php index af2948abf8..35776a3bc4 100644 --- a/ProcessMaker/Http/Controllers/Api/TaskController.php +++ b/ProcessMaker/Http/Controllers/Api/TaskController.php @@ -208,9 +208,27 @@ public function getTasksByCase(Request $request, User $user = null) } // Validate the inputs, including optional ones + $allowedStatuses = ['ACTIVE', 'CLOSED', 'TRIGGERED']; $request->validate([ 'case_number' => 'required|integer', - 'status' => 'nullable|string|in:ACTIVE,CLOSED', + 'status' => [ + 'nullable', + 'string', + function ($attribute, $value, $fail) use ($allowedStatuses) { + $statuses = array_map(fn ($v) => mb_strtoupper(trim($v)), explode(',', $value)); + $statuses = array_filter($statuses); + foreach ($statuses as $status) { + if (!in_array($status, $allowedStatuses)) { + $fail(__('The :attribute must contain only valid statuses: :values. Multiple statuses can be comma-separated.', [ + 'attribute' => $attribute, + 'values' => implode(', ', $allowedStatuses), + ])); + + return; + } + } + }, + ], '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', diff --git a/ProcessMaker/Traits/TaskControllerIndexMethods.php b/ProcessMaker/Traits/TaskControllerIndexMethods.php index be27fa8804..9d6cc9602c 100644 --- a/ProcessMaker/Traits/TaskControllerIndexMethods.php +++ b/ProcessMaker/Traits/TaskControllerIndexMethods.php @@ -135,8 +135,12 @@ private function applyProcessRequestIdFilter($query, $column, $filterByFields, $ private function applyDefaultFiltering($query, $column, $filterByFields, $fieldFilter) { $key = array_search($column, $filterByFields); - $operator = is_numeric($fieldFilter) ? '=' : 'like'; - $query->where(is_string($key) ? $key : $column, $operator, $fieldFilter); + if (str_contains($fieldFilter, ',')) { + $query->whereIn(is_string($key) ? $key : $column, explode(',', $fieldFilter)); + } else { + $operator = is_numeric($fieldFilter) ? '=' : 'like'; + $query->where(is_string($key) ? $key : $column, $operator, $fieldFilter); + } } private function addTaskData($response) @@ -158,7 +162,8 @@ private function excludeNonVisibleTasks($query, $request) $hitlEnabled = filter_var(config('smart-extract.hitl_enabled'), FILTER_VALIDATE_BOOLEAN); $query->when(!$allTasks, function ($query) { $query->where(function ($query) { - $query->where('element_type', '=', 'task'); + $query->orWhere('element_type', '=', 'task'); + $query->orWhere('element_type', '=', 'startEvent'); $query->orWhere(function ($query) { $query->where('element_type', '=', 'serviceTask'); $query->where('element_name', '=', 'AI Assistant'); diff --git a/resources/jscomposition/cases/casesDetail/components/CompletedForms.vue b/resources/jscomposition/cases/casesDetail/components/CompletedForms.vue index ce222a3a22..dd0422e804 100644 --- a/resources/jscomposition/cases/casesDetail/components/CompletedForms.vue +++ b/resources/jscomposition/cases/casesDetail/components/CompletedForms.vue @@ -76,7 +76,7 @@ const getData = async () => { const response = await getDataTask({ params: { case_number: getCaseNumber(), - status: "CLOSED", + status: "CLOSED,TRIGGERED", includeScreen: 1, order_by: filter.value?.field, order_direction: filter.value?.filter, From eaf5f6d78db91e5cb69e42a280f093774926646b Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Tue, 24 Feb 2026 10:12:54 -0400 Subject: [PATCH 2/7] Refactor ProcessRequestToken to support multiple statuses in filtering and enhance getScreen method for improved screen retrieval logic. Update ProcessRequestController to handle new screen data structure. --- .../Api/ProcessRequestController.php | 27 ++++++++++++------- ProcessMaker/Models/ProcessRequestToken.php | 20 +++++++++++--- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php index 6508bba81b..56e14e6ceb 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php @@ -31,6 +31,7 @@ use ProcessMaker\Models\Comment; use ProcessMaker\Models\ProcessRequest; use ProcessMaker\Models\ProcessRequestToken; +use ProcessMaker\Models\Screen; use ProcessMaker\Models\User; use ProcessMaker\Nayra\Contracts\Bpmn\CatchEventInterface; use ProcessMaker\Notifications\ProcessCanceledNotification; @@ -779,8 +780,8 @@ public function screenRequested(Request $httpRequest, ProcessRequest $request) $query = ProcessRequestToken::query(); $query->select('id', 'element_id', 'process_id', 'process_request_id', 'data') ->where('process_request_id', $request->id) - ->whereNotIn('element_type', ['startEvent', 'end_event', 'scriptTask']) - ->where('status', 'CLOSED') + ->whereNotIn('element_type', ['end_event', 'scriptTask']) + ->whereIn('status', ['CLOSED', 'TRIGGERED']) ->orderBy('completed_at'); $response = @@ -792,18 +793,26 @@ public function screenRequested(Request $httpRequest, ProcessRequest $request) $collection = $response->getCollection() ->transform(function ($token): ?object { $definition = $token->getDefinition(); + $screen = null; if (array_key_exists('screenRef', $definition)) { $screen = $token->getScreenVersion(); - if ($screen) { - $dataManager = new DataManager(); - $screen->data = $dataManager->getData($token, true); - $screen->screen_id = $screen->id; - $screen->id = $token->id; - - return $screen; + } else { + $config = json_decode($definition['config']); + // verify the object config has a web_entry property + if (isset($config->web_entry)) { + $screen = Screen::find($config->web_entry->screen_id); } } + if ($screen) { + $dataManager = new DataManager(); + $screen->data = $dataManager->getData($token, true); + $screen->screen_id = $screen->id; + $screen->id = $token->id; + + return $screen; + } + return null; }) ->reject(fn ($item) => $item === null) diff --git a/ProcessMaker/Models/ProcessRequestToken.php b/ProcessMaker/Models/ProcessRequestToken.php index 68de753276..faf772f424 100644 --- a/ProcessMaker/Models/ProcessRequestToken.php +++ b/ProcessMaker/Models/ProcessRequestToken.php @@ -312,13 +312,20 @@ public function scopeFilterByCaseNumber($query, $request) } /** - * Scope to filter by status + * Scope to filter by status. + * Supports single value (e.g. ACTIVE) or comma-separated values (e.g. CLOSED,TRIGGERED). */ public function scopeFilterByStatus($query, $request) { $status = $request->input('status', 'ACTIVE'); + $statuses = array_map(fn ($v) => mb_strtoupper(trim($v)), explode(',', $status)); + $statuses = array_filter($statuses); - return $query->where('status', $status); + if (count($statuses) === 1) { + return $query->where('status', $statuses[0]); + } + + return $query->whereIn('status', $statuses); } /** @@ -441,7 +448,14 @@ public function getBpmnDefinition() public function getScreen(): ?Screen { $definition = $this->getDefinition(); - $screenRef = $definition['screenRef'] ?? null; + + $config = json_decode($definition['config']); + if (isset($config) and isset($config->web_entry)) { + $screenRef = $config->web_entry->screen_id ?? null; + } else { + $screenRef = $definition['screenRef'] ?? null; + } + $screen = Screen::find($screenRef); if ($screen === null) { From 0018fc1648348f9d09a4af1d0d39349090803767 Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Tue, 24 Feb 2026 15:53:32 -0400 Subject: [PATCH 3/7] fix test --- ProcessMaker/Models/ProcessRequestToken.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ProcessMaker/Models/ProcessRequestToken.php b/ProcessMaker/Models/ProcessRequestToken.php index faf772f424..41ddb61ab4 100644 --- a/ProcessMaker/Models/ProcessRequestToken.php +++ b/ProcessMaker/Models/ProcessRequestToken.php @@ -448,8 +448,10 @@ public function getBpmnDefinition() public function getScreen(): ?Screen { $definition = $this->getDefinition(); - - $config = json_decode($definition['config']); + $config = null; + if (isset($definition['config'])) { + $config = json_decode($definition['config']); + } if (isset($config) and isset($config->web_entry)) { $screenRef = $config->web_entry->screen_id ?? null; } else { From 9250ca13004491cfce9bfd028a1400211954779c Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Wed, 25 Feb 2026 10:51:00 -0400 Subject: [PATCH 4/7] Fix test with parameter config --- .../Controllers/Api/ProcessRequestController.php | 16 ++-------------- .../Traits/TaskControllerIndexMethods.php | 13 +++++++++---- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php index 56e14e6ceb..e008c8e07f 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php @@ -792,28 +792,16 @@ public function screenRequested(Request $httpRequest, ProcessRequest $request) $collection = $response->getCollection() ->transform(function ($token): ?object { - $definition = $token->getDefinition(); - $screen = null; - if (array_key_exists('screenRef', $definition)) { - $screen = $token->getScreenVersion(); - } else { - $config = json_decode($definition['config']); - // verify the object config has a web_entry property - if (isset($config->web_entry)) { - $screen = Screen::find($config->web_entry->screen_id); - } - } + $screen = $token->getScreenVersion() ?? null; if ($screen) { $dataManager = new DataManager(); $screen->data = $dataManager->getData($token, true); $screen->screen_id = $screen->id; $screen->id = $token->id; - - return $screen; } - return null; + return $screen; }) ->reject(fn ($item) => $item === null) ->values(); diff --git a/ProcessMaker/Traits/TaskControllerIndexMethods.php b/ProcessMaker/Traits/TaskControllerIndexMethods.php index 9d6cc9602c..5147a621e4 100644 --- a/ProcessMaker/Traits/TaskControllerIndexMethods.php +++ b/ProcessMaker/Traits/TaskControllerIndexMethods.php @@ -160,10 +160,15 @@ private function excludeNonVisibleTasks($query, $request) $nonSystem = filter_var($request->input('non_system'), FILTER_VALIDATE_BOOLEAN); $allTasks = filter_var($request->input('all_tasks'), FILTER_VALIDATE_BOOLEAN); $hitlEnabled = filter_var(config('smart-extract.hitl_enabled'), FILTER_VALIDATE_BOOLEAN); - $query->when(!$allTasks, function ($query) { - $query->where(function ($query) { - $query->orWhere('element_type', '=', 'task'); - $query->orWhere('element_type', '=', 'startEvent'); + $includeScreen = filter_var($request->input('includeScreen'), FILTER_VALIDATE_BOOLEAN); + $query->when(!$allTasks, function ($query) use ($includeScreen) { + $query->where(function ($query) use ($includeScreen) { + if ($includeScreen) { + $query->orWhere('element_type', '=', 'task'); + $query->orWhere('element_type', '=', 'startEvent'); + } else { + $query->where('element_type', '=', 'task'); + } $query->orWhere(function ($query) { $query->where('element_type', '=', 'serviceTask'); $query->where('element_name', '=', 'AI Assistant'); From 5388c23f6013843a7bbb47c8b2821515cdb8f753 Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Wed, 25 Feb 2026 11:35:56 -0400 Subject: [PATCH 5/7] Refactor ProcessRequestToken to improve screen reference retrieval logic by prioritizing definition screenRef and enhancing config handling for web_entry. --- ProcessMaker/Models/ProcessRequestToken.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ProcessMaker/Models/ProcessRequestToken.php b/ProcessMaker/Models/ProcessRequestToken.php index 41ddb61ab4..63da95cd41 100644 --- a/ProcessMaker/Models/ProcessRequestToken.php +++ b/ProcessMaker/Models/ProcessRequestToken.php @@ -452,10 +452,11 @@ public function getScreen(): ?Screen if (isset($definition['config'])) { $config = json_decode($definition['config']); } - if (isset($config) and isset($config->web_entry)) { + + $screenRef = $definition['screenRef'] ?? null; + + if (!$screenRef && isset($config) && isset($config->web_entry)) { $screenRef = $config->web_entry->screen_id ?? null; - } else { - $screenRef = $definition['screenRef'] ?? null; } $screen = Screen::find($screenRef); From e139d8f0eee2f72ea43ccab6f35e456483dd717d Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Wed, 25 Feb 2026 11:57:59 -0400 Subject: [PATCH 6/7] Prioritizing definition's screenRef and optimizing config handling for web_entry. --- ProcessMaker/Models/ProcessRequestToken.php | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ProcessMaker/Models/ProcessRequestToken.php b/ProcessMaker/Models/ProcessRequestToken.php index 63da95cd41..d5d1bfc54a 100644 --- a/ProcessMaker/Models/ProcessRequestToken.php +++ b/ProcessMaker/Models/ProcessRequestToken.php @@ -448,15 +448,12 @@ public function getBpmnDefinition() public function getScreen(): ?Screen { $definition = $this->getDefinition(); - $config = null; - if (isset($definition['config'])) { - $config = json_decode($definition['config']); - } + $screenRef = isset($definition['screenRef']) ? $definition['screenRef'] : null; - $screenRef = $definition['screenRef'] ?? null; + if (!$screenRef) { + $config = isset($definition['config']) ? json_decode($definition['config']) : null; - if (!$screenRef && isset($config) && isset($config->web_entry)) { - $screenRef = $config->web_entry->screen_id ?? null; + $screenRef = (isset($config) && isset($config->web_entry)) ? $config->web_entry->screen_id ?? null : null; } $screen = Screen::find($screenRef); From 78c4cdff699e8a30db8fabf580c241a78c21985e Mon Sep 17 00:00:00 2001 From: "Marco A. Nina Mena" Date: Wed, 25 Feb 2026 16:27:30 -0400 Subject: [PATCH 7/7] Enhance ProcessRequestController to ensure screenRef is prioritized in token definitions and improve config handling for web_entry. --- .../Http/Controllers/Api/ProcessRequestController.php | 8 ++++++++ ProcessMaker/Http/Resources/ScreenVersion.php | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php index e008c8e07f..bb1a4316a5 100644 --- a/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php +++ b/ProcessMaker/Http/Controllers/Api/ProcessRequestController.php @@ -792,6 +792,14 @@ public function screenRequested(Request $httpRequest, ProcessRequest $request) $collection = $response->getCollection() ->transform(function ($token): ?object { + $definition = $token->getDefinition(); + if (!array_key_exists('screenRef', $definition)) { + $config = isset($definition['config']) ? json_decode($definition['config']) : null; + $screenRef = (isset($config) && isset($config->web_entry)) ? $config->web_entry->screen_id ?? null : null; + if (!$screenRef) { + return null; + } + } $screen = $token->getScreenVersion() ?? null; if ($screen) { diff --git a/ProcessMaker/Http/Resources/ScreenVersion.php b/ProcessMaker/Http/Resources/ScreenVersion.php index 31b740aab7..ac288d6ee9 100644 --- a/ProcessMaker/Http/Resources/ScreenVersion.php +++ b/ProcessMaker/Http/Resources/ScreenVersion.php @@ -63,7 +63,7 @@ public function toArray($request) */ private function setDefaultScreenForNestedScreens(array &$screenVersion): void { - $configArray = $screenVersion['config']; + $configArray = $screenVersion['config'] ?? []; foreach ($configArray as $key => $config) { foreach ($config['items'] as $itemKey => $item) { if (isset($item['component']) && $item['component'] === 'FormNestedScreen') {