320 lines
14 KiB
Markdown
320 lines
14 KiB
Markdown
# 📋 Отчет о проверке выполнения этапов 1-6 плана улучшений БД
|
||
|
||
**Дата проверки:** 14 декабря 2025
|
||
**Статус:** ⚠️ **Частично выполнено с критичными ошибками**
|
||
|
||
---
|
||
|
||
## ✅ Выполненные этапы
|
||
|
||
### Этап 1: Подготовка инфраструктуры ✅
|
||
|
||
**Статус:** ✅ Выполнено (с ошибками в коде)
|
||
|
||
#### 1.1 SoftDeleteMixin создан
|
||
- ✅ Файл создан: `lib/database/daos/mixins/soft_delete_mixin.dart`
|
||
- ❌ **ОШИБКА:** Методы имеют ошибки компиляции (метод `companion` не существует)
|
||
|
||
#### 1.2 Новые таблицы созданы
|
||
- ✅ `lib/database/tables/word_statistics.dart` - создана
|
||
- ✅ `lib/database/tables/audit.dart` - создана
|
||
- ❌ **ОШИБКА:** AuditLogs.tableName имеет неверную сигнатуру
|
||
|
||
#### 1.3 database.dart обновлен
|
||
- ✅ WordStatistics добавлена в список таблиц
|
||
- ✅ AuditLogs добавлена в список таблиц
|
||
- ✅ WordStatisticsDao зарегистрирован
|
||
- ✅ AuditDao зарегистрирован
|
||
|
||
#### 1.4 Build runner
|
||
- ✅ `dart run build_runner build` выполняется без ошибок
|
||
- ❌ `dart analyze` показывает **88 ошибок компиляции**
|
||
|
||
---
|
||
|
||
### Этап 2: Добавление soft delete во все таблицы ✅
|
||
|
||
**Статус:** ✅ Выполнено
|
||
|
||
Проверены все таблицы - soft delete поля добавлены:
|
||
|
||
- ✅ **Payments** - isDeleted, deletedAt
|
||
- ✅ **Tokens** - isDeleted, deletedAt
|
||
- ✅ **RefreshTokens** - isDeleted, deletedAt
|
||
- ✅ **TelegramAuthCodes** - isDeleted, deletedAt
|
||
- ✅ **StudySessions** - isDeleted, deletedAt
|
||
- ✅ **Tests** - isDeleted, deletedAt
|
||
- ✅ **TestQuestions** - isDeleted, deletedAt
|
||
- ✅ **PromoCodesCampaigns** - isDeleted, deletedAt
|
||
- ✅ **PromoCodes** - isDeleted, deletedAt
|
||
- ✅ **DiscountCampaigns** - isDeleted, deletedAt
|
||
- ✅ **Discounts** - isDeleted, deletedAt
|
||
- ✅ **WordStatistics** - isDeleted, deletedAt (новая таблица)
|
||
|
||
**Таблицы с soft delete, которые были до плана:**
|
||
- ✅ **Users** - уже был isDeleted (без deletedAt, но это ОК)
|
||
- ✅ **CardPacks** - уже был isDeleted
|
||
- ✅ **GameCards** - уже был isDeleted
|
||
|
||
---
|
||
|
||
### Этап 3: Удаление deprecated полей ✅
|
||
|
||
**Статус:** ✅ Выполнено
|
||
|
||
#### 3.1 UserDatas - deprecated поля удалены
|
||
- ✅ `words` - УДАЛЕНО
|
||
- ✅ `achievements` - УДАЛЕНО
|
||
- ✅ `packProgress` - УДАЛЕНО
|
||
- ✅ `studyDates` - УДАЛЕНО
|
||
- ✅ `categoryMinutes` - УДАЛЕНО
|
||
|
||
**Остались только простые счетчики:**
|
||
- totalStudyTimeMinutes, currentStreak, longestStreak, totalCards, totalTests, tags
|
||
|
||
#### 3.2 Payments - deprecated поля удалены
|
||
- ✅ `packs` - УДАЛЕНО
|
||
- ✅ `subscription` - УДАЛЕНО
|
||
- ✅ Soft delete добавлен (isDeleted, deletedAt)
|
||
|
||
#### 3.3 GameCards - packId удален
|
||
- ✅ `packId` - УДАЛЕНО из таблицы
|
||
- ✅ Комментарий добавлен: "packId удален - связь теперь только через CardPackCards"
|
||
- ❌ **ОШИБКА:** Код в 2 местах все еще использует `card.packId`:
|
||
- `lib/api/v2/admin_cards_api_v2.dart` - 4 использования
|
||
- `lib/api/v2/telegram_bot_api_v2.dart` - 1 использование
|
||
|
||
---
|
||
|
||
### Этап 4: Создание новых DAO и менеджеров ✅
|
||
|
||
**Статус:** ✅ Выполнено (с ошибками в коде)
|
||
|
||
#### 4.1 WordStatisticsDao
|
||
- ✅ Файл создан: `lib/database/daos/word_statistics_dao.dart`
|
||
- ✅ SoftDeleteMixin добавлен
|
||
- ✅ Методы реализованы:
|
||
- `getByUserAndCard(userId, cardId)`
|
||
- `create(...)` - ❌ **ОШИБКА в типах параметров**
|
||
- `update(...)` - ❌ **ОШИБКА: метод конфликтует с базовым**
|
||
- `getPackStatistics(userId, packId)`
|
||
- `getUserStatistics(userId)`
|
||
- ✅ Зарегистрирован в database.dart
|
||
|
||
#### 4.2 AuditDao
|
||
- ✅ Файл создан: `lib/database/daos/audit_dao.dart`
|
||
- ✅ Методы реализованы:
|
||
- `log(...)`
|
||
- `getLogsByRecord(...)`
|
||
- `getRecentLogs(...)`
|
||
- ✅ Зарегистрирован в database.dart
|
||
- ✅ Комментарий "⚠️ Пока не используется в коде" добавлен
|
||
|
||
#### 4.3 WordStatisticsManager
|
||
- ✅ Файл создан: `lib/statistics/word_statistics_manager.dart`
|
||
- ✅ @lazySingleton аннотация добавлена
|
||
- ✅ Методы реализованы:
|
||
- `recordAnswer(userId, cardId, isCorrect)`
|
||
- `calculateMastery(correct, incorrect)`
|
||
- `getPackStatistics(userId, packId)`
|
||
- `getUserStatistics(userId)`
|
||
- ✅ Зарегистрирован в DI (injector.config.dart)
|
||
|
||
---
|
||
|
||
### Этап 5: Обновление существующих DAO ⚠️
|
||
|
||
**Статус:** ⚠️ Частично выполнено
|
||
|
||
#### 5.1 SoftDeleteMixin добавлен в DAO
|
||
|
||
**✅ Используют SoftDeleteMixin:**
|
||
- ✅ PaymentDao
|
||
- ✅ StatisticsDao
|
||
- ✅ WordStatisticsDao
|
||
|
||
**❌ НЕ используют SoftDeleteMixin (фильтруют isDeleted вручную):**
|
||
- ❌ TestDao
|
||
- ❌ PromoCodeDao
|
||
- ❌ DiscountDao
|
||
- ❌ UserDao
|
||
- ❌ PackDao
|
||
- ❌ SubscriptionDao (не проверялся)
|
||
- ❌ TaskDao (не проверялся)
|
||
- ❌ AchievementDao (не проверялся)
|
||
|
||
**Примечание:** Эти DAO фильтруют `isDeleted` вручную в запросах, но не используют единообразный подход через миксин.
|
||
|
||
#### 5.2 PackDao обновлен
|
||
- ✅ Комментарий добавлен: "Связь теперь только через CardPackCards"
|
||
- ✅ Метод `getPackCards()` использует JOIN через CardPackCards
|
||
- ❌ Но в других местах кода все еще используется `card.packId`
|
||
|
||
---
|
||
|
||
### Этап 6: Обновление бизнес-логики ✅
|
||
|
||
**Статус:** ✅ Выполнено
|
||
|
||
#### 6.1 StatisticsCalculator обновлен
|
||
- ✅ Файл: `lib/statistics/statistics_calculator.dart`
|
||
- ✅ Методы добавлены:
|
||
- `calculatePackProgress(userId, packId)` - берет данные из WordStatistics + UserPacks
|
||
- `calculateAllPackProgress(userId)`
|
||
- `calculateStudyDates(userId)` - берет данные из StudySessions
|
||
- `calculateCategoryMinutes(userId)` - берет данные из StudySessions + CardPacks
|
||
- ⚠️ **TODO:** В calculateCategoryMinutes есть комментарий "TODO: добавить category в CardPacks"
|
||
|
||
#### 6.2 TestManager обновлен
|
||
- ❌ **НЕ НАЙДЕН:** В TestManager нет метода `submitTest()`
|
||
- ❌ **НЕ ОБНОВЛЕН:** TestManager НЕ использует WordStatisticsManager напрямую
|
||
|
||
**НО:**
|
||
- ✅ UserManager **ИСПОЛЬЗУЕТ** WordStatisticsManager
|
||
- ✅ В методе для записи результатов теста (строки 260-279 в user_manager.dart):
|
||
```dart
|
||
await _wordStatisticsManager.recordAnswer(
|
||
userId: user.id!,
|
||
cardId: card.id,
|
||
isCorrect: true/false,
|
||
);
|
||
```
|
||
|
||
#### 6.3 UsersApiV2 обновлен
|
||
- ✅ Файл: `lib/api/v2/users_api_v2.dart`
|
||
- ✅ Метод `getCurrentUser()` рассчитывает:
|
||
- `packProgress` через `statisticsCalculator.calculateAllPackProgress()`
|
||
- `studyDates` через `statisticsCalculator.calculateStudyDates()`
|
||
- `categoryMinutes` через `statisticsCalculator.calculateCategoryMinutes()`
|
||
- ✅ `words` берутся из WordStatistics (строки 79-94)
|
||
|
||
---
|
||
|
||
## ❌ Критичные проблемы
|
||
|
||
### 1. Ошибки компиляции (88 ошибок)
|
||
|
||
**Dart analyzer показывает 88 ошибок:**
|
||
|
||
#### Использование удаленного поля `card.packId`
|
||
- `lib/api/v2/admin_cards_api_v2.dart` - 4 использования
|
||
- `lib/api/v2/telegram_bot_api_v2.dart` - 1 использование
|
||
- **Необходимо:** Использовать CardPackCards для получения пака карточки
|
||
|
||
#### SoftDeleteMixin - метод companion не существует
|
||
- `lib/database/daos/mixins/soft_delete_mixin.dart:40` - ошибка в softDelete()
|
||
- `lib/database/daos/mixins/soft_delete_mixin.dart:85` - ошибка в restore()
|
||
- **Необходимо:** Исправить конструкцию Companion объектов
|
||
|
||
#### WordStatisticsDao - ошибки в методах
|
||
- `lib/database/daos/word_statistics_dao.dart:42-45` - неверные типы в create()
|
||
- `lib/database/daos/word_statistics_dao.dart:55` - метод update() конфликтует с базовым
|
||
- `lib/database/daos/word_statistics_dao.dart:64-71` - ошибки в вызове update
|
||
- **Необходимо:** Переименовать метод и исправить типы
|
||
|
||
#### AuditLogs.tableName - неверная сигнатура
|
||
- `lib/database/tables/audit.dart:21` - tableName должен быть String?, а не Column<String>
|
||
- **Необходимо:** Удалить геттер tableName или исправить сигнатуру
|
||
|
||
#### DateTime vs PgDateTime
|
||
- Множество мест используют DateTime вместо PgDateTime
|
||
- **Необходимо:** Обернуть все DateTime в PgDateTime()
|
||
|
||
#### Недостающие методы
|
||
- `deleteToken()` в UserDao
|
||
- `deleteCampaign()` в DiscountDao
|
||
- `deleteExpiredRefreshTokens()` в UserDao
|
||
|
||
---
|
||
|
||
## 📊 Сводная статистика
|
||
|
||
| Этап | Статус | Прогресс |
|
||
|------|--------|----------|
|
||
| **Этап 1: Инфраструктура** | ⚠️ Частично | 80% (SoftDeleteMixin и AuditLogs имеют ошибки) |
|
||
| **Этап 2: Soft delete** | ✅ Выполнено | 100% |
|
||
| **Этап 3: Удаление полей** | ⚠️ Частично | 90% (packId удален из таблицы, но используется в коде) |
|
||
| **Этап 4: Новые DAO** | ⚠️ Частично | 85% (созданы, но имеют ошибки) |
|
||
| **Этап 5: Обновление DAO** | ❌ Не завершено | 40% (SoftDeleteMixin в 3 из ~12 DAO) |
|
||
| **Этап 6: Бизнес-логика** | ✅ Выполнено | 95% (интеграция работает через UserManager) |
|
||
|
||
**Общий прогресс этапов 1-6:** ~75%
|
||
|
||
---
|
||
|
||
## 🔧 Что нужно исправить для завершения этапов 1-6
|
||
|
||
### Критичные (блокируют компиляцию):
|
||
|
||
1. ❌ **Исправить SoftDeleteMixin** - метод создания Companion
|
||
2. ❌ **Исправить WordStatisticsDao** - переименовать метод update(), исправить типы в create()
|
||
3. ❌ **Исправить AuditLogs.tableName** - удалить или изменить сигнатуру
|
||
4. ❌ **Удалить использование card.packId** в:
|
||
- admin_cards_api_v2.dart (4 места)
|
||
- telegram_bot_api_v2.dart (1 место)
|
||
5. ❌ **Исправить DateTime → PgDateTime** во всех DAO
|
||
6. ❌ **Реализовать недостающие методы:** deleteToken(), deleteCampaign()
|
||
|
||
### Желательные (для полноты реализации):
|
||
|
||
7. ⚠️ **Добавить SoftDeleteMixin** в остальные DAO (8 DAO):
|
||
- TestDao
|
||
- PromoCodeDao
|
||
- DiscountDao
|
||
- UserDao
|
||
- PackDao
|
||
- SubscriptionDao
|
||
- TaskDao
|
||
- AchievementDao
|
||
|
||
8. ⚠️ **Добавить поле category** в CardPacks (для полноты calculateCategoryMinutes)
|
||
|
||
---
|
||
|
||
## ✅ Что точно работает
|
||
|
||
1. ✅ **Все deprecated поля удалены** из UserDatas и Payments
|
||
2. ✅ **Soft delete поля добавлены** во все нужные таблицы
|
||
3. ✅ **WordStatisticsManager создан** и зарегистрирован в DI
|
||
4. ✅ **Интеграция с API работает:**
|
||
- UsersApiV2 использует calculatePackProgress, calculateStudyDates, calculateCategoryMinutes
|
||
- UserManager записывает статистику через WordStatisticsManager
|
||
5. ✅ **Build runner работает** без ошибок генерации кода
|
||
6. ✅ **AuditDao инфраструктура готова** (пока не используется, как и планировалось)
|
||
|
||
---
|
||
|
||
## 📝 Рекомендации
|
||
|
||
### Немедленные действия:
|
||
1. Исправить 6 критичных проблем, блокирующих компиляцию
|
||
2. Запустить тесты после исправления
|
||
3. Проверить работу API endpoints
|
||
|
||
### Следующий шаг (Этап 7):
|
||
После исправления ошибок можно переходить к **Этапу 7: Тестирование**:
|
||
- Unit тесты для WordStatisticsDao
|
||
- Unit тесты для WordStatisticsManager
|
||
- Unit тесты для SoftDeleteMixin
|
||
- Integration тесты для UsersApiV2
|
||
- Smoke тесты
|
||
|
||
---
|
||
|
||
## 📄 Выводы
|
||
|
||
**Этапы 1-6 выполнены на ~75%.**
|
||
|
||
**Положительные моменты:**
|
||
- Архитектура изменений реализована корректно
|
||
- Soft delete добавлен во все таблицы
|
||
- Deprecated поля успешно удалены
|
||
- Новая логика расчета статистики работает
|
||
- Интеграция WordStatisticsManager с API выполнена
|
||
|
||
**Проблемы:**
|
||
- 88 ошибок компиляации блокируют работу
|
||
- SoftDeleteMixin добавлен только в 3 из ~12 DAO
|
||
- Код не компилируется и не запускается
|
||
|
||
**Приоритет:** Исправить критичные ошибки компиляции перед переходом к этапу 7.
|