11 KiB
🔥 Критичные исправления для завершения этапов 1-6
Приоритет: ВЫСОКИЙ
Блокирует: Компиляцию проекта (88 ошибок)
1. ❌ Исправить SoftDeleteMixin
Файл: lib/database/daos/mixins/soft_delete_mixin.dart
Проблема: Метод table.companion() не существует в Drift
Текущий код (строки 40-44):
.write(
table.companion(
isDeleted: const Value(true),
deletedAt: Value(now),
updatedAt: Value(now),
) as UpdateCompanion<D>,
);
Исправление: Нужно создавать Companion вручную для каждой таблицы. SoftDeleteMixin не может быть универсальным для создания Companion.
Решение А (рекомендуемое): Упростить миксин - убрать методы softDelete() и restore(), оставить только selectActive() и getActiveById()
Решение Б: В каждом DAO реализовывать softDelete() вручную
2. ❌ Исправить WordStatisticsDao
Файл: lib/database/daos/word_statistics_dao.dart
Проблема 2.1: Метод update() конфликтует с базовым (строка 55)
Текущий код:
Future<void> update({
required String id,
required int correctAnswers,
required int incorrectAnswers,
required DateTime lastReviewed,
}) async {
Исправление: Переименовать метод
Future<void> updateStatistics({
required String id,
required int correctAnswers,
required int incorrectAnswers,
required DateTime lastReviewed,
}) async {
Проблема 2.2: Неверные типы в create() (строки 42-45)
Текущий код:
correctAnswers: correctAnswers,
incorrectAnswers: incorrectAnswers,
mastery: mastery,
lastReviewed: Value(lastReviewed),
Исправление:
correctAnswers: Value(correctAnswers),
incorrectAnswers: Value(incorrectAnswers),
mastery: Value(mastery),
lastReviewed: Value(PgDateTime(lastReviewed)),
Проблема 2.3: Ошибки в вызове update (строки 64-71)
Текущий код:
await (update(wordStatistics)..where((w) => w.id.equals(id)))
.write(
WordStatisticsCompanion(
correctAnswers: Value(correctAnswers),
incorrectAnswers: Value(incorrectAnswers),
mastery: Value(mastery),
lastReviewed: Value(lastReviewed),
updatedAt: Value(DateTime.now()),
),
);
Исправление:
await (update(wordStatistics)..where((w) => w.id.equals(id)))
.write(
WordStatisticsCompanion(
correctAnswers: Value(correctAnswers),
incorrectAnswers: Value(incorrectAnswers),
mastery: Value(mastery),
lastReviewed: Value(PgDateTime(lastReviewed)),
updatedAt: Value(PgDateTime(DateTime.now())),
),
);
Проблема 2.4: Обновить вызовы метода update
Файл: lib/statistics/word_statistics_manager.dart (строка 45)
Текущий код:
await _db.wordStatisticsDao.update(
id: existing.id,
correctAnswers: newCorrect,
incorrectAnswers: newIncorrect,
lastReviewed: DateTime.now(),
);
Исправление:
await _db.wordStatisticsDao.updateStatistics(
id: existing.id,
correctAnswers: newCorrect,
incorrectAnswers: newIncorrect,
lastReviewed: DateTime.now(),
);
3. ❌ Исправить AuditLogs.tableName
Файл: lib/database/tables/audit.dart
Проблема: tableName должен возвращать String?, а не Column
Текущий код (строка 21):
TextColumn get tableName => text()();
Исправление: Переименовать поле, чтобы не конфликтовать с Table.tableName
TextColumn get table => text()();
Также нужно обновить:
lib/database/daos/audit_dao.dart- заменитьtableNameнаtableво всех местах
4. ❌ Удалить использование card.packId
4.1 Файл: lib/api/v2/admin_cards_api_v2.dart
Места использования:
- Строка 101:
'packId': card.packId, - Строка 164:
'packId': card.packId, - Строка 263:
'packId': card.packId ?? '', - Строка 280:
packId: requestData['packId'], - Строка 311:
'packId': card.packId,
Решение:
- Для чтения packId: получить через JOIN с CardPackCards
- Для записи packId: использовать CardPackCards.insert
Пример исправления (для чтения):
// Вместо:
'packId': card.packId,
// Использовать:
final packs = await _db.packDao.getPacksForCard(card.id);
'packId': packs.isNotEmpty ? packs.first.id : null,
Нужно добавить метод в PackDao:
Future<List<CardPack>> getPacksForCard(String cardId) async {
final query = select(cardPacks).join([
innerJoin(
cardPackCards,
cardPackCards.packId.equalsExp(cardPacks.id),
),
])..where(cardPackCards.cardId.equals(cardId));
final rows = await query.get();
return rows.map((row) => row.readTable(cardPacks)).toList();
}
4.2 Файл: lib/api/v2/telegram_bot_api_v2.dart
Место использования:
- Строка 83:
'packId': card.packId,
Исправление: Аналогично - использовать JOIN через CardPackCards
5. ❌ Исправить DateTime → PgDateTime
Затронутые файлы (найдено анализатором):
lib/database/daos/discount_dao.dart:83- updatedAtlib/database/daos/discount_dao.dart:110- updatedAtlib/database/daos/promo_code_dao.dart:125- updatedAtlib/database/daos/promo_code_dao.dart:135- updatedAtlib/database/daos/test_dao.dart:99- updatedAtlib/database/daos/user_dao.dart:210, 219, 230, 282, 300- различные поля
Общее правило исправления:
// Было:
updatedAt: Value(DateTime.now()),
// Стало:
updatedAt: Value(PgDateTime(DateTime.now())),
Автоматизация: Можно использовать поиск и замену:
Найти: Value\(DateTime\.now\(\)\)
Заменить: Value(PgDateTime(DateTime.now()))
6. ❌ Реализовать недостающие методы
6.1 UserDao.deleteToken()
Файл: lib/database/daos/user_dao.dart
Использование:
lib/user/user_manager_drift.dart:51lib/user/user_manager_drift.dart:72
Добавить метод:
/// Удалить токен
Future<void> deleteToken(String token) async {
await (delete(tokens)..where((t) => t.token.equals(token))).go();
}
6.2 UserDao.deleteExpiredRefreshTokens()
Файл: lib/database/daos/user_dao.dart
Использование:
lib/api/v2/jwt_service.dart:281
Добавить метод:
/// Удалить истекшие refresh токены
Future<void> deleteExpiredRefreshTokens() async {
final now = PgDateTime(DateTime.now());
await (delete(refreshTokens)
..where((rt) => rt.expiresAt.isSmallerThanValue(now))
).go();
}
6.3 DiscountDao.deleteCampaign()
Файл: lib/database/daos/discount_dao.dart
Использование:
lib/discounts/discounts_manager.dart:161
Добавить метод:
/// Удалить кампанию (soft delete)
Future<void> deleteCampaign(String campaignId) async {
await (update(discountCampaigns)
..where((c) => c.id.equals(campaignId)))
.write(DiscountCampaignsCompanion(
isDeleted: const Value(true),
deletedAt: Value(PgDateTime(DateTime.now())),
updatedAt: Value(PgDateTime(DateTime.now())),
));
}
6.4 PaymentDao.countPaymentsByUserId() - дубликат
Файл: lib/database/daos/payment_dao.dart
Проблема: Метод определен дважды (строки 96 и 164)
Исправление: Удалить одно из определений
7. ❌ Исправить card_pack_drift_extension.dart
Файл: lib/packs/card_pack_drift_extension.dart:86
Проблема: Используется несуществующий параметр packId в GameCardsCompanion
Текущий код:
packId: Value(pack.id),
Исправление: Удалить эту строку (packId больше нет в GameCards)
Порядок выполнения исправлений
Фаза 1: Простые исправления (30 минут)
- ✅ Исправить AuditLogs.tableName → table
- ✅ Исправить DateTime → PgDateTime (массовая замена)
- ✅ Удалить дубликат метода в PaymentDao
- ✅ Удалить packId из card_pack_drift_extension.dart
Фаза 2: Методы DAO (30 минут)
- ✅ Добавить deleteToken() в UserDao
- ✅ Добавить deleteExpiredRefreshTokens() в UserDao
- ✅ Добавить deleteCampaign() в DiscountDao
Фаза 3: WordStatisticsDao (20 минут)
- ✅ Переименовать update() → updateStatistics()
- ✅ Исправить типы в create()
- ✅ Обновить вызовы в WordStatisticsManager
Фаза 4: SoftDeleteMixin (30 минут)
- ✅ Упростить миксин (убрать softDelete и restore)
- ✅ Или реализовать softDelete вручную в PaymentDao, StatisticsDao
Фаза 5: card.packId (1 час)
- ✅ Добавить getPacksForCard() в PackDao
- ✅ Исправить admin_cards_api_v2.dart (5 мест)
- ✅ Исправить telegram_bot_api_v2.dart (1 место)
Фаза 6: Проверка (30 минут)
- ✅ Запустить
dart analyze - ✅ Запустить
dart run build_runner build - ✅ Проверить что нет ошибок
После исправлений
После всех исправлений:
- ✅ Запустить компиляцию:
dart analyze - ✅ Убедиться что 0 ошибок
- ✅ Запустить build_runner:
dart run build_runner build --delete-conflicting-outputs - ✅ Проверить что backend запускается:
dart run bin/server.dart - ✅ Запустить тесты:
dart test
Только после этого можно переходить к Этапу 7: Тестирование.
Оценка времени
- Фаза 1-3 (простые): ~1.5 часа
- Фаза 4-5 (сложные): ~1.5 часа
- Фаза 6 (проверка): ~0.5 часа
Итого: ~3.5 часа работы
После этого этапы 1-6 будут завершены на 100%.