Skip to content

Commit 33d31b7

Browse files
authored
Merge pull request #8664 from ProcessMaker/bugfix/FOUR-28520
FOUR-28520 Reassign > The imported process does not list all reassign…
2 parents b1863e2 + 745cc92 commit 33d31b7

File tree

7 files changed

+538
-43
lines changed

7 files changed

+538
-43
lines changed

ProcessMaker/Http/Controllers/Api/UserController.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,10 +255,13 @@ public function getUsersTaskCount(Request $request)
255255
$processRequestToken = ProcessRequestToken::findOrFail($request->input('assignable_for_task_id'));
256256
if (config('app.reassign_restrict_to_assignable_users')) {
257257
$include_ids = $processRequestToken->process->getAssignableUsersByAssignmentType($processRequestToken);
258-
}
259-
$assignmentRule = $processRequestToken->getAssignmentRule();
260-
if ($assignmentRule === 'rule_expression' && $request->has('form_data')) {
261-
$include_ids = $processRequestToken->getAssigneesFromExpression($request->input('form_data'));
258+
$assignmentRule = $processRequestToken->getAssignmentRule();
259+
if ($assignmentRule === 'rule_expression' && $request->has('form_data')) {
260+
$include_ids = $processRequestToken->getAssigneesFromExpression($request->input('form_data'));
261+
}
262+
if ($assignmentRule === 'process_variable' && $request->has('form_data')) {
263+
$include_ids = $processRequestToken->getUsersFromProcessVariable($request->input('form_data'));
264+
}
262265
}
263266
}
264267

ProcessMaker/Models/ProcessRequestToken.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,60 @@ public function getAssignmentRule()
991991
return $assignment;
992992
}
993993

994+
/**
995+
* Get user IDs from process variables for task assignment.
996+
*
997+
* Extracts user IDs and group IDs from form data based on the activity's
998+
* assignedUsers and assignedGroups properties. Retrieves all users from
999+
* specified groups (including subgroups recursively) and combines them
1000+
* with directly assigned users.
1001+
*
1002+
* Used when assignment rule is 'process_variable'.
1003+
*
1004+
* @param array $form_data Form data containing process variable values.
1005+
* Keys must match activity's assignedUsers and
1006+
* assignedGroups properties. Values must be arrays.
1007+
*
1008+
* @return array Unique numeric user IDs (direct users + users from groups).
1009+
*/
1010+
public function getUsersFromProcessVariable(array $form_data)
1011+
{
1012+
$activity = $this->getBpmnDefinition()->getBpmnElementInstance();
1013+
$assignedUsers = $activity->getProperty('assignedUsers', null);
1014+
$assignedGroups = $activity->getProperty('assignedGroups', null);
1015+
1016+
$usersIds = [];
1017+
$groupsIds = [];
1018+
1019+
// Validate and get user IDs from form_data
1020+
if ($assignedUsers && isset($form_data[$assignedUsers]) && is_array($form_data[$assignedUsers])) {
1021+
$usersIds = $form_data[$assignedUsers];
1022+
}
1023+
1024+
// Validate and get group IDs from form_data
1025+
if ($assignedGroups && isset($form_data[$assignedGroups]) && is_array($form_data[$assignedGroups])) {
1026+
$groupsIds = $form_data[$assignedGroups];
1027+
}
1028+
1029+
// Get users from groups using the Process model method
1030+
$usersFromGroups = [];
1031+
if (!empty($groupsIds) && $this->process) {
1032+
// Use the getConsolidatedUsers method from the Process model
1033+
// This method gets users from groups including subgroups recursively
1034+
$this->process->getConsolidatedUsers($groupsIds, $usersFromGroups);
1035+
}
1036+
1037+
// Combine direct users with users from groups
1038+
$allUserIds = array_unique(array_merge($usersIds, $usersFromGroups));
1039+
1040+
// Convert to numeric array and filter valid values
1041+
$allUserIds = array_values(array_filter($allUserIds, function ($id) {
1042+
return !empty($id) && is_numeric($id) && $id > 0;
1043+
}));
1044+
1045+
return $allUserIds;
1046+
}
1047+
9941048
/**
9951049
* Get the assignees for the token.
9961050
*

resources/js/common/reassignMixin.js

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { getReassignUsers as getReassignUsersApi } from "../tasks/api";
2+
13
export default {
24
data() {
35
return {
@@ -21,32 +23,28 @@ export default {
2123
this.allowReassignment = response.data[this.task.id];
2224
});
2325
},
24-
getReassignUsers(filter = null) {
25-
const params = { };
26-
if (filter) {
27-
params.filter = filter;
28-
}
29-
if (this.task?.id) {
30-
params.assignable_for_task_id = this.task.id;
31-
// The variables are needed to calculate the rule expression.
32-
if (this?.formData) {
33-
params.form_data = this.formData;
34-
delete params.form_data._user;
35-
delete params.form_data._request;
36-
delete params.form_data._process;
37-
}
38-
}
26+
async getReassignUsers(filter = null) {
27+
try {
28+
const response = await getReassignUsersApi(
29+
filter,
30+
this.task?.id,
31+
this.task?.request_data,
32+
this.currentTaskUserId
33+
);
3934

40-
ProcessMaker.apiClient.post('users_task_count', params ).then(response => {
4135
this.reassignUsers = [];
42-
response.data.data.forEach((user) => {
43-
this.reassignUsers.push({
44-
text: user.fullname,
45-
value: user.id,
46-
active_tasks_count: user.active_tasks_count
36+
if (response?.data) {
37+
response.data.forEach((user) => {
38+
this.reassignUsers.push({
39+
text: user.fullname,
40+
value: user.id,
41+
active_tasks_count: user.active_tasks_count
42+
});
4743
});
48-
});
49-
});
44+
}
45+
} catch (error) {
46+
console.error('Error loading reassign users:', error);
47+
}
5048
},
5149
onReassignInput: _.debounce(function (filter) {
5250
this.getReassignUsers(filter);

resources/js/tasks/api/index.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,49 @@
11
import { getApi } from "../variables/index";
22

3-
export const getReassignUsers = async (filter = null, taskId = null, currentTaskUserId = null) => {
3+
/**
4+
* Get reassign users using POST with form_data (for rule expression evaluation)
5+
* This replaces the obsolete GET method with the advanced POST logic from reassignMixin
6+
*
7+
* @param {string|null} filter - Filter string to search users
8+
* @param {number|null} taskId - Task ID to get assignable users for
9+
* @param {Object|null} formData - Form data needed to calculate rule expressions
10+
* @param {number|null} currentTaskUserId - User ID to exclude from results (matches: task?.user_id ?? task?.user?.id)
11+
* @returns {Promise<Object>} Response data with users array
12+
*/
13+
export const getReassignUsers = async (
14+
filter = null,
15+
taskId = null,
16+
formData = null,
17+
currentTaskUserId = null
18+
) => {
419
const api = getApi();
5-
const response = await api.get("users_task_count", { params: { filter, assignable_for_task_id: taskId, include_current_user: true } });
20+
const params = {};
21+
22+
if (filter) {
23+
params.filter = filter;
24+
}
25+
26+
if (taskId) {
27+
params.assignable_for_task_id = taskId;
28+
29+
// The variables are needed to calculate the rule expression.
30+
if (formData) {
31+
params.form_data = { ...formData };
32+
// Remove internal variables
33+
delete params.form_data._user;
34+
delete params.form_data._request;
35+
delete params.form_data._process;
36+
}
37+
}
38+
39+
const response = await api.post("users_task_count", params);
640
const data = response.data;
41+
42+
// Filter out current user to prevent self-reassignment (matches mixin logic)
743
if (currentTaskUserId && Array.isArray(data?.data)) {
844
data.data = data.data.filter((user) => user.id !== currentTaskUserId);
945
}
46+
1047
return data;
1148
};
1249

resources/js/tasks/components/TasksPreview.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@
201201
<TaskPreviewAssignment
202202
v-if="showReassignment"
203203
:task="task"
204+
:form-data="formData"
205+
:current-task-user-id="currentTaskUserId"
204206
@on-cancel-reassign="showReassignment = false"
205207
@on-reassign-user="e=> reassignUser(e,false)"
206208
/>
@@ -413,7 +415,6 @@ export default {
413415
},
414416
openReassignment() {
415417
this.showReassignment = !this.showReassignment;
416-
this.getReassignUsers();
417418
},
418419
getTaskDefinitionForReassignmentPermission() {
419420
ProcessMaker.apiClient

resources/js/tasks/components/taskPreview/TaskPreviewAssignment.vue

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ const props = defineProps({
6767
type: Object,
6868
required: true,
6969
},
70+
formData: {
71+
type: Object,
72+
default: null,
73+
},
74+
currentTaskUserId: {
75+
type: Number,
76+
default: null,
77+
},
7078
});
7179
7280
const emit = defineEmits(["on-reassign-user"]);
@@ -80,18 +88,29 @@ const disabledAssign = ref(false);
8088
// Computed properties
8189
const disabled = computed(() => !selectedUser.value || !comments.value?.trim());
8290
83-
// Load the reassign users
91+
// Load the reassign users using the centralized function with form_data
8492
const loadReassignUsers = async (filter) => {
85-
const response = await getReassignUsers(filter, props.task.id, props.task.user_id);
86-
87-
reassignUsers.value = [];
88-
response.data.forEach((user) => {
89-
reassignUsers.value.push({
90-
text: user.fullname,
91-
value: user.id,
92-
active_tasks_count: user.active_tasks_count,
93-
});
94-
});
93+
try {
94+
const response = await getReassignUsers(
95+
filter,
96+
props.task?.id,
97+
props.formData,
98+
props.currentTaskUserId
99+
);
100+
101+
reassignUsers.value = [];
102+
if (response?.data) {
103+
response.data.forEach((user) => {
104+
reassignUsers.value.push({
105+
text: user.fullname,
106+
value: user.id,
107+
active_tasks_count: user.active_tasks_count,
108+
});
109+
});
110+
}
111+
} catch (error) {
112+
console.error('Error loading reassign users:', error);
113+
}
95114
};
96115
97116
/**

0 commit comments

Comments
 (0)