| @@ -511,13 +511,18 @@ | ||
| 511 | 511 | $tasks = Task::where('stage_id', $oldStageId)->whereNull('parent_id')->whereNull('archived_at')->get(); |
| 512 | 512 | $sourceStage = Stage::findOrFail($oldStageId); |
| 513 | 513 | $targetStage = Stage::findOrFail($newStageId); |
| 514 | 514 | |
| 515 | - // Load shared watcher data once; stage data is injected per task below. | |
| 516 | - $tasks->load('watchers'); | |
| 515 | + // Reuse task-user relations unless default assignments change them. | |
| 516 | + $tasks->load(['assignees', 'watchers']); | |
| 517 | 517 | |
| 518 | 518 | // get the last position available of that stage |
| 519 | - $position = (new TaskService())->getLastPositionOfTasks($newStageId); | |
| 519 | + $taskService = new TaskService(); | |
| 520 | + $position = $taskService->getLastPositionOfTasks($newStageId); | |
| 521 | + $notificationService = new NotificationService(); | |
| 522 | + $currentUserId = get_current_user_id(); | |
| 523 | + // Stage-email eligibility per watcher, resolved in batches and shared across tasks. | |
| 524 | + $emailEligibility = []; | |
| 520 | 525 | |
| 521 | 526 | // update tasks stage and position |
| 522 | 527 | foreach ($tasks as $key => $task) { |
| 523 | 528 | $taskOldStageId = $task->stage_id; |
| @@ -532,12 +537,38 @@ | ||
| 532 | 537 | $task->setRelation('stage', $targetStage); |
| 533 | 538 | $task->save(); |
| 534 | 539 | |
| 535 | 540 | if ((int) $taskOldStageId !== (int) $newStageId) { |
| 541 | + $assignmentsChanged = $taskService->manageDefaultAssignees($task, $newStageId, $targetStage); | |
| 542 | + if ($targetStage->defaultTaskStatus() === 'closed' && $task->status !== 'closed') { | |
| 543 | + $task = $task->close(); | |
| 544 | + } | |
| 545 | + // Assignment hooks may change assignees and watchers before notification. | |
| 546 | + if ($assignmentsChanged) { | |
| 547 | + $task->load(['assignees', 'watchers']); | |
| 548 | + } | |
| 549 | + | |
| 536 | 550 | do_action('fluent_boards/task_stage_updated', $task, $taskOldStageId, [ |
| 537 | 551 | 'source' => $sourceStage, |
| 538 | 552 | 'target' => $targetStage, |
| 539 | 553 | ]); |
| 554 | + | |
| 555 | + $watcherIds = array_diff(array_map('intval', $task->watchers->pluck('ID')->toArray()), [$currentUserId]); | |
| 556 | + $unknownIds = array_diff($watcherIds, array_keys($emailEligibility)); | |
| 557 | + if ($unknownIds) { | |
| 558 | + $emailEligibility += array_fill_keys($unknownIds, false); | |
| 559 | + $enabledIds = $notificationService->getEmailEnabledUserIds($task->board_id, $unknownIds, Constant::BOARD_EMAIL_STAGE_CHANGE); | |
| 560 | + foreach ($enabledIds as $enabledId) { | |
| 561 | + $emailEligibility[$enabledId] = true; | |
| 562 | + } | |
| 563 | + } | |
| 564 | + $recipients = []; | |
| 565 | + foreach ($task->watchers as $watcher) { | |
| 566 | + if (!empty($emailEligibility[(int) $watcher->ID])) { | |
| 567 | + $recipients[] = $watcher->user_email; | |
| 568 | + } | |
| 569 | + } | |
| 570 | + $taskService->sendMailAfterTaskModify('stage_change', $recipients, $task->id); | |
| 540 | 571 | } |
| 541 | 572 | } |
| 542 | 573 | |
| 543 | 574 | if ($tasks->count() && (int) $sourceStage->id !== (int) $targetStage->id) { |