feat(11-01): recalculate nextDueDate from today on non-due-day completion

- When completing on due date: use original due date as base (preserves rhythm)
- When completing on different day: use today as base (per D-02)
- Replace todayDateOnly with todayStart used for both base calculation and catch-up
- Update doc comment to reflect new behavior
This commit is contained in:
2026-03-24 09:47:49 +01:00
parent 3398acab33
commit c5ab052f9e

View File

@@ -35,8 +35,10 @@ class TasksDao extends DatabaseAccessor<AppDatabase> with _$TasksDaoMixin {
/// Mark a task as done: records completion and calculates next due date. /// Mark a task as done: records completion and calculates next due date.
/// ///
/// Uses scheduling utility for date calculation. Next due is calculated /// Uses scheduling utility for date calculation. If completing on the due
/// from the original due date (not completion date) to keep rhythm stable. /// date, next due is calculated from the original due date (keeps rhythm).
/// If completing on a different day (early or late), next due is calculated
/// from today (per D-02: matches user mental model "I did it now, schedule next from now").
/// If the calculated next due is in the past, catch-up advances to present. /// If the calculated next due is in the past, catch-up advances to present.
/// ///
/// [now] parameter allows injection of current time for testing. /// [now] parameter allows injection of current time for testing.
@@ -54,23 +56,24 @@ class TasksDao extends DatabaseAccessor<AppDatabase> with _$TasksDaoMixin {
completedAt: currentTime, completedAt: currentTime,
)); ));
// 3. Calculate next due date (from original due date, not today) // 3. Calculate next due date
// If completing on the due date, use original due date as base (keeps rhythm).
// If completing on a different day (early or late), use today as base (per D-02).
final todayStart = DateTime(currentTime.year, currentTime.month, currentTime.day);
final taskDueDay = DateTime(task.nextDueDate.year, task.nextDueDate.month, task.nextDueDate.day);
final baseDate = todayStart == taskDueDay ? task.nextDueDate : todayStart;
var nextDue = calculateNextDueDate( var nextDue = calculateNextDueDate(
currentDueDate: task.nextDueDate, currentDueDate: baseDate,
intervalType: task.intervalType, intervalType: task.intervalType,
intervalDays: task.intervalDays, intervalDays: task.intervalDays,
anchorDay: task.anchorDay, anchorDay: task.anchorDay,
); );
// 4. Catch up if next due is still in the past // 4. Catch up if next due is still in the past
final todayDateOnly = DateTime(
currentTime.year,
currentTime.month,
currentTime.day,
);
nextDue = catchUpToPresent( nextDue = catchUpToPresent(
nextDue: nextDue, nextDue: nextDue,
today: todayDateOnly, today: todayStart,
intervalType: task.intervalType, intervalType: task.intervalType,
intervalDays: task.intervalDays, intervalDays: task.intervalDays,
anchorDay: task.anchorDay, anchorDay: task.anchorDay,