'array', 'progress_manual' => 'boolean', 'is_archived' => 'boolean', 'is_locked' => 'boolean', 'start_date' => 'datetime', 'end_date' => 'datetime', ]; public function members() { return $this->belongsToMany(\App\User::class, 'pp_project_members', 'project_id', 'user_id'); } public function createdBy() { return $this->belongsTo(\App\User::class, 'created_by'); } public function lead() { return $this->belongsTo(\App\User::class, 'lead_id'); } public function manager() { return $this->belongsTo(\App\User::class, 'manager_id'); } public function supervisors() { return $this->belongsToMany(\App\User::class, 'pp_project_supervisors', 'project_id', 'user_id'); } public function parents() { return $this->belongsToMany(self::class, 'pp_project_parents', 'project_id', 'parent_id'); } public function customer() { return $this->belongsTo(\App\Contact::class, 'contact_id'); } public function tasks() { return $this->hasMany(PpTask::class, 'project_id'); } public function milestones() { return $this->hasMany(PpMilestone::class, 'project_id'); } public function parent() { return $this->belongsTo(self::class, 'parent_id'); } public function children() { return $this->hasMany(self::class, 'parent_id'); } public function categories() { return $this->belongsToMany(PpProjectCategory::class, 'pp_project_category', 'project_id', 'category_id'); } public function scopeInCategory($query, $category_id) { return $query->whereHas('categories', fn ($q) => $q->where('pp_project_categories.id', $category_id)); } public function scopeUncategorized($query) { return $query->whereDoesntHave('categories'); } public function ganttLinks() { return $this->hasMany(PpGanttLink::class, 'project_id'); } public static function statusDropdown() { return [ 'not_started' => __('professionalproject::lang.not_started'), 'in_progress' => __('professionalproject::lang.in_progress'), 'on_hold' => __('professionalproject::lang.on_hold'), 'cancelled' => __('professionalproject::lang.cancelled'), 'completed' => __('professionalproject::lang.completed'), ]; } public static function projectDropdown($business_id, $user_id = null, $category_id = null) { $query = self::where('business_id', $business_id)->where('is_archived', false); if (! empty($user_id)) { $query->where(function ($q) use ($user_id) { $q->where('lead_id', $user_id) ->orWhereHas('members', fn ($m) => $m->where('user_id', $user_id)); }); } if (! empty($category_id) && $category_id !== 'all') { if ($category_id === 'uncategorized') { $query->uncategorized(); } else { $query->inCategory((int) $category_id); } } return $query->orderBy('name')->pluck('name', 'id'); } public function recalculateProgress() { if ($this->progress_manual) { return; } $total = $this->tasks()->count(); if ($total === 0) { $this->update(['progress' => 0]); return; } $completedStatusIds = PpTaskStatus::where('business_id', $this->business_id) ->where('is_completed', true) ->pluck('id'); $completed = $this->tasks()->whereIn('status_id', $completedStatusIds)->count(); $this->update(['progress' => round(($completed / $total) * 100, 2)]); } }