import 'package:drift/drift.dart'; import 'package:drift_postgres/drift_postgres.dart'; import '../database.dart'; import '../tables/tests.dart'; part 'test_dao.g.dart'; @DriftAccessor(tables: [Tests, TestQuestions, TestPackRelations, TestStatistics]) class TestDao extends DatabaseAccessor with _$TestDaoMixin { TestDao(super.db); // ==================== Tests ==================== /// Получить тест по ID (только активные) Future getTestById(String id) { return (select(tests) ..where((t) => t.id.equals(id) & t.isDeleted.equals(false)) ).getSingleOrNull(); } /// Получить все тесты (только активные) Future> getAllTests() { return (select(tests) ..where((t) => t.isDeleted.equals(false)) ).get(); } /// Получить тесты пака (только активные) Future> getTestsByPackId(String packId) async { final query = select(tests).join([ innerJoin( testPackRelations, testPackRelations.testId.equalsExp(tests.id) & testPackRelations.packId.equals(packId), ), ]) ..where(tests.isDeleted.equals(false)); return query.map((row) => row.readTable(tests)).get(); } /// Создать тест Future createTest(TestsCompanion test) async { final inserted = await into(tests).insertReturning(test); return inserted.id; } /// Обновить тест Future updateTest(Test test) { return update(tests).replace(test); } /// Удалить тест (soft delete) Future softDeleteTest(String testId) { return (update(tests)..where((t) => t.id.equals(testId))) .write(TestsCompanion( isDeleted: const Value(true), deletedAt: Value(PgDateTime(DateTime.now())), updatedAt: Value(PgDateTime(DateTime.now())), )); } /// Связать тест с паком Future linkTestToPack(String testId, String packId) async { await into(testPackRelations).insert( TestPackRelationsCompanion.insert( testId: testId, packId: packId, ), mode: InsertMode.insertOrIgnore, ); } /// Удалить связь теста с паком Future unlinkTestFromPack(String testId, String packId) async { await (delete(testPackRelations) ..where((tpr) => tpr.testId.equals(testId) & tpr.packId.equals(packId)) ).go(); } /// Получить packId для теста Future getPackIdForTest(String testId) async { final relation = await (select(testPackRelations) ..where((tpr) => tpr.testId.equals(testId)) ..limit(1) ).getSingleOrNull(); return relation?.packId; } /// Получить все packId для теста Future> getPackIdsForTest(String testId) async { final relations = await (select(testPackRelations) ..where((tpr) => tpr.testId.equals(testId)) ).get(); return relations.map((r) => r.packId).toList(); } // ==================== TestQuestions ==================== /// Получить вопросы теста (только активные, отсортированные по orderIndex) Future> getTestQuestions(String testId) { return (select(testQuestions) ..where((tq) => tq.testId.equals(testId) & tq.isDeleted.equals(false)) ..orderBy([(tq) => OrderingTerm(expression: tq.orderIndex)]) ).get(); } /// Создать вопрос теста Future createTestQuestion(TestQuestionsCompanion question) async { final inserted = await into(testQuestions).insertReturning(question); return inserted.id; } /// Обновить вопрос теста Future updateTestQuestion(TestQuestion question) { return update(testQuestions).replace(question); } /// Удалить вопрос теста (soft delete) Future softDeleteTestQuestion(String questionId) { return (update(testQuestions)..where((tq) => tq.id.equals(questionId))) .write(TestQuestionsCompanion( isDeleted: const Value(true), deletedAt: Value(PgDateTime(DateTime.now())), updatedAt: Value(PgDateTime(DateTime.now())), )); } // ==================== TestStatistics ==================== /// Получить статистику теста пользователя Future getTestStatistics(String userId, String testId) { return (select(testStatistics) ..where((ts) => ts.userId.equals(userId) & ts.testId.equals(testId)) ).getSingleOrNull(); } /// Создать статистику теста Future createTestStatistics(TestStatisticsCompanion statistics) async { final inserted = await into(testStatistics).insertReturning(statistics); return inserted.id; } /// Обновить статистику теста Future updateTestStatistics(TestStatistic statistics) { return update(testStatistics).replace(statistics); } }