Skip to content

Commit ac2b6a0

Browse files
change to manage multiple managers
1 parent 4f5db81 commit ac2b6a0

16 files changed

Lines changed: 98 additions & 41 deletions

‎ProcessMaker/AssignmentRules/ProcessManagerAssigned.php‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use ProcessMaker\Exception\ThereIsNoProcessManagerAssignedException;
77
use ProcessMaker\Models\Process;
88
use ProcessMaker\Models\ProcessRequest;
9+
use ProcessMaker\Models\ProcessRequestToken;
910
use ProcessMaker\Nayra\Contracts\Bpmn\ActivityInterface;
1011
use ProcessMaker\Nayra\Contracts\Bpmn\TokenInterface;
1112

@@ -29,11 +30,54 @@ class ProcessManagerAssigned implements AssignmentRuleInterface
2930
*/
3031
public function getNextUser(ActivityInterface $task, TokenInterface $token, Process $process, ProcessRequest $request)
3132
{
32-
$user_id = $request->processVersion->manager_id;
33+
// review for multiple managers
34+
$managers = $request->processVersion->manager_id;
35+
$user_id = $this->getNextManagerAssigned($managers, $task, $request);
3336
if (!$user_id) {
3437
throw new ThereIsNoProcessManagerAssignedException($task);
3538
}
3639

3740
return $user_id;
3841
}
42+
43+
/**
44+
* Get the round robin manager using a true round robin algorithm
45+
*
46+
* @param array $managers
47+
* @return int|null
48+
*/
49+
private function getNextManagerAssigned($managers, $task, $request)
50+
{
51+
// Validate input
52+
if (empty($managers) || !is_array($managers)) {
53+
return null;
54+
}
55+
56+
// If only one manager, return it
57+
if (count($managers) === 1) {
58+
return $managers[0];
59+
}
60+
61+
// get the last manager assigned to the task
62+
$last = ProcessRequestToken::where('process_id', $task->process->id)
63+
->where('element_id', $$task->element_id)
64+
->where('process_request_id', $request->id)
65+
->whereIn('user_id', $managers)
66+
->orderBy('created_at', 'desc')
67+
->first();
68+
69+
$user_id = $last ? $last->user_id : null;
70+
71+
sort($managers);
72+
73+
$key = array_search($user_id, $managers);
74+
if ($key === false) {
75+
$key = 0;
76+
}
77+
$key = $key + 1;
78+
$key = $key % count($managers);
79+
$user_id = $managers[$key];
80+
81+
return $user_id;
82+
}
3983
}

‎ProcessMaker/Http/Controllers/Api/ProcessController.php‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ public function store(Request $request)
429429

430430
//set manager id
431431
if ($request->has('manager_id')) {
432-
$process->manager_id = $request->input('manager_id', null);
432+
$process->manager_id = $request->input('manager_id', []);
433433
}
434434

435435
if (isset($data['bpmn'])) {
@@ -542,7 +542,7 @@ public function update(Request $request, Process $process)
542542

543543
$process->fill($request->except('notifications', 'task_notifications', 'notification_settings', 'cancel_request', 'cancel_request_id', 'start_request_id', 'edit_data', 'edit_data_id', 'projects'));
544544
if ($request->has('manager_id')) {
545-
$process->manager_id = $request->input('manager_id', null);
545+
$process->manager_id = $request->input('manager_id', []);
546546
}
547547

548548
if ($request->has('user_id')) {
@@ -1714,7 +1714,7 @@ protected function checkUserCanStartProcess($event, $currentUser, $process, $req
17141714
}
17151715
break;
17161716
case 'process_manager':
1717-
$response = $currentUser === $process->manager_id;
1717+
$response = in_array($currentUser, $process->manager_id ?? []);
17181718
break;
17191719
}
17201720
}

‎ProcessMaker/ImportExport/Exporters/ProcessExporter.php‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,13 @@ public function export() : void
3838
$this->addDependent('user', $process->user, UserExporter::class);
3939
}
4040

41-
if ($process->manager) {
42-
$this->addDependent('manager', $process->manager, UserExporter::class, null, ['properties']);
41+
// review
42+
$managers = $process->getManagers();
43+
44+
if ($managers) {
45+
foreach ($managers as $manager) {
46+
$this->addDependent('manager', $manager, UserExporter::class, null, ['properties']);
47+
}
4348
}
4449

4550
$this->exportScreens();
@@ -99,9 +104,11 @@ public function import($existingAssetInDatabase = null, $importingFromTemplate =
99104
$process->user_id = User::where('is_administrator', true)->firstOrFail()->id;
100105
}
101106

107+
$managers = [];
102108
foreach ($this->getDependents('manager') as $dependent) {
103-
$process->manager_id = $dependent->model->id;
109+
$managers[] = $dependent->model->id;
104110
}
111+
$process->manager_id = $managers;
105112

106113
// Avoid associating the category from the manifest with processes imported from templates.
107114
// Use the user-selected category instead.

‎ProcessMaker/Jobs/ErrorHandling.php‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,11 @@ private function requeue($job)
9393
public function sendExecutionErrorNotification(string $message)
9494
{
9595
if ($this->processRequestToken) {
96-
$user = $this->processRequestToken->processRequest->processVersion->manager;
97-
if ($user !== null) {
98-
Log::info('Send Execution Error Notification: ' . $message);
99-
Notification::send($user, new ErrorExecutionNotification($this->processRequestToken, $message, $this->bpmnErrorHandling));
96+
// review no multiple managers
97+
$mangers = $this->processRequestToken->processRequest->processVersion->getManagers();
98+
foreach ($mangers as $manager) {
99+
Log::info('Send Execution Error Notification: ' . $message . ' to manager: ' . $manager->username);
100+
Notification::send($manager, new ErrorExecutionNotification($this->processRequestToken, $message, $this->bpmnErrorHandling));
100101
}
101102
}
102103
}

‎ProcessMaker/Models/FormalExpression.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ function ($__data, $user_id, $assigned_groups) {
240240
$request = ProcessRequest::find($__data['_request']['id']);
241241
$process = $request->processVersion;
242242

243-
return $process->manager_id;
243+
return array_rand($process->manager_id ?? []);
244244
}
245245

246246
return $user->manager_id;

‎ProcessMaker/Models/Process.php‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
* @OA\Property(property="self_service_tasks", type="object"),
8787
* @OA\Property(property="signal_events", type="array", @OA\Items(type="object")),
8888
* @OA\Property(property="category", type="object", @OA\Schema(ref="#/components/schemas/ProcessCategory")),
89-
* @OA\Property(property="manager_id", type="integer", format="id"),
89+
* @OA\Property(property="manager_id", type="array", @OA\Items(type="integer", format="id")),
9090
* ),
9191
* @OA\Schema(
9292
* schema="Process",
@@ -693,7 +693,8 @@ private function checkAssignment(ProcessRequest $request, ActivityInterface $act
693693
if ($isSelfService && !$escalateToManager) {
694694
return null;
695695
}
696-
$user = $request->processVersion->manager;
696+
$rule = new ProcessManagerAssigned();
697+
$user = $rule->getNextUser($activity, $request->token, $this, $request);
697698
if (!$user) {
698699
throw new ThereIsNoProcessManagerAssignedException($activity);
699700
}
@@ -1147,7 +1148,7 @@ public function getStartEvents($filterWithPermissions = false, $filterWithoutAss
11471148
}
11481149
}
11491150
} elseif (isset($startEvent['assignment']) && $startEvent['assignment'] === 'process_manager') {
1150-
$access = $this->manager && $this->manager->id && $this->manager->id === $user->id;
1151+
$access = in_array($user->id, $this->manager_id ?? []);
11511152
} else {
11521153
$access = false;
11531154
}

‎ProcessMaker/Models/ProcessRequest.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ public function getNotifiableUserIds($notifiableType)
280280
case 'participants':
281281
return $this->participants()->get()->pluck('id');
282282
case 'manager':
283-
return collect([$this->process()->first()->manager_id]);
283+
return collect($this->process()->first()->manager_id ?? []);
284284
default:
285285
return collect([]);
286286
}

‎ProcessMaker/Models/ProcessRequestToken.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public function getNotifiableUserIds($notifiableType)
256256
case 'manager':
257257
$process = $this->process()->first();
258258

259-
return collect([$process?->manager_id]);
259+
return collect($process?->manager_id ?? []);
260260
break;
261261
default:
262262
return collect([]);

‎ProcessMaker/Policies/ProcessPolicy.php‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ProcessPolicy
1717
* Run before all methods to determine if the
1818
* user is an admin and can do everything.
1919
*
20-
* @param \ProcessMaker\Models\User $user
20+
* @param User $user
2121
* @return mixed
2222
*/
2323
public function before(User $user)
@@ -39,8 +39,8 @@ public function edit(User $user, Process $process)
3939
/**
4040
* Determine whether the user can start the process.
4141
*
42-
* @param \ProcessMaker\Models\User $user
43-
* @param \ProcessMaker\Models\Process $process
42+
* @param User $user
43+
* @param Process $process
4444
* @return mixed
4545
*/
4646
public function start(User $user, Process $process)
@@ -60,7 +60,7 @@ public function start(User $user, Process $process)
6060
$userCanStartAsProcessManager = array_reduce($process->getStartEvents(),
6161
function ($carry, $item) use ($process, $user) {
6262
if (array_key_exists('assignment', $item)) {
63-
$carry = $carry || ($item['assignment'] === 'process_manager' && $process->manager_id === $user->id);
63+
$carry = $carry || ($item['assignment'] === 'process_manager' && in_array($user->id, $process->manager_id ?? []));
6464
}
6565

6666
return $carry;
@@ -81,8 +81,8 @@ function ($carry, $item) use ($process, $user) {
8181
/**
8282
* Determine whether the user can cancel the process.
8383
*
84-
* @param \ProcessMaker\Models\User $user
85-
* @param \ProcessMaker\Models\Process $process
84+
* @param User $user
85+
* @param Process $process
8686
*
8787
* @return bool
8888
*/
@@ -99,7 +99,7 @@ public function cancel(User $user, Process $process)
9999
}
100100

101101
if (
102-
$process->manager_id === $user->id &&
102+
in_array($user->id, $process->manager_id ?? []) &&
103103
$process->getProperty('manager_can_cancel_request') === true
104104
) {
105105
return true;
@@ -111,8 +111,8 @@ public function cancel(User $user, Process $process)
111111
/**
112112
* Determine whether the user can edit data.
113113
*
114-
* @param \ProcessMaker\Models\User $user
115-
* @param \ProcessMaker\Models\Process $process
114+
* @param User $user
115+
* @param Process $process
116116
*
117117
* @return bool
118118
*/

‎ProcessMaker/Policies/ProcessRequestTokenPolicy.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function before(User $user)
3838
public function view(User $user, ProcessRequestToken $processRequestToken)
3939
{
4040
if ($processRequestToken->user_id == $user->id ||
41-
$processRequestToken->process?->manager_id === $user->id
41+
in_array($user->id, $processRequestToken->process?->manager_id ?? [])
4242
) {
4343
return true;
4444
}
@@ -59,7 +59,7 @@ public function update(User $user, ProcessRequestToken $processRequestToken)
5959
if (
6060
$processRequestToken->user_id === $user->id ||
6161
$processRequestToken->user_id === app(AnonymousUser::class)->id ||
62-
$processRequestToken->process?->manager_id === $user->id
62+
in_array($user->id, $processRequestToken->process?->manager_id ?? [])
6363
) {
6464
return true;
6565
}
@@ -90,13 +90,13 @@ public function viewScreen(User $user, ProcessRequestToken $task): bool
9090
public function rollback(User $user, ProcessRequestToken $task)
9191
{
9292
// For now, only the process manager can rollback the request
93-
return $user->id === $task->process->managerId;
93+
return in_array($user->id, $task->process?->manager_id ?? []);
9494
}
9595

9696
public function reassign(User $user, ProcessRequestToken $task)
9797
{
9898
// If user is process manager
99-
if ($user->id === $task->process->managerId) {
99+
if (in_array($user->id, $task->process?->manager_id ?? [])) {
100100
return true;
101101
}
102102

0 commit comments

Comments
 (0)