feat(08-01): add isActive filters to CalendarDao, DailyPlanDao, RoomsDao

- CalendarDao: filter all 6 task queries (watchTasksForDate,
  watchTasksForDateInRoom, watchOverdueTasks, watchOverdueTasksInRoom,
  getTaskCount, getTaskCountInRoom) by isActive=true
- DailyPlanDao: filter all 3 queries (watchAllTasksWithRoomName,
  getOverdueAndTodayTaskCount, getOverdueTaskCount) by isActive=true
- RoomsDao: filter watchRoomWithStats task query by isActive=true
- Update migration test: add schema_v3.dart, test v1->v3 and v2->v3 paths
- Update database_test schemaVersion assertion to expect 3
- Fix test helpers in home_screen_test and task_list_screen_test to pass isActive=true
This commit is contained in:
2026-03-18 20:56:34 +01:00
parent 4b51f5fa04
commit b2f14dcd97
10 changed files with 694 additions and 47 deletions

View File

@@ -10,13 +10,14 @@ class DailyPlanDao extends DatabaseAccessor<AppDatabase>
with _$DailyPlanDaoMixin {
DailyPlanDao(super.attachedDatabase);
/// Watch all tasks joined with room name, sorted by nextDueDate ascending.
/// Includes ALL tasks (overdue, today, future) -- filtering is done in the
/// provider layer to avoid multiple queries.
/// Watch all active tasks joined with room name, sorted by nextDueDate ascending.
/// Includes overdue, today, and future tasks -- filtering is done in the
/// provider layer to avoid multiple queries. Excludes soft-deleted tasks.
Stream<List<TaskWithRoom>> watchAllTasksWithRoomName() {
final query = select(tasks).join([
innerJoin(rooms, rooms.id.equalsExp(tasks.roomId)),
]);
query.where(tasks.isActive.equals(true));
query.orderBy([OrderingTerm.asc(tasks.nextDueDate)]);
return query.watch().map((rows) {
@@ -32,24 +33,30 @@ class DailyPlanDao extends DatabaseAccessor<AppDatabase>
});
}
/// One-shot count of overdue + today tasks (for notification body).
/// One-shot count of overdue + today active tasks (for notification body).
Future<int> getOverdueAndTodayTaskCount({DateTime? today}) async {
final now = today ?? DateTime.now();
final endOfToday = DateTime(now.year, now.month, now.day + 1);
final result = await (selectOnly(tasks)
..addColumns([tasks.id.count()])
..where(tasks.nextDueDate.isSmallerThanValue(endOfToday)))
..where(
tasks.nextDueDate.isSmallerThanValue(endOfToday) &
tasks.isActive.equals(true),
))
.getSingle();
return result.read(tasks.id.count()) ?? 0;
}
/// One-shot count of overdue tasks only (for notification body split).
/// One-shot count of overdue active tasks only (for notification body split).
Future<int> getOverdueTaskCount({DateTime? today}) async {
final now = today ?? DateTime.now();
final startOfToday = DateTime(now.year, now.month, now.day);
final result = await (selectOnly(tasks)
..addColumns([tasks.id.count()])
..where(tasks.nextDueDate.isSmallerThanValue(startOfToday)))
..where(
tasks.nextDueDate.isSmallerThanValue(startOfToday) &
tasks.isActive.equals(true),
))
.getSingle();
return result.read(tasks.id.count()) ?? 0;
}