resourceAccess->tasks($request->user()) ->with(['project', 'assignee', 'reporter']) ->withCount(['comments', 'files']); if ($request->filled('project_id')) { $query->where('project_id', $request->project_id); } if ($request->filled('assignee_id')) { $query->where('assignee_id', $request->assignee_id); } if ($request->filled('status')) { $query->where('status', $request->status); } if ($request->filled('priority')) { $query->where('priority', $request->priority); } if ($request->filled('search')) { $search = $request->search; $query->where('title', 'like', "%{$search}%"); } $perPage = min((int) $request->input('per_page', 15), 100); $sortBy = in_array($request->input('sort_by'), ['id', 'title', 'status', 'priority', 'created_at', 'updated_at', 'due_date', 'sort_order'], true) ? $request->input('sort_by') : 'created_at'; $sortDir = $request->input('sort_dir') === 'asc' ? 'asc' : 'desc'; $tasks = $query->orderBy($sortBy, $sortDir)->paginate($perPage); return response()->json([ 'success' => true, 'data' => TaskResource::collection($tasks), 'meta' => [ 'current_page' => $tasks->currentPage(), 'last_page' => $tasks->lastPage(), 'per_page' => $tasks->perPage(), 'total' => $tasks->total(), ], 'message' => 'لیست وظایف', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در دریافت لیست وظایف', ], 500); } } public function show(Task $task): JsonResponse { try { $task->load(['project', 'assignee', 'reporter', 'checklists', 'subtasks', 'comments.user', 'files']); return response()->json([ 'success' => true, 'data' => new TaskResource($task), 'message' => 'اطلاعات وظیفه', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در دریافت اطلاعات وظیفه', ], 500); } } public function store(StoreTaskRequest $request): JsonResponse { try { $data = $request->validated(); abort_unless( $this->resourceAccess->projects($request->user())->whereKey($data['project_id'])->exists(), 403, 'شما به پروژه انتخاب‌شده دسترسی ندارید.' ); $data['reporter_id'] = $request->user()->id; $data['created_by'] = $request->user()->id; $task = Task::create($data); $this->projectProgressService->calculateProgress($task->project_id); $this->activityLogService->log( $request->user()->id, 'create_task', "وظیفه {$task->title} ایجاد شد", 'task', $task->id, $task->project_id, $task->id, ['task_title' => $task->title] ); if ($task->assignee_id) { $this->notificationService->create( $task->assignee_id, 'task_assigned', [ 'task_id' => $task->id, 'project_id' => $task->project_id, 'url' => '/kanban', 'notifiable_type' => 'App\\Models\\Task', 'notifiable_id' => $task->id, ], "وظیفه جدید {$task->title} به شما اختصاص داده شد" ); } $task->load(['project', 'assignee', 'reporter']); return response()->json([ 'success' => true, 'data' => new TaskResource($task), 'message' => 'وظیفه با موفقیت ایجاد شد', ], 201); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در ایجاد وظیفه', ], 500); } } public function update(UpdateTaskRequest $request, Task $task): JsonResponse { try { $validated = $request->validated(); if (isset($validated['project_id'])) { abort_unless( $this->resourceAccess->projects($request->user())->whereKey($validated['project_id'])->exists(), 403, 'شما به پروژه انتخاب‌شده دسترسی ندارید.' ); } $oldStatus = $task->status; $task->update($validated); if ($task->wasChanged('status')) { $this->activityLogService->log( $request->user()->id, 'update_task_status', "وضعیت وظیفه {$task->title} از {$oldStatus} به {$task->status} تغییر یافت", 'task', $task->id, $task->project_id, $task->id, ['old_status' => $oldStatus, 'new_status' => $task->status] ); } $this->projectProgressService->calculateProgress($task->project_id); $task->load(['project', 'assignee', 'reporter']); return response()->json([ 'success' => true, 'data' => new TaskResource($task->fresh()), 'message' => 'وظیفه با موفقیت به‌روزرسانی شد', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در به‌روزرسانی وظیفه', ], 500); } } public function destroy(Request $request, Task $task): JsonResponse { try { $projectId = $task->project_id; $taskId = $task->id; $taskTitle = $task->title; $this->activityLogService->log( $request->user()->id, 'delete_task', "وظیفه {$taskTitle} حذف شد", 'task', $taskId, $projectId, null, ['task_title' => $taskTitle] ); $task->delete(); $this->projectProgressService->calculateProgress($projectId); return response()->json([ 'success' => true, 'message' => 'وظیفه با موفقیت حذف شد', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در حذف وظیفه', ], 500); } } public function updateStatus(Request $request, Task $task): JsonResponse { try { $request->validate(['status' => 'required|string']); $oldStatus = $task->status; $task->update(['status' => $request->status]); $this->projectProgressService->calculateProgress($task->project_id); $this->activityLogService->log( $request->user()->id, 'update_task_status', "وضعیت وظیفه {$task->title} از {$oldStatus} به {$task->status} تغییر یافت", 'task', $task->id, $task->project_id, $task->id, ['old_status' => $oldStatus, 'new_status' => $task->status] ); if ($task->assignee_id) { $this->notificationService->create( $task->assignee_id, 'task_status_changed', ['task_id' => $task->id, 'status' => $task->status], "وضعیت وظیفه {$task->title} به {$task->status} تغییر یافت" ); } return response()->json([ 'success' => true, 'data' => new TaskResource($task->fresh()->load(['project', 'assignee'])), 'message' => 'وضعیت وظیفه به‌روزرسانی شد', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در به‌روزرسانی وضعیت', ], 500); } } public function updateAssignee(Request $request, Task $task): JsonResponse { try { $request->validate(['assignee_id' => 'nullable|exists:users,id']); $oldAssigneeId = $task->assignee_id; $task->update(['assignee_id' => $request->assignee_id]); if ($request->assignee_id && $request->assignee_id != $oldAssigneeId) { $this->notificationService->create( $request->assignee_id, 'task_assigned', [ 'task_id' => $task->id, 'project_id' => $task->project_id, 'url' => '/kanban', 'notifiable_type' => 'App\\Models\\Task', 'notifiable_id' => $task->id, ], "وظیفه {$task->title} به شما اختصاص داده شد" ); } $this->activityLogService->log( $request->user()->id, 'update_task_assignee', "مسئول وظیفه {$task->title} تغییر یافت", 'task', $task->id, $task->project_id, $task->id, ['old_assignee' => $oldAssigneeId, 'new_assignee' => $request->assignee_id] ); return response()->json([ 'success' => true, 'data' => new TaskResource($task->fresh()->load(['project', 'assignee'])), 'message' => 'مسئول وظیفه به‌روزرسانی شد', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در به‌روزرسانی مسئول', ], 500); } } public function reorder(Request $request): JsonResponse { try { $request->validate([ 'tasks' => 'required|array', 'tasks.*.id' => 'required|exists:tasks,id', 'tasks.*.sort_order' => 'required|integer', ]); foreach ($request->tasks as $item) { Task::where('id', $item['id'])->update(['sort_order' => $item['sort_order']]); } return response()->json([ 'success' => true, 'message' => 'ترتیب وظایف به‌روزرسانی شد', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در مرتب‌سازی وظایف', ], 500); } } public function myTasks(Request $request): JsonResponse { try { $tasks = Task::with(['project', 'assignee']) ->where('assignee_id', $request->user()->id) ->where('status', '!=', 'done') ->orderBy('due_date') ->get(); return response()->json([ 'success' => true, 'data' => TaskResource::collection($tasks), 'message' => 'وظایف من', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در دریافت وظایف من', ], 500); } } public function delayedTasks(): JsonResponse { try { $tasks = Task::with(['project', 'assignee']) ->where('due_date', '<', Carbon::now()) ->where('status', '!=', 'done') ->orderBy('due_date') ->get(); return response()->json([ 'success' => true, 'data' => TaskResource::collection($tasks), 'message' => 'وظایف عقب افتاده', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'خطا در دریافت وظایف عقب افتاده', ], 500); } } }