From 0681defcd0045cf6eb06ecab482586de8d64e3cd Mon Sep 17 00:00:00 2001 From: Roly Gutierrez Date: Thu, 28 Aug 2025 10:59:53 -0400 Subject: [PATCH 1/2] FOUR-23734 [44349] - Reassignment User List Not Filtering by Regular Expressio ## Description: Steps to Reproduce the Issue: Open a Request/Case: Navigate to the ProcessMaker cases and open an existing request (case). Click on the Reassignment Button: Locate and click the "Reassignment" button to reassign the case to another user. View the Assignment User List: Observe the list of users displayed in the reassignment dropdown. Current Behavior (Issue): Instead of filtering users as per the regular expression, all users are displayed in the reassignment list. Expected Behavior: The user list should be filtered based on the regular expression condition set in the process. Only users that match the specified regular expression should appear in the list. Impact: The client expects the user list to be filtered dynamically based on the regular expression condition applied in the process, but it is not working correctly. Potentials Fix: Request the development team to investigate and ensure that the reassignment user list correctly applies the regular expression condition as configured in the process. Acceptance criteria: When having a Rule Expression, the reassignment should only allow to reassign to Admin, Process Manager or the users listed in the Rule Expression list. ## Related Tickets & Packages https://processmaker.atlassian.net/browse/FOUR-23734 --- .../Http/Controllers/Api/UserController.php | 6 +- ProcessMaker/Models/ProcessRequestToken.php | 61 +++++++++++++++++++ resources/js/common/reassignMixin.js | 12 ++-- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/ProcessMaker/Http/Controllers/Api/UserController.php b/ProcessMaker/Http/Controllers/Api/UserController.php index 34c3d6c758..070483b348 100644 --- a/ProcessMaker/Http/Controllers/Api/UserController.php +++ b/ProcessMaker/Http/Controllers/Api/UserController.php @@ -209,10 +209,14 @@ public function getUsersTaskCount(Request $request) $include_ids = explode(',', $include_ids_string); } elseif ($request->has('assignable_for_task_id')) { $task = ProcessRequestToken::findOrFail($request->input('assignable_for_task_id')); - if ($task->getAssignmentRule() === 'user_group') { + $assignmentRule = $task->getAssignmentRule(); + if ($assignmentRule === 'user_group') { // Limit the list of users to those that can be assigned to the task $include_ids = $task->process->getAssignableUsers($task->element_id); } + if ($assignmentRule === 'rule_expression' && $request->has('form_data')) { + $include_ids = $task->getAssigneesFromExpression($request->input('form_data')); + } } if (!empty($include_ids)) { diff --git a/ProcessMaker/Models/ProcessRequestToken.php b/ProcessMaker/Models/ProcessRequestToken.php index 0f052e1819..c12e332b25 100644 --- a/ProcessMaker/Models/ProcessRequestToken.php +++ b/ProcessMaker/Models/ProcessRequestToken.php @@ -30,6 +30,7 @@ use ProcessMaker\Traits\HasUuids; use ProcessMaker\Traits\HideSystemResources; use ProcessMaker\Traits\SerializeToIso8601; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Throwable; /** @@ -968,6 +969,66 @@ public function getAssignmentRule() return $assignment; } + /** + * Get the assignees for the token. + * + * @param array $assignments + * @param array $variables + * @return array + */ + public function getAssignees(array $assignments, array $variables): array + { + $result = []; + $language = new ExpressionLanguage(); + + foreach ($assignments as $assignment) { + $isTrue = false; + + if (!empty($assignment['expression'])) { + try { + $isTrue = $language->evaluate($assignment['expression'], $variables); + } catch (Throwable $e) { + $isTrue = false; + } + } + + if ($isTrue) { + $result[] = $assignment['assignee']; + } + + if (isset($assignment['default']) && $assignment['default'] === true) { + $result[] = $assignment['assignee']; + } + } + + return $result; + } + + /** + * Get the assignees from the expression + * + * @param string $form_data + * @return array + */ + public function getAssigneesFromExpression(string $form_data): array + { + $formData = json_decode($form_data, true); + + $activity = $this->getBpmnDefinition()->getBpmnElementInstance(); + $assignmentRules = $activity->getProperty('assignmentRules', null); + $assignments = json_decode($assignmentRules, true); + + $include_ids = $this->getAssignees($assignments, $formData); + + // we add the manager to the list of assignees + $manager_id = $this->process->manager_id; + if ($manager_id) { + $include_ids[] = $manager_id; + } + + return $include_ids; + } + /** * Returns if the token has the self service option activated */ diff --git a/resources/js/common/reassignMixin.js b/resources/js/common/reassignMixin.js index 5a9aef2fbe..d1f920943a 100644 --- a/resources/js/common/reassignMixin.js +++ b/resources/js/common/reassignMixin.js @@ -28,14 +28,18 @@ export default { } if (this.task?.id) { params.assignable_for_task_id = this.task.id; + // The variables are needed to calculate the rule expression. + if (this?.formData) { + params.form_data = this.formData; + delete params.form_data._user; + delete params.form_data._request; + delete params.form_data._process; + } } - + console.log('getReassignUsers:', JSON.stringify(this.formData, null, 2)); ProcessMaker.apiClient.get('users_task_count', { params }).then(response => { this.reassignUsers = []; response.data.data.forEach((user) => { - if (this.currentTaskUserId === user.id) { - return; - } this.reassignUsers.push({ text: user.fullname, value: user.id, From 6088e4b10e25a282f0380a2ccdf7c701389a9561 Mon Sep 17 00:00:00 2001 From: Roly Gutierrez Date: Thu, 28 Aug 2025 11:07:14 -0400 Subject: [PATCH 2/2] FOUR-23734 Remove console.log --- resources/js/common/reassignMixin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/common/reassignMixin.js b/resources/js/common/reassignMixin.js index d1f920943a..fc4d2b9550 100644 --- a/resources/js/common/reassignMixin.js +++ b/resources/js/common/reassignMixin.js @@ -36,7 +36,7 @@ export default { delete params.form_data._process; } } - console.log('getReassignUsers:', JSON.stringify(this.formData, null, 2)); + ProcessMaker.apiClient.get('users_task_count', { params }).then(response => { this.reassignUsers = []; response.data.data.forEach((user) => {