97 lines
3.2 KiB
PHP
97 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Department;
|
|
use App\Models\Feedback;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\App;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
|
|
|
class ClosingService
|
|
{
|
|
public function close(Feedback $feedback, User $actor): void
|
|
{
|
|
if ($feedback->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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|