commonUtil = $commonUtil; $this->ppUtil = $ppUtil; $this->moduleUtil = $moduleUtil; } protected function authorizeModule($business_id) { if (! (auth()->user()->can('superadmin') || $this->moduleUtil->hasThePermissionInSubscription($business_id, 'professional_project_module'))) { abort(403, 'Unauthorized action.'); } if (! auth()->user()->can('professionalproject.view_gantt')) { abort(403, 'Unauthorized action.'); } } protected function normalizeStartDate($start): string { $start = is_string($start) ? trim($start) : ''; if ($start === '') { return now()->format('Y-m-d'); } if (function_exists('english_number')) { $start = english_number($start); } $start = str_replace('/', '-', $start); if (preg_match('/^1[34]\d{2}-\d{1,2}-\d{1,2}$/', $start)) { $converted = jalali_to_gregorian($start, 'Y-m-d'); return $converted ?: now()->format('Y-m-d'); } return $start; } public function storeTask(Request $request) { $business_id = $request->session()->get('user.business_id'); $this->authorizeModule($business_id); $project_id = $request->input('project_id'); $status_id = $this->ppUtil->getDefaultTaskStatusId($business_id); $milestone = $this->ppUtil->ensureUncategorisedMilestone($business_id, $project_id, auth()->user()->id); $start = $this->normalizeStartDate($request->input('start_date')); $duration = max(1, (int) $request->input('duration', 1)); $task = PpTask::create([ 'business_id' => $business_id, 'project_id' => $project_id, 'milestone_id' => $milestone->id, 'title' => $request->input('text', __('professionalproject::lang.new_task')), 'status_id' => $status_id, 'priority' => $request->input('priority', 'normal'), 'start_date' => $start, 'due_date' => \Carbon\Carbon::parse($start)->addDays($duration), 'duration' => $duration, 'progress' => ($request->input('progress', 0)) * 100, 'parent_id' => $request->input('parent') ?: null, 'task_type' => $request->input('type', 'task'), 'sortorder' => (PpTask::where('project_id', $project_id)->max('sortorder') ?? 0) + 1, 'position' => $this->ppUtil->getNextKanbanPosition($status_id), 'created_by' => auth()->user()->id, ]); PpProject::find($project_id)?->recalculateProgress(); return response()->json([ 'action' => 'inserted', 'tid' => $task->id, ]); } public function updateTask(Request $request, $id) { $business_id = $request->session()->get('user.business_id'); $this->authorizeModule($business_id); $task = PpTask::where('business_id', $business_id)->findOrFail($id); $data = []; if ($request->has('text')) { $data['title'] = $request->input('text'); } if ($request->has('start_date')) { $data['start_date'] = $this->normalizeStartDate($request->input('start_date')); } if ($request->has('duration')) { $data['duration'] = max(1, (int) $request->input('duration')); if (! empty($data['start_date'])) { $data['due_date'] = \Carbon\Carbon::parse($data['start_date'])->addDays($data['duration']); } } if ($request->has('progress')) { $data['progress'] = $request->input('progress') * 100; } if ($request->has('parent')) { $data['parent_id'] = $request->input('parent') ?: null; } if ($request->has('sortorder')) { $data['sortorder'] = $request->input('sortorder'); } $task->update($data); $task->project->recalculateProgress(); return response()->json(['action' => 'updated']); } public function destroyTask($id) { $business_id = request()->session()->get('user.business_id'); $this->authorizeModule($business_id); $task = PpTask::where('business_id', $business_id)->findOrFail($id); $project = $task->project; $task->delete(); $project?->recalculateProgress(); return response()->json(['action' => 'deleted']); } public function storeLink(Request $request) { $business_id = $request->session()->get('user.business_id'); $this->authorizeModule($business_id); $link = PpGanttLink::create([ 'project_id' => $request->input('project_id'), 'source_task_id' => $request->input('source'), 'target_task_id' => $request->input('target'), 'link_type' => $request->input('type', 0), ]); return response()->json(['action' => 'inserted', 'lid' => $link->id]); } public function updateLink(Request $request, $id) { $business_id = $request->session()->get('user.business_id'); $this->authorizeModule($business_id); $link = PpGanttLink::whereHas('project', fn ($q) => $q->where('business_id', $business_id))->findOrFail($id); $link->update([ 'source_task_id' => $request->input('source', $link->source_task_id), 'target_task_id' => $request->input('target', $link->target_task_id), 'link_type' => $request->input('type', $link->link_type), ]); return response()->json(['action' => 'updated']); } public function destroyLink($id) { $business_id = request()->session()->get('user.business_id'); $this->authorizeModule($business_id); PpGanttLink::whereHas('project', fn ($q) => $q->where('business_id', $business_id))->findOrFail($id)->delete(); return response()->json(['action' => 'deleted']); } }