commonUtil = $commonUtil; $this->ppUtil = $ppUtil; $this->moduleUtil = $moduleUtil; } protected function authorizeModule() { $business_id = request()->session()->get('user.business_id'); if (! (auth()->user()->can('superadmin') || $this->moduleUtil->hasThePermissionInSubscription($business_id, 'professional_project_module'))) { abort(403, 'Unauthorized action.'); } if (! auth()->user()->can('professionalproject.access')) { abort(403, 'Unauthorized action.'); } } public function index() { $this->authorizeModule(); $business_id = request()->session()->get('user.business_id'); $is_admin = $this->commonUtil->is_admin(auth()->user(), $business_id); $this->ppUtil->ensureTaskStatuses($business_id, auth()->user()->id); $view = request()->get('view', 'kanban'); $project_id = request()->get('project_id'); $statuses = PpTaskStatus::where('business_id', $business_id)->orderBy('position')->get(); $projects = PpProject::projectDropdown($business_id, $is_admin ? null : auth()->user()->id); $priorities = PpTask::priorityDropdown(); if (request()->ajax()) { if ($view === 'kanban') { $boards = []; foreach ($statuses as $status) { $query = PpTask::with(['assignees', 'project', 'milestone']) ->where('business_id', $business_id) ->where('status_id', $status->id); if ($project_id) { $query->where('project_id', $project_id); } if (! $is_admin && ! $project_id) { $query->whereHas('assignees', fn ($q) => $q->where('user_id', auth()->user()->id)); } $boards[$status->id] = $query->orderBy('position')->get(); } return view('professionalproject::task.partials.kanban') ->with(compact('boards', 'statuses', 'priorities')) ->render(); } $query = PpTask::with(['assignees', 'project', 'status', 'milestone']) ->where('business_id', $business_id); if ($project_id) { $query->where('project_id', $project_id); } return DataTables::of($query) ->addColumn('action', function ($row) { $html = ''; if (auth()->user()->can('professionalproject.edit_task')) { $html .= ' '; } if (auth()->user()->can('professionalproject.delete_task')) { $html .= ''; } return $html; }) ->editColumn('priority', function ($row) { $colors = PpTask::priorityColors(); return ''.PpTask::priorityDropdown()[$row->priority].''; }) ->editColumn('status_id', function ($row) { return $row->status ? $row->status->title : ''; }) ->rawColumns(['action', 'priority']) ->make(true); } return view('professionalproject::task.index') ->with(compact('view', 'statuses', 'projects', 'project_id', 'priorities')); } public function create() { $this->authorizeModule(); if (! auth()->user()->can('professionalproject.create_task')) { abort(403, 'Unauthorized action.'); } $business_id = request()->session()->get('user.business_id'); $project_id = request()->get('project_id'); $projects = PpProject::projectDropdown($business_id); $users = User::forDropdown($business_id, false); $statuses = PpTaskStatus::where('business_id', $business_id)->orderBy('position')->pluck('title', 'id'); $priorities = PpTask::priorityDropdown(); $milestones = $project_id ? \Modules\ProfessionalProject\Entities\PpMilestone::where('project_id', $project_id)->pluck('title', 'id') : collect(); return view('professionalproject::task.create') ->with(compact('projects', 'users', 'statuses', 'priorities', 'project_id', 'milestones')); } public function store(Request $request) { $this->authorizeModule(); if (! auth()->user()->can('professionalproject.create_task')) { abort(403, 'Unauthorized action.'); } try { $business_id = $request->session()->get('user.business_id'); $project_id = $request->input('project_id'); $status_id = $request->input('status_id') ?: $this->ppUtil->getDefaultTaskStatusId($business_id); $milestone_id = $request->input('milestone_id'); if (empty($milestone_id)) { $milestone = $this->ppUtil->ensureUncategorisedMilestone($business_id, $project_id, auth()->user()->id); $milestone_id = $milestone->id; } $task = PpTask::create([ 'business_id' => $business_id, 'project_id' => $project_id, 'milestone_id' => $milestone_id, 'title' => $request->input('title'), 'description' => $request->input('description'), 'status_id' => $status_id, 'priority' => $request->input('priority', 'normal'), 'start_date' => $this->commonUtil->uf_date($request->input('start_date'), true), 'due_date' => $this->commonUtil->uf_date($request->input('due_date'), true), 'duration' => $request->input('duration', 1), 'position' => $this->ppUtil->getNextKanbanPosition($status_id), 'sortorder' => (PpTask::where('project_id', $project_id)->max('sortorder') ?? 0) + 1, 'created_by' => auth()->user()->id, ]); $task->assignees()->sync($request->input('user_id', [])); $this->ppUtil->notifyUsersAboutAssignedTask( $request->input('user_id', []), $task, $request->user()->user_full_name ?? $request->user()->username ); $project = PpProject::find($project_id); if ($project) { $project->recalculateProgress(); } $output = ['success' => true, 'msg' => __('lang_v1.success')]; } catch (\Exception $e) { \Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage()); $output = ['success' => false, 'msg' => __('messages.something_went_wrong')]; } if ($request->ajax()) { return $output; } return redirect()->back()->with('status', $output); } public function edit($id) { $this->authorizeModule(); if (! auth()->user()->can('professionalproject.edit_task')) { abort(403, 'Unauthorized action.'); } $business_id = request()->session()->get('user.business_id'); $task = PpTask::with('assignees')->where('business_id', $business_id)->findOrFail($id); $projects = PpProject::projectDropdown($business_id); $users = User::forDropdown($business_id, false); $statuses = PpTaskStatus::where('business_id', $business_id)->orderBy('position')->pluck('title', 'id'); $priorities = PpTask::priorityDropdown(); $milestones = \Modules\ProfessionalProject\Entities\PpMilestone::where('project_id', $task->project_id)->pluck('title', 'id'); $project_tasks = PpTask::where('project_id', $task->project_id)->where('id', '!=', $id)->pluck('title', 'id'); $dependencies = PpTaskDependency::with('blocker')->where('task_id', $id)->get(); return view('professionalproject::task.edit') ->with(compact('task', 'projects', 'users', 'statuses', 'priorities', 'milestones', 'project_tasks', 'dependencies')); } public function update(Request $request, $id) { $this->authorizeModule(); if (! auth()->user()->can('professionalproject.edit_task')) { abort(403, 'Unauthorized action.'); } $business_id = $request->session()->get('user.business_id'); $task = PpTask::where('business_id', $business_id)->findOrFail($id); try { $new_status_id = $request->input('status_id', $task->status_id); $new_status = PpTaskStatus::find($new_status_id); if ($new_status && $new_status->is_completed && $this->ppUtil->hasActiveCannotCompleteDependencies($id)) { return ['success' => false, 'msg' => __('professionalproject::lang.dependency_blocks_complete')]; } $task->update([ 'title' => $request->input('title'), 'description' => $request->input('description'), 'project_id' => $request->input('project_id'), 'milestone_id' => $request->input('milestone_id'), 'status_id' => $new_status_id, 'priority' => $request->input('priority', 'normal'), 'start_date' => $this->commonUtil->uf_date($request->input('start_date'), true), 'due_date' => $this->commonUtil->uf_date($request->input('due_date'), true), 'duration' => $request->input('duration', $task->duration), 'progress' => $request->input('progress', $task->progress), ]); $syncResult = $task->assignees()->sync($request->input('user_id', [])); $attached = $syncResult['attached'] ?? []; if (! empty($attached)) { $this->ppUtil->notifyUsersAboutAssignedTask( $attached, $task, $request->user()->user_full_name ?? $request->user()->username ); } if ($new_status && $new_status->is_completed) { $this->ppUtil->fulfillDependenciesForTask($task->id); } $task->project->recalculateProgress(); $output = ['success' => true, 'msg' => __('lang_v1.success')]; } catch (\Exception $e) { $output = ['success' => false, 'msg' => __('messages.something_went_wrong')]; } if ($request->ajax()) { return $output; } return redirect()->back()->with('status', $output); } public function destroy($id) { $this->authorizeModule(); if (! auth()->user()->can('professionalproject.delete_task')) { abort(403, 'Unauthorized action.'); } $business_id = request()->session()->get('user.business_id'); $task = PpTask::where('business_id', $business_id)->findOrFail($id); $project = $task->project; try { $task->delete(); if ($project) { $project->recalculateProgress(); } $output = ['success' => true, 'msg' => __('lang_v1.success')]; } catch (\Exception $e) { $output = ['success' => false, 'msg' => __('messages.something_went_wrong')]; } return $output; } public function updateKanbanPosition(Request $request) { $this->authorizeModule(); $business_id = $request->session()->get('user.business_id'); $task = PpTask::where('business_id', $business_id)->findOrFail($request->input('task_id')); $new_status_id = $request->input('status_id'); $new_status = PpTaskStatus::find($new_status_id); if ($new_status && $new_status->is_completed && $this->ppUtil->hasActiveCannotCompleteDependencies($task->id)) { return ['success' => false, 'msg' => __('professionalproject::lang.dependency_blocks_complete')]; } $task->update([ 'status_id' => $new_status_id, 'position' => $request->input('position', $this->ppUtil->getNextKanbanPosition($new_status_id)), ]); if ($new_status && $new_status->is_completed) { $this->ppUtil->fulfillDependenciesForTask($task->id); } $task->project->recalculateProgress(); return ['success' => true, 'msg' => __('lang_v1.success')]; } public function storeDependency(Request $request) { $this->authorizeModule(); $business_id = $request->session()->get('user.business_id'); PpTaskDependency::create([ 'task_id' => $request->input('task_id'), 'blocker_task_id' => $request->input('blocker_task_id'), 'project_id' => $request->input('project_id'), 'dependency_type' => $request->input('dependency_type', 'cannot_start'), 'status' => 'active', 'created_by' => auth()->user()->id, ]); return ['success' => true, 'msg' => __('lang_v1.success')]; } public function destroyDependency($id) { $this->authorizeModule(); PpTaskDependency::findOrFail($id)->delete(); return ['success' => true, 'msg' => __('lang_v1.success')]; } public function getMilestonesByProject($project_id) { $milestones = \Modules\ProfessionalProject\Entities\PpMilestone::where('project_id', $project_id)->pluck('title', 'id'); return $milestones; } }