mnemo_cards/mnemo_cards_backend/lib/database/daos/task_dao.dart
Dmitry 0f49280805
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Mobile App CI / test (push) Waiting to run
Mobile App CI / build-android (push) Blocked by required conditions
Mobile App CI / build-ios (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Waiting to run
fixes and format
2025-12-20 21:26:15 +03:00

189 lines
6.4 KiB
Dart

import 'package:drift/drift.dart';
import 'package:drift_postgres/drift_postgres.dart';
import '../database.dart';
part 'task_dao.g.dart';
@DriftAccessor()
class TaskDao extends DatabaseAccessor<AppDatabase> with _$TaskDaoMixin {
TaskDao(super.db);
// ==================== Tasks ====================
/// Получить задачу по ID
Future<Task?> getTaskById(String id) {
return (select(db.tasks)..where((t) => t.id.equals(id))).getSingleOrNull();
}
/// Получить все задачи
Future<List<Task>> getAllTasks() {
return select(db.tasks).get();
}
/// Создать задачу
Future<String> createTask(TasksCompanion task) async {
final inserted = await into(db.tasks).insertReturning(task);
return inserted.id;
}
/// Обновить задачу
Future<bool> updateTask(Task task) {
return update(db.tasks).replace(task);
}
/// Обновить время последнего выполнения
Future<void> updateLastExecution(String taskId) {
final now = PgDateTime(DateTime.now());
return (update(db.tasks)..where((t) => t.id.equals(taskId))).write(
TasksCompanion(lastExecution: Value(now), updatedAt: Value(now)),
);
}
// ==================== UserTasks ====================
/// Получить задачу пользователя по ID
Future<UserTask?> getUserTaskById(String id) {
return (select(
db.userTasks,
)..where((ut) => ut.id.equals(id))).getSingleOrNull();
}
/// Получить все задачи пользователей (для системных задач)
Future<List<UserTask>> getAllUserTasks() {
return select(db.userTasks).get();
}
/// Получить задачи пользователя
Future<List<UserTask>> getUserTasks(
String userId, {
String? status,
bool activeOnly = false,
}) {
final query = select(db.userTasks);
// 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
if (status != null) {
query.where((ut) => ut.status.equals(status));
}
if (activeOnly) {
final now = PgDateTime(DateTime.now());
query.where((ut) => ut.expiresAt.isBiggerThanValue(now));
}
query.orderBy([(ut) => OrderingTerm.desc(ut.createdAt)]);
return query.get();
}
/// Создать задачу пользователя
Future<String> createUserTask(UserTasksCompanion task) async {
final inserted = await into(db.userTasks).insertReturning(task);
return inserted.id;
}
/// Создать задачу пользователя или игнорировать, если уже существует
/// Возвращает true, если задача была создана, false если уже существовала
///
/// Если 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; // Задача уже существует
}
}
try {
await into(db.userTasks).insert(task, mode: InsertMode.insertOrIgnore);
return true; // Задача была создана
} catch (e) {
// PostgreSQL error code 23505 = unique_violation (duplicate key)
// Это может произойти в редких случаях race condition
final errorString = e.toString();
if (errorString.contains('23505') ||
errorString.contains('duplicate key') ||
errorString.contains('unique constraint')) {
return false; // Задача уже существует
}
// Пробрасываем другие ошибки
rethrow;
}
}
/// Обновить задачу пользователя
Future<bool> updateUserTask(UserTask task) {
return update(db.userTasks).replace(task);
}
/// Завершить задачу пользователя
Future<void> completeUserTask(String taskId) {
final now = PgDateTime(DateTime.now());
return (update(db.userTasks)..where((ut) => ut.id.equals(taskId))).write(
UserTasksCompanion(
status: const Value('completed'),
completedAt: Value(now),
updatedAt: Value(now),
),
);
}
/// Подсчитать задачи пользователя
Future<int> countUserTasks(String userId, {String? status}) async {
final countExpr = db.userTasks.id.count();
final query = selectOnly(db.userTasks)..addColumns([countExpr]);
if (status != null) {
query.where(db.userTasks.status.equals(status));
}
return await query.map((row) => row.read(countExpr)!).getSingle();
}
// ==================== UserTaskProgresses ====================
/// Получить прогресс задачи пользователя
Future<UserTaskProgressesData?> getTaskProgress(
String userId,
String taskId,
) {
return (select(db.userTaskProgresses)..where(
(utp) => utp.userId.equals(userId) & utp.taskId.equals(taskId),
))
.getSingleOrNull();
}
/// Создать прогресс задачи
Future<String> createTaskProgress(
UserTaskProgressesCompanion progress,
) async {
final inserted = await into(
db.userTaskProgresses,
).insertReturning(progress);
return inserted.id;
}
/// Обновить прогресс задачи
Future<bool> updateTaskProgress(UserTaskProgressesData progress) {
return update(db.userTaskProgresses).replace(progress);
}
// ==================== UserTaskResults ====================
/// Получить результаты задач пользователя
Future<List<UserTaskResult>> getTaskResults(String userId) {
return (select(db.userTaskResults)
..where((utr) => utr.userId.equals(userId))
..orderBy([(utr) => OrderingTerm.desc(utr.completedAt)]))
.get();
}
/// Создать результат задачи
Future<String> createTaskResult(UserTaskResultsCompanion result) async {
final inserted = await into(db.userTaskResults).insertReturning(result);
return inserted.id;
}
}