fix(kanban): repeating tasks dates won't update when moved in done bucket (#1638)

This commit is contained in:
Biagio00
2025-11-14 17:57:53 +01:00
committed by GitHub
parent 28d96d5a84
commit 5b42724205
6 changed files with 40 additions and 10 deletions

View File

@@ -226,7 +226,7 @@
updated: 2018-12-01 01:12:04
start_date: 2018-11-30 22:25:24
- id: 28
title: 'task #28 with repeat after'
title: 'task #28 with repeat after, start_date, end_date and due_date'
done: false
created_by_id: 1
repeat_after: 3600
@@ -234,6 +234,9 @@
index: 13
created: 2018-12-01 01:12:04
updated: 2018-12-01 01:12:04
due_date: 2018-12-02 22:25:24
start_date: 2018-11-30 22:25:24
end_date: 2018-12-13 11:20:00
- id: 29
title: 'task #29 with parent task (1)'
done: false

View File

@@ -157,9 +157,9 @@ func (b *TaskBucket) Update(s *xorm.Session, a web.Auth) (err error) {
doneChanged = true
task.Done = true
if task.isRepeating() {
oldTask := task
oldTask := *task
oldTask.Done = false
updateDone(oldTask, task)
updateDone(&oldTask, task)
updateBucket = false
b.BucketID = oldTaskBucket.BucketID
}

View File

@@ -141,7 +141,21 @@ func TestTaskBucket_Update(t *testing.T) {
ProjectViewID: 4,
ProjectID: 1, // In actual web requests set via the url
}
err := tb.Update(s, u)
// Before running the TaskBucket Update we retrieve the task and execute
// an updateDone to obtain the task with updated start/end/due dates
// This way we can later match them with what happens after running TaskBucket Update
u := &user.User{ID: 1}
oldTask := &Task{ID: tb.TaskID}
err := oldTask.ReadOne(s, u)
require.NoError(t, err)
updatedTask := &Task{ID: tb.TaskID}
err = updatedTask.ReadOne(s, u)
require.NoError(t, err)
updatedTask.Done = true
updateDone(oldTask, updatedTask) // updatedTask now contains the updated dates
err = tb.Update(s, u)
require.NoError(t, err)
err = s.Commit()
require.NoError(t, err)
@@ -156,6 +170,10 @@ func TestTaskBucket_Update(t *testing.T) {
"task_id": 1,
"bucket_id": 1,
}, false)
assert.Equal(t, updatedTask.DueDate.Unix(), tb.Task.DueDate.Unix())
assert.Equal(t, updatedTask.StartDate.Unix(), tb.Task.StartDate.Unix())
assert.Equal(t, updatedTask.EndDate.Unix(), tb.Task.EndDate.Unix())
})
t.Run("keep done timestamp when moving task between projects", func(t *testing.T) {

View File

@@ -502,7 +502,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
}
task28 := &Task{
ID: 28,
Title: "task #28 with repeat after",
Title: "task #28 with repeat after, start_date, end_date and due_date",
Identifier: "test1-13",
Index: 13,
CreatedByID: 1,
@@ -512,6 +512,9 @@ func TestTaskCollection_ReadAll(t *testing.T) {
RepeatAfter: 3600,
Created: time.Unix(1543626724, 0).In(loc),
Updated: time.Unix(1543626724, 0).In(loc),
DueDate: time.Unix(1543789524, 0).In(loc),
StartDate: time.Unix(1543616724, 0).In(loc),
EndDate: time.Unix(1544700000, 0).In(loc),
}
task29 := &Task{
ID: 29,
@@ -832,6 +835,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
task7,
task8,
task9,
task28,
},
wantErr: false,
},
@@ -844,6 +848,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
want: []*Task{
task8,
task9,
task28,
},
wantErr: false,
},
@@ -890,6 +895,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
task7,
task8,
task9,
task28,
},
wantErr: false,
},
@@ -1500,6 +1506,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
// The only tasks with a due date
task6,
task5,
task28,
// The other ones don't have a due date
task39,
task35,
@@ -1508,7 +1515,6 @@ func TestTaskCollection_ReadAll(t *testing.T) {
task31,
task30,
task29,
task28,
task27,
task26,
task25,
@@ -1550,6 +1556,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
task7,
task6,
task5,
task28,
},
},
{
@@ -1563,6 +1570,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
a: &user.User{ID: 1},
},
want: []*Task{
task28,
task5,
task6,
task7,
@@ -1583,6 +1591,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
want: []*Task{
task6,
task5,
task28,
task7,
task8,
task9,

View File

@@ -1570,7 +1570,7 @@ func setTaskDatesFromCurrentDateRepeat(oldTask, newTask *Task) {
newTask.Done = false
}
// This helper function updates the reminders, doneAt, start and end dates of the *old* task
// This helper function updates the reminders, doneAt, start, end and due dates of the *old* task
// and saves the new values in the newTask object.
// We make a few assumptions here:
// 1. Everything in oldTask is the truth - we figure out if we update anything at all if oldTask.RepeatAfter has a value > 0

View File

@@ -136,7 +136,7 @@ func TestTaskCollection(t *testing.T) {
t.Run("by duedate desc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, urlParams)
require.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
assert.Contains(t, rec.Body.String(), `[{"id":28,"title":"task #28 with repeat after, start_date, end_date and due_date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-02T22:25:24Z","reminders":null,"project_id":1,"repeat_after":3600,"repeat_mode":0,"priority":0,"start_date":"2018-11-30T22:25:24Z","end_date":"2018-12-13T11:20:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-13","index":13,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
})
// Due date without unix suffix
t.Run("by duedate asc without suffix", func(t *testing.T) {
@@ -152,7 +152,7 @@ func TestTaskCollection(t *testing.T) {
t.Run("by duedate desc without suffix", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, urlParams)
require.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
assert.Contains(t, rec.Body.String(), `[{"id":28,"title":"task #28 with repeat after, start_date, end_date and due_date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-02T22:25:24Z","reminders":null,"project_id":1,"repeat_after":3600,"repeat_mode":0,"priority":0,"start_date":"2018-11-30T22:25:24Z","end_date":"2018-12-13T11:20:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-13","index":13,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
})
t.Run("by duedate asc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, urlParams)
@@ -379,7 +379,7 @@ func TestTaskCollection(t *testing.T) {
t.Run("by duedate desc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, nil)
require.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
assert.Contains(t, rec.Body.String(), `[{"id":28,"title":"task #28 with repeat after, start_date, end_date and due_date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-02T22:25:24Z","reminders":null,"project_id":1,"repeat_after":3600,"repeat_mode":0,"priority":0,"start_date":"2018-11-30T22:25:24Z","end_date":"2018-12-13T11:20:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-13","index":13,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminders":null,"project_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"cover_image_attachment_id":0,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":0,"position":0,"reactions":null,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
})
t.Run("by duedate asc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, nil)