status === 'closed') { throw ValidationException::withMessages([ 'status' => __('feedback.already_closed'), ]); } if (! $actor->hasPermissionTo('close-ticket')) { throw new HttpException(403, __('feedback.close_permission_denied')); } if (! $actor->hasRole('admin')) { $managedDeptIds = Department::where('manager_id', $actor->id)->pluck('id')->toArray(); $actorDeptId = $actor->department_id; $allowedDeptIds = array_filter(array_merge([$actorDeptId], $managedDeptIds)); if (! in_array($feedback->current_department_id, $allowedDeptIds)) { throw new HttpException(403, __('feedback.close_department_only')); } } $fileService = App::make(FileService::class); if (! $fileService->hasCollection($feedback, 'proof_of_resolution')) { throw ValidationException::withMessages([ 'status' => __('feedback.proof_required'), ]); } $previousStatus = $feedback->status; $feedback->update(['status' => 'closed']); ActivityLogger::log( 'close', __('feedback.log_close', ['title' => $feedback->title]), $feedback, [ 'feedback_id' => $feedback->id, 'previous_status' => $previousStatus, ], ); $this->notifyStakeholders($feedback, $actor); } public function resolve(Feedback $feedback, User $actor): void { if (in_array($feedback->status, ['closed', 'resolved'])) { throw ValidationException::withMessages([ 'status' => __('feedback.already_resolved'), ]); } $feedback->update(['status' => 'resolved']); } protected function notifyStakeholders(Feedback $feedback, User $actor): void { $notifiedUserIds = []; if ($feedback->assignedTo) { $feedback->assignedTo->notify(new \App\Notifications\TicketClosed($feedback, $actor)); $notifiedUserIds[] = $feedback->assignedTo->id; } $department = $feedback->currentDepartment; if ($department && $department->manager) { if (! in_array($department->manager->id, $notifiedUserIds)) { $department->manager->notify(new \App\Notifications\TicketClosed($feedback, $actor)); } } else { // No manager! Notify admins $admins = User::whereHas('roles', fn ($q) => $q->where('name', 'admin'))->get(); foreach ($admins as $admin) { if (! in_array($admin->id, $notifiedUserIds)) { $admin->notify(new \App\Notifications\TicketClosed($feedback, $actor)); } } } } }