From 4b806a3202171adec092cb5af695a8c3f7eb77cc Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 25 Sep 2026 03:55:20 +0200 Subject: [PATCH] UserService refactored to integrate into TenantUser --- .../Services/Users/UserService.cs | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/PostFundManagement.Application/Services/Users/UserService.cs b/PostFundManagement.Application/Services/Users/UserService.cs index a7ca325..fb8c107 100644 --- a/PostFundManagement.Application/Services/Users/UserService.cs +++ b/PostFundManagement.Application/Services/Users/UserService.cs @@ -1,5 +1,6 @@ using PostFundManagement.Application.Abstractions.Services; using PostFundManagement.Domain; +using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Errors; using PostFundManagement.Domain.Extensions; using PostFundManagement.Domain.Models; @@ -7,19 +8,19 @@ using PostFundManagement.Infrastructure.Database; namespace PostFundManagement.Application.Services.Users; -public sealed class UserService(IDbContextFactory contextFactory) : IUserService +public sealed class UserService(IDbContextFactory contextFactory, ITenantContextService tenantContext) : IUserService { public async Task SyncUserAsync(Guid userId, string email, CancellationToken cancellationToken = default) => await Result.Try((Func>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - // TODO: refactor to use TenantUser - var user = await context.Users.FirstOrDefaultAsync(u => u.Id == userId, cancellationToken); + var tenantUser = await context.TenantUsers + .Include(i => i.User) + .FirstOrDefaultAsync(u => u.UserId == userId, cancellationToken); - // TODO: refactor to use TenantUser - // TODO: Also add to TenantUser - if (user is null) + if (tenantUser is null) + { context.Users.Add(new Domain.Entities.User { Id = userId, @@ -27,12 +28,22 @@ public sealed class UserService(IDbContextFactory contextF Status = ActivityStatus.Active, LastLoginAt = DateTime.UtcNow }); + + context.TenantUsers.Add(new Domain.Entities.TenantUser + { + CreatedAt = DateTime.UtcNow, + CreatedBy = userId, + Status = ActivityStatus.Active, + TenantId = tenantContext.TenantId, + UserId = userId + }); + } else { - user!.Email = email; - user.LastLoginAt = DateTime.UtcNow; + tenantUser.User!.Email = email; + tenantUser.User.LastLoginAt = DateTime.UtcNow; - context.Users.Update(user); + context.Users.Update(tenantUser.User); } return Result.OkIf(await context.SaveChangesAsync(cancellationToken) > 0, CreateError.New); @@ -43,32 +54,29 @@ public sealed class UserService(IDbContextFactory contextF { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - // TODO: refactor to use TenantUser - var query = context.Users.AsNoTracking(); + var query = context.TenantUsers.Include(i => i.User).AsNoTracking(); - // TODO: refactor to use TenantUser if (request.Status.HasValue) query = query.Where(u => u.Status == request.Status.Value); if (!string.IsNullOrWhiteSpace(request.Email)) - query = query.Where(u => u.Email != null && u.Email.Contains(request.Email)); + query = query.Where(u => u.User!.Email != null && u.User!.Email.Contains(request.Email)); if (!string.IsNullOrWhiteSpace(request.SortBy)) query = request.SortBy.ToLowerInvariant() switch { - "email" => request.SortDescending ? query.OrderByDescending(u => u.Email) : query.OrderBy(u => u.Email), - "lastloginat" => request.SortDescending ? query.OrderByDescending(u => u.LastLoginAt) : query.OrderBy(u => u.LastLoginAt), + "email" => request.SortDescending ? query.OrderByDescending(u => u.User!.Email) : query.OrderBy(u => u.User!.Email), + "lastloginat" => request.SortDescending ? query.OrderByDescending(u => u.User!.LastLoginAt) : query.OrderBy(u => u.User!.LastLoginAt), "status" => request.SortDescending ? query.OrderByDescending(u => u.Status) : query.OrderBy(u => u.Status), _ => request.SortDescending ? query.OrderByDescending(u => u.Id) : query.OrderBy(u => u.Id) }; else query = query.OrderBy(u => u.Id); - // TODO: refactor to use TenantUser var users = await query.Skip((pagination.Page - 1) * pagination.PageSize) .Take(pagination.PageSize).ToListAsync(cancellationToken); - return Result.Ok(users.Select(u => u.Map()).ToArray()); + return Result.Ok(users.Select(u => u.User!.Map()).ToArray()); })); public async Task UpdateUserStatusAsync(Guid userId, ActivityStatus status, CancellationToken cancellationToken = default) => @@ -76,9 +84,13 @@ public sealed class UserService(IDbContextFactory contextF { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - // TODO: Update TenantUser status as well - var changedTotal = await context.Users - .Where(f => f.Id == userId) + var changedTotal = await context.TenantUsers + .Include(i => i.User) + .Where(f => f.UserId == userId) + .ExecuteUpdateAsync(f => f + .SetProperty(u => u.Status, status), cancellationToken); + + changedTotal += await context.Users.Where(f => f.Id == userId) .ExecuteUpdateAsync(f => f.SetProperty(u => u.Status, status), cancellationToken); return Result.OkIf(changedTotal > 0, UpdateError.New); @@ -89,11 +101,11 @@ public sealed class UserService(IDbContextFactory contextF { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); - // TODO: refactor to use TenantUser - var user = await context.Users.AsNoTracking() - .FirstOrDefaultAsync(f => f.Id == userId, cancellationToken); + var tenantUser = await context.TenantUsers.AsNoTracking() + .Include(i => i.User) + .FirstOrDefaultAsync(f => f.UserId == userId, cancellationToken); - return Result.FailIf(user == null, NotFoundError.New) - .ToResult(user?.Map()!); + return Result.FailIf(tenantUser == null, NotFoundError.New) + .ToResult(tenantUser!.User?.Map()!); })); }