feat(08-01): add isActive column, migration v3, softDeleteTask and getCompletionCount

- Add isActive BoolColumn (default true) to Tasks table
- Bump schema version from 2 to 3 with addColumn migration
- Filter watchTasksInRoom to isActive=true only
- Filter getOverdueTaskCount to isActive=true only
- Add softDeleteTask(taskId) - sets isActive=false without removing data
- Add getCompletionCount(taskId) - counts TaskCompletions for a task
This commit is contained in:
2026-03-18 20:49:45 +01:00
parent a2cef91d7e
commit 4b51f5fa04
3 changed files with 98 additions and 6 deletions

View File

@@ -470,6 +470,21 @@ class $TasksTable extends Tasks with TableInfo<$TasksTable, Task> {
requiredDuringInsert: false,
clientDefault: () => DateTime.now(),
);
static const VerificationMeta _isActiveMeta = const VerificationMeta(
'isActive',
);
@override
late final GeneratedColumn<bool> isActive = GeneratedColumn<bool>(
'is_active',
aliasedName,
false,
type: DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints: GeneratedColumn.constraintIsAlways(
'CHECK ("is_active" IN (0, 1))',
),
defaultValue: const Constant(true),
);
@override
List<GeneratedColumn> get $columns => [
id,
@@ -482,6 +497,7 @@ class $TasksTable extends Tasks with TableInfo<$TasksTable, Task> {
effortLevel,
nextDueDate,
createdAt,
isActive,
];
@override
String get aliasedName => _alias ?? actualTableName;
@@ -555,6 +571,12 @@ class $TasksTable extends Tasks with TableInfo<$TasksTable, Task> {
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta),
);
}
if (data.containsKey('is_active')) {
context.handle(
_isActiveMeta,
isActive.isAcceptableOrUnknown(data['is_active']!, _isActiveMeta),
);
}
return context;
}
@@ -608,6 +630,10 @@ class $TasksTable extends Tasks with TableInfo<$TasksTable, Task> {
DriftSqlType.dateTime,
data['${effectivePrefix}created_at'],
)!,
isActive: attachedDatabase.typeMapping.read(
DriftSqlType.bool,
data['${effectivePrefix}is_active'],
)!,
);
}
@@ -633,6 +659,7 @@ class Task extends DataClass implements Insertable<Task> {
final EffortLevel effortLevel;
final DateTime nextDueDate;
final DateTime createdAt;
final bool isActive;
const Task({
required this.id,
required this.roomId,
@@ -644,6 +671,7 @@ class Task extends DataClass implements Insertable<Task> {
required this.effortLevel,
required this.nextDueDate,
required this.createdAt,
required this.isActive,
});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
@@ -670,6 +698,7 @@ class Task extends DataClass implements Insertable<Task> {
}
map['next_due_date'] = Variable<DateTime>(nextDueDate);
map['created_at'] = Variable<DateTime>(createdAt);
map['is_active'] = Variable<bool>(isActive);
return map;
}
@@ -689,6 +718,7 @@ class Task extends DataClass implements Insertable<Task> {
effortLevel: Value(effortLevel),
nextDueDate: Value(nextDueDate),
createdAt: Value(createdAt),
isActive: Value(isActive),
);
}
@@ -712,6 +742,7 @@ class Task extends DataClass implements Insertable<Task> {
),
nextDueDate: serializer.fromJson<DateTime>(json['nextDueDate']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
isActive: serializer.fromJson<bool>(json['isActive']),
);
}
@override
@@ -732,6 +763,7 @@ class Task extends DataClass implements Insertable<Task> {
),
'nextDueDate': serializer.toJson<DateTime>(nextDueDate),
'createdAt': serializer.toJson<DateTime>(createdAt),
'isActive': serializer.toJson<bool>(isActive),
};
}
@@ -746,6 +778,7 @@ class Task extends DataClass implements Insertable<Task> {
EffortLevel? effortLevel,
DateTime? nextDueDate,
DateTime? createdAt,
bool? isActive,
}) => Task(
id: id ?? this.id,
roomId: roomId ?? this.roomId,
@@ -757,6 +790,7 @@ class Task extends DataClass implements Insertable<Task> {
effortLevel: effortLevel ?? this.effortLevel,
nextDueDate: nextDueDate ?? this.nextDueDate,
createdAt: createdAt ?? this.createdAt,
isActive: isActive ?? this.isActive,
);
Task copyWithCompanion(TasksCompanion data) {
return Task(
@@ -780,6 +814,7 @@ class Task extends DataClass implements Insertable<Task> {
? data.nextDueDate.value
: this.nextDueDate,
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
isActive: data.isActive.present ? data.isActive.value : this.isActive,
);
}
@@ -795,7 +830,8 @@ class Task extends DataClass implements Insertable<Task> {
..write('anchorDay: $anchorDay, ')
..write('effortLevel: $effortLevel, ')
..write('nextDueDate: $nextDueDate, ')
..write('createdAt: $createdAt')
..write('createdAt: $createdAt, ')
..write('isActive: $isActive')
..write(')'))
.toString();
}
@@ -812,6 +848,7 @@ class Task extends DataClass implements Insertable<Task> {
effortLevel,
nextDueDate,
createdAt,
isActive,
);
@override
bool operator ==(Object other) =>
@@ -826,7 +863,8 @@ class Task extends DataClass implements Insertable<Task> {
other.anchorDay == this.anchorDay &&
other.effortLevel == this.effortLevel &&
other.nextDueDate == this.nextDueDate &&
other.createdAt == this.createdAt);
other.createdAt == this.createdAt &&
other.isActive == this.isActive);
}
class TasksCompanion extends UpdateCompanion<Task> {
@@ -840,6 +878,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
final Value<EffortLevel> effortLevel;
final Value<DateTime> nextDueDate;
final Value<DateTime> createdAt;
final Value<bool> isActive;
const TasksCompanion({
this.id = const Value.absent(),
this.roomId = const Value.absent(),
@@ -851,6 +890,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
this.effortLevel = const Value.absent(),
this.nextDueDate = const Value.absent(),
this.createdAt = const Value.absent(),
this.isActive = const Value.absent(),
});
TasksCompanion.insert({
this.id = const Value.absent(),
@@ -863,6 +903,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
required EffortLevel effortLevel,
required DateTime nextDueDate,
this.createdAt = const Value.absent(),
this.isActive = const Value.absent(),
}) : roomId = Value(roomId),
name = Value(name),
intervalType = Value(intervalType),
@@ -879,6 +920,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
Expression<int>? effortLevel,
Expression<DateTime>? nextDueDate,
Expression<DateTime>? createdAt,
Expression<bool>? isActive,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
@@ -891,6 +933,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
if (effortLevel != null) 'effort_level': effortLevel,
if (nextDueDate != null) 'next_due_date': nextDueDate,
if (createdAt != null) 'created_at': createdAt,
if (isActive != null) 'is_active': isActive,
});
}
@@ -905,6 +948,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
Value<EffortLevel>? effortLevel,
Value<DateTime>? nextDueDate,
Value<DateTime>? createdAt,
Value<bool>? isActive,
}) {
return TasksCompanion(
id: id ?? this.id,
@@ -917,6 +961,7 @@ class TasksCompanion extends UpdateCompanion<Task> {
effortLevel: effortLevel ?? this.effortLevel,
nextDueDate: nextDueDate ?? this.nextDueDate,
createdAt: createdAt ?? this.createdAt,
isActive: isActive ?? this.isActive,
);
}
@@ -957,6 +1002,9 @@ class TasksCompanion extends UpdateCompanion<Task> {
if (createdAt.present) {
map['created_at'] = Variable<DateTime>(createdAt.value);
}
if (isActive.present) {
map['is_active'] = Variable<bool>(isActive.value);
}
return map;
}
@@ -972,7 +1020,8 @@ class TasksCompanion extends UpdateCompanion<Task> {
..write('anchorDay: $anchorDay, ')
..write('effortLevel: $effortLevel, ')
..write('nextDueDate: $nextDueDate, ')
..write('createdAt: $createdAt')
..write('createdAt: $createdAt, ')
..write('isActive: $isActive')
..write(')'))
.toString();
}
@@ -1556,6 +1605,7 @@ typedef $$TasksTableCreateCompanionBuilder =
required EffortLevel effortLevel,
required DateTime nextDueDate,
Value<DateTime> createdAt,
Value<bool> isActive,
});
typedef $$TasksTableUpdateCompanionBuilder =
TasksCompanion Function({
@@ -1569,6 +1619,7 @@ typedef $$TasksTableUpdateCompanionBuilder =
Value<EffortLevel> effortLevel,
Value<DateTime> nextDueDate,
Value<DateTime> createdAt,
Value<bool> isActive,
});
final class $$TasksTableReferences
@@ -1668,6 +1719,11 @@ class $$TasksTableFilterComposer extends Composer<_$AppDatabase, $TasksTable> {
builder: (column) => ColumnFilters(column),
);
ColumnFilters<bool> get isActive => $composableBuilder(
column: $table.isActive,
builder: (column) => ColumnFilters(column),
);
$$RoomsTableFilterComposer get roomId {
final $$RoomsTableFilterComposer composer = $composerBuilder(
composer: this,
@@ -1771,6 +1827,11 @@ class $$TasksTableOrderingComposer
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<bool> get isActive => $composableBuilder(
column: $table.isActive,
builder: (column) => ColumnOrderings(column),
);
$$RoomsTableOrderingComposer get roomId {
final $$RoomsTableOrderingComposer composer = $composerBuilder(
composer: this,
@@ -1843,6 +1904,9 @@ class $$TasksTableAnnotationComposer
GeneratedColumn<DateTime> get createdAt =>
$composableBuilder(column: $table.createdAt, builder: (column) => column);
GeneratedColumn<bool> get isActive =>
$composableBuilder(column: $table.isActive, builder: (column) => column);
$$RoomsTableAnnotationComposer get roomId {
final $$RoomsTableAnnotationComposer composer = $composerBuilder(
composer: this,
@@ -1930,6 +1994,7 @@ class $$TasksTableTableManager
Value<EffortLevel> effortLevel = const Value.absent(),
Value<DateTime> nextDueDate = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(),
Value<bool> isActive = const Value.absent(),
}) => TasksCompanion(
id: id,
roomId: roomId,
@@ -1941,6 +2006,7 @@ class $$TasksTableTableManager
effortLevel: effortLevel,
nextDueDate: nextDueDate,
createdAt: createdAt,
isActive: isActive,
),
createCompanionCallback:
({
@@ -1954,6 +2020,7 @@ class $$TasksTableTableManager
required EffortLevel effortLevel,
required DateTime nextDueDate,
Value<DateTime> createdAt = const Value.absent(),
Value<bool> isActive = const Value.absent(),
}) => TasksCompanion.insert(
id: id,
roomId: roomId,
@@ -1965,6 +2032,7 @@ class $$TasksTableTableManager
effortLevel: effortLevel,
nextDueDate: nextDueDate,
createdAt: createdAt,
isActive: isActive,
),
withReferenceMapper: (p0) => p0
.map(