'(SOLVED) How to update parent model in laravel?

[SOLVED] /*** The parent-children relationship works fine. But there was a code i wrote several weeks ago that prevent me to update the progress value. ***/

I have a project that has similar functionality to trello (kanban) There are 3 models which are projects, TaskList (columns), Tasks (cards).

  • a project has many columns

  • a column has many tasks

  • a task has many

    subtasks (the subtask refer to the model itself)

each model has a column named progress. This column must be updated when the children are updated. The progress is calculated by averaging the progress of all cards.

Models : Project.php


class Project extends Model
{
    use HasFactory;

    protected $table = 'projects';

    public $timestamps = true;

    protected $fillable = [
        'id','title', 'description', 'actual_start', 'actual_end',
        'start', 'end','progress'
    ];

    public function updateProgress(){      
        $sum=0;
        if(count($this->columns)){
            for ($i = 0; $i < count($this->columns); $i++) {
                $list = $this->columns[$i];
                if($list->progress==null){
                    $list->progress=0;
                }
                $sum+=$list->progress;
            }
            $progress=$sum/count($this->columns);
            $this->progress=round($progress);
            $this->save();
        }
        return $this->progress;
    }
    
    public function scopeExclude($query, $value = []) 
    {
        return $query->select(array_diff($this->fillable, (array) $value));
    }

    public function lists(){
        return $this->hasMany(TaskList::class,'projects_id');
    }

TaskList.php

class TaskList extends Model
{
    protected $table = 'lists';
    
    protected $fillable = [ 'title', 'position', 'projects_id', 'start', 'end', 'actual_start', 'actual_end','progress' ];

    public static function boot() {
        parent::boot();

        static::saved(function($list){
            $list->project->updateProgress();
        });
    }

    public function updateProgress(){      
        $tes=[];
        if(count($this->cards)){
            $sum=0;
            for ($i = 0; $i < count($this->cards); $i++) {
                $task = $this->cards[$i];
                if($task->progress==null){
                    $task->progress=0;
                }
                $sum+=$task->progress;
                $tes[]=['id'=>$task->id,'progress'=>$task->progress,$task->cards];
            }
            $progress=$sum/count($this->cards);
            $this->progress=round($progress);
            $this->save();
        }
        return ['id'=>$this->id,'progress'=>$this->progress,'cards'=>$this->cards];
    }

    
    public function cards(){
        return $this->hasMany(Task::class,'lists_id');
    }
}

Task.php


class Task extends Model
{
    use HasFactory;
    
    protected $table = 'tasks';

    public $timestamps = true;

    protected $fillable = [
        'id','users_id', 'title', 'description', 'complete', 'end', 'start',
        'actual_start', 'actual_end', 'start_label', 'end_label', 
        'progress', 'is_subtask', 'lists_id','parent_task_id'
    ];

    protected $casts = [
        'progress' => 'double',
    ];
    
    public static function boot() {
        parent::boot();
        static::saving(function($task){
            if(!empty($task->start)  && !empty($task->end)){
                $start = Carbon::parse($task->start);
                $end = Carbon::parse($task->end);
                $days= $start->diffInDays($end);
                $task->days=$days+1;
            }       

            if(!empty($task->actual_start) && !empty($task->actual_end)){
                $actual_start = Carbon::parse($task->actual_start);
                $actual_end = Carbon::parse($task->actual_end);
                $work_days= $actual_start->diffInDays($actual_end);
                $task->work_days=$work_days+1;
            }
   

            // This part was the problem           
            if($task->parentTask){
                if($task->actual_end){
                    $task->progress=100;
                }else{
                    $task->progress=0;
                }
            }else{
                if($task->actual_end){
                    $task->progress=100;
                }else{
                    $task->progress=0;
                }
            }         
            if($task->parentTask){
                if($task->actual_end){
                    $task->progress=100;
                }else{
                    $task->progress=0;
                }
            }else{
                if($task->actual_end){
                    $task->progress=100;
                }else{
                    $task->progress=0;
                }
            }

            //------------------------
            if($task->progress==100){
                $task->complete=true;
            }
            
            
        });
        
        static::saved(function($task){
            //is a subtask
            if($task->parentTask){
                // dd('subtask',$task->id,$task->complete,$task->progress,$task->parentTask,$task->list);
                $task->parentTask->updateProgress();
            }else{
                // dd('parent task',$task->id,$task->complete,$task->progress,$task->parentTask,$task->list);
                $task->list->updateProgress();
                // dd('list ',$task->list->updateProgress());
            }
        });

        static::deleting(function($task) { 
            foreach ($task->members as $i => $member) {
                $member->delete();
            }
            foreach ($task->cards as $k => $subtask) {
                $subtask->delete();
            }
            $task->tags()->detach();
            $task->task_members()->detach();
        });
    }

    public function updateProgress(){      
        if(count($this->cards)){
            $valuePerSubtask=100/count($this->cards);
            $completeSubtaskCounter=0;
            for ($i = 0; $i < count($this->cards); $i++) {
                $subtask = $this->cards[$i];
                if($subtask->complete){ 
                    $completeSubtaskCounter++; 
                }
            }
            $progress=$completeSubtaskCounter*$valuePerSubtask;
            $this->progress=$progress;
            $this->save();
            return [$this->progress,$progress];
        }
    }

    public function scopeExclude($query, $value = []) 
    {
        return $query->select(array_diff($this->fillable, (array) $value));
    }
    
   
    public function parentTask(){
        return $this->belongsTo(Task::class,'parent_task_id');
    }

    public function list(){
        return $this->belongsTo(TaskList::class,'lists_id');
    }
 
}


I can't update the parent task from the children. As you can see in Task.php model, I have a updateProgress() that return [$this->progress, $progress]; after i call $this->save(). I already have $this->progress=$progress before i save it. But $this->progress still show the same result.

[![the first item is $this->progress, the second one is $progress][1]][1] [1]: https://i.stack.imgur.com/RS2mq.png

i tried override touch() and place updateProgress() inside it. But still doesn't show the expected result.

Any advice for a better approach? Am I missing something?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source