mnemo_cards/mnemo_cards_backend/lib/database/daos/task_dao.dart

198 lines
6.6 KiB
Dart
Raw Normal View History

2025-12-13 13:27:05 +00:00
import 'package:drift/drift.dart';
2025-12-13 23:35:14 +00:00
import 'package:drift_postgres/drift_postgres.dart';
2025-12-13 13:27:05 +00:00
import '../database.dart';
part 'task_dao.g.dart';
@DriftAccessor()
class TaskDao extends DatabaseAccessor<AppDatabase> with _$TaskDaoMixin {
TaskDao(super.db);
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
// ==================== Tasks ====================
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Получить задачу по ID
2025-12-13 20:55:50 +00:00
Future<Task?> getTaskById(String id) {
2025-12-13 13:27:05 +00:00
return (select(db.tasks)..where((t) => t.id.equals(id))).getSingleOrNull();
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Получить все задачи
Future<List<Task>> getAllTasks() {
return select(db.tasks).get();
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Создать задачу
2025-12-13 20:55:50 +00:00
Future<String> createTask(TasksCompanion task) async {
final inserted = await into(db.tasks).insertReturning(task);
return inserted.id;
2025-12-13 13:27:05 +00:00
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Обновить задачу
Future<bool> updateTask(Task task) {
return update(db.tasks).replace(task);
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Обновить время последнего выполнения
2025-12-13 20:55:50 +00:00
Future<void> updateLastExecution(String taskId) {
2025-12-13 23:35:14 +00:00
final now = PgDateTime(DateTime.now());
2025-12-20 18:26:15 +00:00
return (update(db.tasks)..where((t) => t.id.equals(taskId))).write(
TasksCompanion(lastExecution: Value(now), updatedAt: Value(now)),
);
2025-12-13 13:27:05 +00:00
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
// ==================== UserTasks ====================
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Получить задачу пользователя по ID
2025-12-13 20:55:50 +00:00
Future<UserTask?> getUserTaskById(String id) {
2025-12-20 18:26:15 +00:00
return (select(
db.userTasks,
)..where((ut) => ut.id.equals(id))).getSingleOrNull();
2025-12-13 13:27:05 +00:00
}
2025-12-20 18:26:15 +00:00
2025-12-13 14:48:00 +00:00
/// Получить все задачи пользователей (для системных задач)
Future<List<UserTask>> getAllUserTasks() {
return select(db.userTasks).get();
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Получить задачи пользователя
2025-12-20 18:26:15 +00:00
Future<List<UserTask>> getUserTasks(
String userId, {
2025-12-13 13:27:05 +00:00
String? status,
bool activeOnly = false,
}) {
final query = select(db.userTasks);
2025-12-20 18:26:15 +00:00
2025-12-13 20:55:50 +00:00
// Note: UserTasks table doesn't have userId column, so we can't filter by userId
// This method may need to be refactored if userId filtering is required
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
if (status != null) {
query.where((ut) => ut.status.equals(status));
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
if (activeOnly) {
2025-12-13 23:35:14 +00:00
final now = PgDateTime(DateTime.now());
2025-12-13 13:27:05 +00:00
query.where((ut) => ut.expiresAt.isBiggerThanValue(now));
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
query.orderBy([(ut) => OrderingTerm.desc(ut.createdAt)]);
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
return query.get();
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Создать задачу пользователя
2025-12-13 20:55:50 +00:00
Future<String> createUserTask(UserTasksCompanion task) async {
final inserted = await into(db.userTasks).insertReturning(task);
return inserted.id;
2025-12-13 13:27:05 +00:00
}
2025-12-14 00:13:49 +00:00
/// Создать задачу пользователя или игнорировать, если уже существует
/// Возвращает true, если задача была создана, false если уже существовала
2025-12-20 18:26:15 +00:00
///
2025-12-14 00:13:49 +00:00
/// Если task.id.present == true, проверяет существование перед вставкой
Future<bool> createUserTaskOrIgnore(UserTasksCompanion task) async {
// Если ID указан, проверяем существование перед вставкой
if (task.id.present) {
final existing = await getUserTaskById(task.id.value);
if (existing != null) {
return false; // Задача уже существует
}
}
2025-12-20 18:26:15 +00:00
2025-12-14 00:13:49 +00:00
try {
2025-12-20 18:26:15 +00:00
await into(db.userTasks).insert(task, mode: InsertMode.insertOrIgnore);
2025-12-14 00:13:49 +00:00
return true; // Задача была создана
} catch (e) {
// PostgreSQL error code 23505 = unique_violation (duplicate key)
// Это может произойти в редких случаях race condition
final errorString = e.toString();
2025-12-20 18:26:15 +00:00
if (errorString.contains('23505') ||
2025-12-14 00:13:49 +00:00
errorString.contains('duplicate key') ||
errorString.contains('unique constraint')) {
return false; // Задача уже существует
}
// Пробрасываем другие ошибки
rethrow;
}
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Обновить задачу пользователя
Future<bool> updateUserTask(UserTask task) {
return update(db.userTasks).replace(task);
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Завершить задачу пользователя
2025-12-13 20:55:50 +00:00
Future<void> completeUserTask(String taskId) {
2025-12-13 23:35:14 +00:00
final now = PgDateTime(DateTime.now());
2025-12-20 18:26:15 +00:00
return (update(db.userTasks)..where((ut) => ut.id.equals(taskId))).write(
UserTasksCompanion(
status: const Value('completed'),
completedAt: Value(now),
updatedAt: Value(now),
),
);
2025-12-13 13:27:05 +00:00
}
2025-12-13 14:48:00 +00:00
/// Подсчитать задачи пользователя
2025-12-13 20:55:50 +00:00
Future<int> countUserTasks(String userId, {String? status}) async {
2025-12-13 14:48:00 +00:00
final countExpr = db.userTasks.id.count();
final query = selectOnly(db.userTasks)..addColumns([countExpr]);
2025-12-20 18:26:15 +00:00
2025-12-13 14:48:00 +00:00
if (status != null) {
query.where(db.userTasks.status.equals(status));
}
2025-12-20 18:26:15 +00:00
2025-12-13 14:48:00 +00:00
return await query.map((row) => row.read(countExpr)!).getSingle();
}
2025-12-20 18:26:15 +00:00
2026-01-09 17:21:18 +00:00
/// Удалить задачу пользователя
Future<bool> deleteUserTask(String taskId) async {
final deleted = await (delete(
db.userTasks,
)..where((ut) => ut.id.equals(taskId))).go();
return deleted > 0;
}
2025-12-13 13:27:05 +00:00
// ==================== UserTaskProgresses ====================
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Получить прогресс задачи пользователя
2025-12-20 18:26:15 +00:00
Future<UserTaskProgressesData?> getTaskProgress(
String userId,
String taskId,
) {
return (select(db.userTaskProgresses)..where(
(utp) => utp.userId.equals(userId) & utp.taskId.equals(taskId),
))
.getSingleOrNull();
2025-12-13 13:27:05 +00:00
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Создать прогресс задачи
2025-12-20 18:26:15 +00:00
Future<String> createTaskProgress(
UserTaskProgressesCompanion progress,
) async {
final inserted = await into(
db.userTaskProgresses,
).insertReturning(progress);
2025-12-13 20:55:50 +00:00
return inserted.id;
2025-12-13 13:27:05 +00:00
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Обновить прогресс задачи
2025-12-13 20:55:50 +00:00
Future<bool> updateTaskProgress(UserTaskProgressesData progress) {
2025-12-13 13:27:05 +00:00
return update(db.userTaskProgresses).replace(progress);
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
// ==================== UserTaskResults ====================
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Получить результаты задач пользователя
2025-12-13 20:55:50 +00:00
Future<List<UserTaskResult>> getTaskResults(String userId) {
2025-12-13 13:27:05 +00:00
return (select(db.userTaskResults)
2025-12-20 18:26:15 +00:00
..where((utr) => utr.userId.equals(userId))
..orderBy([(utr) => OrderingTerm.desc(utr.completedAt)]))
.get();
2025-12-13 13:27:05 +00:00
}
2025-12-20 18:26:15 +00:00
2025-12-13 13:27:05 +00:00
/// Создать результат задачи
2025-12-13 20:55:50 +00:00
Future<String> createTaskResult(UserTaskResultsCompanion result) async {
final inserted = await into(db.userTaskResults).insertReturning(result);
return inserted.id;
2025-12-13 13:27:05 +00:00
}
}