using Microsoft.EntityFrameworkCore; using Mws.Application.Common.Repositories; using Mws.Domain.Projects; namespace Mws.Infrastructure.Persistence.Repositories; public class ProjectRepository(AppDbContext db) : RepositoryBase(db), IProjectRepository { public Task GetByIdAsync(Guid id, CancellationToken ct = default) => Set.FirstOrDefaultAsync(p => p.Id == id, ct); public Task GetForUserAsync(Guid userId, Guid projectId, CancellationToken ct = default) => Set.FirstOrDefaultAsync(p => p.Id == projectId && p.Members.Any(m => m.UserId == userId), ct); public Task> GetForUserAsync(Guid userId, CancellationToken ct = default) => Set.Where(p => p.Members.Any(m => m.UserId == userId)) .OrderByDescending(p => p.UpdatedAt) .ToListAsync(ct); public Task> SearchForUserAsync(Guid userId, string? term, CancellationToken ct = default) { var query = Set.Where(p => p.Members.Any(m => m.UserId == userId)); if (!string.IsNullOrWhiteSpace(term)) { var lower = term.Trim().ToLower(); query = query.Where(p => p.Name.ToLower().Contains(lower)); } return query.OrderByDescending(p => p.UpdatedAt).ToListAsync(ct); } public Task CountMembersAsync(Guid projectId, CancellationToken ct = default) => Db.ProjectMembers.CountAsync(m => m.ProjectId == projectId, ct); public Task IsMemberAsync(Guid projectId, Guid userId, CancellationToken ct = default) => Db.ProjectMembers.AnyAsync(m => m.ProjectId == projectId && m.UserId == userId, ct); public Task GetMemberRoleAsync(Guid projectId, Guid userId, CancellationToken ct = default) => Db.ProjectMembers .Where(m => m.ProjectId == projectId && m.UserId == userId) .Select(m => (MemberRole?)m.Role) .SingleOrDefaultAsync(ct); public Task GetMemberAsync(Guid projectId, Guid userId, CancellationToken ct = default) => Db.ProjectMembers.FirstOrDefaultAsync(m => m.ProjectId == projectId && m.UserId == userId, ct); public Task GetMemberWithUserAsync(Guid projectId, Guid userId, CancellationToken ct = default) => Db.ProjectMembers.Include(m => m.User).FirstOrDefaultAsync(m => m.ProjectId == projectId && m.UserId == userId, ct); public Task> GetMembersWithUserAsync(Guid projectId, CancellationToken ct = default) => Db.ProjectMembers .Where(m => m.ProjectId == projectId) .Include(m => m.User) .OrderByDescending(m => m.Role) .ThenBy(m => m.User.DisplayName) .ToListAsync(ct); public Task CountOwnersAsync(Guid projectId, CancellationToken ct = default) => Db.ProjectMembers.CountAsync(m => m.ProjectId == projectId && m.Role == MemberRole.Owner, ct); public Task> GetProjectIdsForUserAsync(Guid userId, CancellationToken ct = default) => Set.Where(p => p.Members.Any(m => m.UserId == userId)).Select(p => p.Id).ToListAsync(ct); public Task> GetOwnedProjectIdsAsync(Guid userId, CancellationToken ct = default) => Db.ProjectMembers.Where(m => m.UserId == userId && m.Role == MemberRole.Owner).Select(m => m.ProjectId).ToListAsync(ct); public Task> GetDocumentViewableProjectIdsAsync(Guid userId, CancellationToken ct = default) => Db.ProjectMembers .Where(m => m.UserId == userId && (m.Role == MemberRole.Owner || Db.ProjectMemberPermissions.Any(p => p.ProjectId == m.ProjectId && p.UserId == userId && p.Screen == ProjectPermissionScreens.Documents && p.CanView))) .Select(m => m.ProjectId) .ToListAsync(ct); public void AddMember(ProjectMember member) => Db.ProjectMembers.Add(member); public void RemoveMember(ProjectMember member) => Db.ProjectMembers.Remove(member); public Task GetMemberPermissionAsync(Guid projectId, Guid userId, string screen, CancellationToken ct = default) => Db.ProjectMemberPermissions.FirstOrDefaultAsync(p => p.ProjectId == projectId && p.UserId == userId && p.Screen == screen, ct); public Task> GetMemberPermissionsAsync(Guid projectId, string screen, CancellationToken ct = default) => Db.ProjectMemberPermissions .Where(p => p.ProjectId == projectId && p.Screen == screen) .ToDictionaryAsync(p => p.UserId, ct); public void AddMemberPermission(ProjectMemberPermission permission) => Db.ProjectMemberPermissions.Add(permission); }