Some checks are pending
Backend CI / test (push) Waiting to run
Backend 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
158 lines
5 KiB
Dart
158 lines
5 KiB
Dart
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] - загружать ли связанные паки пользователя
|
||
/// [withData] - загружать ли UserData пользователя
|
||
Future<UserModel?> getUserById(
|
||
String id, {
|
||
bool includePacks = false,
|
||
bool withData = true,
|
||
}) async {
|
||
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();
|
||
}
|
||
|
||
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);
|
||
|
||
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);
|
||
}
|
||
}
|