Skip to content

Commit c4531da

Browse files
IAMSamuelRoddaclaude
andcommitted
fix(repeat): restore no-op behavior for repeating tasks without due date
Repeating tasks without a due date should not get one auto-assigned when marked as done. This restores the upstream behavior where repeat + no due date = no-op. Addresses maintainer review comment on PR go-vikunja#2032. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f3073a5 commit c4531da

File tree

2 files changed

+9
-9
lines changed

2 files changed

+9
-9
lines changed

pkg/models/tasks.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,13 +1544,10 @@ func setTaskDatesRRule(oldTask, newTask *Task) {
15441544
var timeDiff time.Duration
15451545
if !oldTask.DueDate.IsZero() {
15461546
timeDiff = nextOccurrence.Sub(oldTask.DueDate)
1547+
newTask.DueDate = nextOccurrence
15471548
} else {
1548-
// No due date, calculate diff from the base date used for rule generation
15491549
timeDiff = nextOccurrence.Sub(baseDate)
15501550
}
1551-
// Always set the due date for repeating tasks - if there was no due date,
1552-
// the next occurrence becomes the new due date
1553-
newTask.DueDate = nextOccurrence
15541551

15551552
// Update reminders with the same time difference
15561553
newTask.Reminders = oldTask.Reminders

pkg/models/tasks_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ func TestUpdateDone(t *testing.T) {
633633
assert.True(t, newTask.DueDate.After(time.Now()) || newTask.DueDate.Equal(time.Now().Truncate(24*time.Hour)))
634634
assert.False(t, newTask.Done)
635635
})
636-
t.Run("set due date if old task had no due date", func(t *testing.T) {
636+
t.Run("no due date is a no-op", func(t *testing.T) {
637637
oldTask := &Task{
638638
Done: false,
639639
Repeats: "FREQ=DAILY;INTERVAL=1",
@@ -643,17 +643,16 @@ func TestUpdateDone(t *testing.T) {
643643
Done: true,
644644
}
645645
updateDone(oldTask, newTask)
646-
// Even if old task had no due date, new task should get one (next occurrence from now)
647-
assert.False(t, newTask.DueDate.IsZero(), "due date should be set for repeating task")
648-
assert.True(t, newTask.DueDate.After(time.Now().Add(-time.Minute)), "due date should be in the future (or very recent)")
649-
assert.False(t, newTask.Done)
646+
// Repeating task without a due date should not get one auto-assigned
647+
assert.True(t, newTask.DueDate.IsZero(), "due date should remain unset")
650648
})
651649
t.Run("update reminders", func(t *testing.T) {
652650
oldReminder1 := time.Now().Add(-48 * time.Hour)
653651
oldReminder2 := time.Now().Add(-24 * time.Hour)
654652
oldTask := &Task{
655653
Done: false,
656654
Repeats: "FREQ=DAILY;INTERVAL=1",
655+
DueDate: time.Now().Add(-48 * time.Hour),
657656
Reminders: []*TaskReminder{
658657
{
659658
Reminder: oldReminder1,
@@ -679,6 +678,7 @@ func TestUpdateDone(t *testing.T) {
679678
oldTask := &Task{
680679
Done: false,
681680
Repeats: "FREQ=DAILY;INTERVAL=1",
681+
DueDate: time.Now().Add(-48 * time.Hour),
682682
StartDate: oldStartDate,
683683
}
684684
newTask := &Task{
@@ -694,6 +694,7 @@ func TestUpdateDone(t *testing.T) {
694694
oldTask := &Task{
695695
Done: false,
696696
Repeats: "FREQ=DAILY;INTERVAL=1",
697+
DueDate: time.Now().Add(-48 * time.Hour),
697698
EndDate: oldEndDate,
698699
}
699700
newTask := &Task{
@@ -788,6 +789,7 @@ func TestUpdateDone(t *testing.T) {
788789
oldTask := &Task{
789790
Done: false,
790791
Repeats: "FREQ=MONTHLY;INTERVAL=1",
792+
DueDate: time.Unix(1550000000, 0),
791793
StartDate: time.Unix(1550000000, 0),
792794
}
793795
newTask := &Task{
@@ -804,6 +806,7 @@ func TestUpdateDone(t *testing.T) {
804806
oldTask := &Task{
805807
Done: false,
806808
Repeats: "FREQ=MONTHLY;INTERVAL=1",
809+
DueDate: time.Unix(1560000000, 0),
807810
EndDate: time.Unix(1560000000, 0),
808811
}
809812
newTask := &Task{

0 commit comments

Comments
 (0)