diff --git a/pkg/models/task_collection_subtasks_move_test.go b/pkg/models/task_collection_subtasks_move_test.go new file mode 100644 index 000000000..0b30bb469 --- /dev/null +++ b/pkg/models/task_collection_subtasks_move_test.go @@ -0,0 +1,80 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-present Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package models + +import ( + "testing" + + "code.vikunja.io/api/pkg/db" + "code.vikunja.io/api/pkg/user" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTaskCollection_SubtaskRemainsAfterMove(t *testing.T) { + db.LoadAndAssertFixtures(t) + s := db.NewSession() + defer s.Close() + + u := &user.User{ID: 1} + + c := &TaskCollection{ + ProjectID: 1, + Expand: []TaskCollectionExpandable{TaskCollectionExpandSubtasks}, + } + + res, _, _, err := c.ReadAll(s, u, "", 0, 50) + require.NoError(t, err) + tasks, ok := res.([]*Task) + require.True(t, ok) + + found := false + for _, tsk := range tasks { + if tsk.ID == 29 { + found = true + break + } + } + assert.True(t, found, "subtask should be returned before moving") + + subtask := &Task{ID: 29, ProjectID: 7} + err = subtask.Update(s, u) + require.NoError(t, err) + require.NoError(t, s.Commit()) + + s2 := db.NewSession() + defer s2.Close() + c = &TaskCollection{ + ProjectID: 7, + Expand: []TaskCollectionExpandable{TaskCollectionExpandSubtasks}, + } + + res, _, _, err = c.ReadAll(s2, u, "", 0, 50) + require.NoError(t, err) + tasks, ok = res.([]*Task) + require.True(t, ok) + + found = false + for _, tsk := range tasks { + if tsk.ID == 29 { + found = true + break + } + } + assert.True(t, found, "subtask should be returned after moving to another project") +} diff --git a/pkg/models/task_search.go b/pkg/models/task_search.go index a8baf3280..07aec884f 100644 --- a/pkg/models/task_search.go +++ b/pkg/models/task_search.go @@ -294,7 +294,7 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo var projectIDCond builder.Cond var favoritesCond builder.Cond if len(opts.projectIDs) > 0 { - projectIDCond = builder.In("project_id", opts.projectIDs) + projectIDCond = builder.In("tasks.project_id", opts.projectIDs) } if d.hasFavoritesProject { @@ -328,7 +328,10 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo } if expandSubtasks { - cond = builder.And(cond, builder.IsNull{"task_relations.id"}) + cond = builder.And(cond, builder.Or( + builder.IsNull{"task_relations.id"}, + builder.Expr("parent_tasks.project_id != tasks.project_id"), + )) } query := d.s. @@ -349,7 +352,9 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo query = query.Join("LEFT", "task_buckets", "task_buckets.task_id = tasks.id") } if expandSubtasks { - query = query.Join("LEFT", "task_relations", "tasks.id = task_relations.task_id and task_relations.relation_kind = 'parenttask'") + query = query. + Join("LEFT", "task_relations", "tasks.id = task_relations.task_id and task_relations.relation_kind = 'parenttask'"). + Join("LEFT", "tasks parent_tasks", "task_relations.other_task_id = parent_tasks.id") } tasks = []*Task{} @@ -416,7 +421,9 @@ func (d *dbTaskSearcher) Search(opts *taskSearchOptions) (tasks []*Task, totalCo queryCount = queryCount.Join("LEFT", "task_buckets", "task_buckets.task_id = tasks.id") } if expandSubtasks { - queryCount = queryCount.Join("LEFT", "task_relations", "tasks.id = task_relations.task_id and task_relations.relation_kind = 'parenttask'") + queryCount = queryCount. + Join("LEFT", "task_relations", "tasks.id = task_relations.task_id and task_relations.relation_kind = 'parenttask'"). + Join("LEFT", "tasks parent_tasks", "task_relations.other_task_id = parent_tasks.id") } totalCount, err = queryCount. Select("count(DISTINCT tasks.id)").