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..fc4d2b9550 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; + } } 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,