2026-01-08 16:07:56 +00:00
|
|
|
|
import 'package:drift/drift.dart';
|
|
|
|
|
|
import 'package:drift_postgres/drift_postgres.dart';
|
|
|
|
|
|
import 'package:injectable/injectable.dart';
|
|
|
|
|
|
import 'package:mnemo_cards_backend/database/database.dart';
|
|
|
|
|
|
import 'package:mnemo_cards_backend/packs/card_pack_drift_extension.dart';
|
|
|
|
|
|
import 'package:mnemo_cards_common_backend/mnemo_cards_common_backend.dart';
|
|
|
|
|
|
|
|
|
|
|
|
import 'user_drift_extension.dart';
|
|
|
|
|
|
|
|
|
|
|
|
/// Repository для работы с пользователями
|
|
|
|
|
|
/// Работает с доменными моделями (UserModel), использует DAO для доступа к БД
|
|
|
|
|
|
@lazySingleton
|
|
|
|
|
|
class UserRepository {
|
|
|
|
|
|
final AppDatabase _db;
|
|
|
|
|
|
|
|
|
|
|
|
UserRepository(this._db);
|
|
|
|
|
|
|
|
|
|
|
|
/// Получить пользователя по ID
|
|
|
|
|
|
/// [includePacks] - загружать ли связанные паки пользователя
|
2026-01-08 16:32:25 +00:00
|
|
|
|
/// [withData] - загружать ли UserData пользователя
|
2026-01-08 16:07:56 +00:00
|
|
|
|
Future<UserModel?> getUserById(
|
|
|
|
|
|
String id, {
|
|
|
|
|
|
bool includePacks = false,
|
2026-01-08 16:32:25 +00:00
|
|
|
|
bool withData = true,
|
2026-01-08 16:07:56 +00:00
|
|
|
|
}) async {
|
2026-01-08 16:32:25 +00:00
|
|
|
|
if (withData) {
|
|
|
|
|
|
final userWithData = await _db.userDao.getUserWithDataById(id);
|
|
|
|
|
|
if (userWithData == null) return null;
|
|
|
|
|
|
|
|
|
|
|
|
if (includePacks) {
|
|
|
|
|
|
final packs = await _db.userDao.getUserPacks(id);
|
|
|
|
|
|
return await userWithData.user.toUserModel(packs);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return await userWithData.user.toUserModel();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-08 16:07:56 +00:00
|
|
|
|
final user = await _db.userDao.getUserById(id);
|
|
|
|
|
|
if (user == null) return null;
|
|
|
|
|
|
|
|
|
|
|
|
if (includePacks) {
|
|
|
|
|
|
final packs = await _db.userDao.getUserPacks(id);
|
|
|
|
|
|
return await user.toUserModel(packs);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return await user.toUserModel();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Получить пользователя по email
|
|
|
|
|
|
Future<UserModel?> getUserByEmail(String email) async {
|
|
|
|
|
|
final user = await _db.userDao.getUserByEmail(email);
|
|
|
|
|
|
if (user == null) return null;
|
|
|
|
|
|
|
|
|
|
|
|
return await user.toUserModel();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Получить пользователя по externalUserId
|
|
|
|
|
|
Future<UserModel?> getUserByExternalId(String externalId) async {
|
|
|
|
|
|
final user = await _db.userDao.getUserByExternalId(externalId);
|
2026-01-08 16:58:13 +00:00
|
|
|
|
|
2026-01-08 16:07:56 +00:00
|
|
|
|
if (user == null) return null;
|
|
|
|
|
|
|
|
|
|
|
|
return await user.toUserModel();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Создать пользователя
|
|
|
|
|
|
Future<String> createUser(UserModel userModel) async {
|
|
|
|
|
|
final userCompanion = userModel.toUsersCompanion();
|
|
|
|
|
|
return await _db.userDao.createUser(userCompanion);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Создать пользователя с UserData
|
|
|
|
|
|
Future<String> createUserWithData({
|
|
|
|
|
|
required UserModel userModel,
|
|
|
|
|
|
required UserDatasCompanion userData,
|
|
|
|
|
|
}) async {
|
|
|
|
|
|
final userCompanion = userModel.toUsersCompanion();
|
|
|
|
|
|
return await _db.userDao.createUserWithData(
|
|
|
|
|
|
user: userCompanion,
|
|
|
|
|
|
userData: userData,
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Обновить пользователя
|
|
|
|
|
|
Future<void> updateUser(UserModel userModel) async {
|
|
|
|
|
|
if (userModel.id == null) {
|
|
|
|
|
|
throw ArgumentError('User ID is required');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await _db.userDao.updateUserPartial(
|
|
|
|
|
|
userModel.toUsersCompanion().copyWith(
|
|
|
|
|
|
updatedAt: Value(PgDateTime(DateTime.now())),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Обновить пользователя частично
|
|
|
|
|
|
Future<void> updateUserPartial(UsersCompanion updates) async {
|
|
|
|
|
|
await _db.userDao.updateUserPartial(updates);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Удалить пользователя (soft delete)
|
|
|
|
|
|
Future<void> softDeleteUser(String userId) async {
|
|
|
|
|
|
await _db.userDao.softDeleteUser(userId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Получить всех пользователей (для админки)
|
|
|
|
|
|
Future<List<UserModel>> getAllUsers({
|
|
|
|
|
|
int? limit,
|
|
|
|
|
|
int? offset,
|
|
|
|
|
|
bool includeDeleted = false,
|
|
|
|
|
|
bool includePacks = false,
|
|
|
|
|
|
}) async {
|
|
|
|
|
|
final users = await _db.userDao.getAllUsers(
|
|
|
|
|
|
limit: limit,
|
|
|
|
|
|
offset: offset,
|
|
|
|
|
|
includeDeleted: includeDeleted,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (includePacks) {
|
|
|
|
|
|
final userModels = <UserModel>[];
|
|
|
|
|
|
for (final user in users) {
|
|
|
|
|
|
final packs = await _db.userDao.getUserPacks(user.id);
|
|
|
|
|
|
final userModel = await user.toUserModel(packs);
|
|
|
|
|
|
userModels.add(userModel);
|
|
|
|
|
|
}
|
|
|
|
|
|
return userModels;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return await Future.wait(users.map((u) => u.toUserModel()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Подсчитать пользователей
|
|
|
|
|
|
Future<int> countUsers({bool includeDeleted = false}) async {
|
|
|
|
|
|
return await _db.userDao.countUsers(includeDeleted: includeDeleted);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Получить паки пользователя
|
|
|
|
|
|
Future<List<CardPackModel>> getUserPacks(String userId) async {
|
|
|
|
|
|
final packs = await _db.userDao.getUserPacks(userId);
|
|
|
|
|
|
return await Future.wait(packs.map((p) => p.toModel()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Получить UserData пользователя
|
|
|
|
|
|
Future<UserData?> getUserData(String userId) async {
|
|
|
|
|
|
return await _db.userDao.getUserData(userId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Обновить UserData частично
|
|
|
|
|
|
Future<void> updateUserDataPartial(UserDatasCompanion updates) async {
|
|
|
|
|
|
await _db.userDao.updateUserDataPartial(updates);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Обновить время последнего визита
|
|
|
|
|
|
Future<void> updateLastOnline(String userId) async {
|
|
|
|
|
|
await _db.userDao.updateLastOnline(userId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|