diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs index a9a92e9e43..b1c1df1676 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IOrganizationUnitRepository.cs @@ -110,6 +110,7 @@ public interface IOrganizationUnitRepository : IBasicRepository GetMembersCountAsync( OrganizationUnit organizationUnit, string filter = null, + bool includeChildren = false, CancellationToken cancellationToken = default ); diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs index 03649b3c73..1af35eafcc 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs @@ -231,9 +231,10 @@ public class EfCoreOrganizationUnitRepository public virtual async Task GetMembersCountAsync( OrganizationUnit organizationUnit, string filter = null, + bool includeChildren = false, CancellationToken cancellationToken = default) { - var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, includeChildren); return await query.CountAsync(GetCancellationToken(cancellationToken)); } @@ -324,14 +325,33 @@ public class EfCoreOrganizationUnitRepository dbContext.Set().RemoveRange(ouMembersQuery); } - protected virtual async Task> CreateGetMembersFilteredQueryAsync(OrganizationUnit organizationUnit, string filter = null) + protected virtual async Task> CreateGetMembersFilteredQueryAsync( + OrganizationUnit organizationUnit, + string filter = null, + bool includeChildren = false) { var dbContext = await GetDbContextAsync(); - var query = from userOu in dbContext.Set() - join user in dbContext.Users on userOu.UserId equals user.Id - where userOu.OrganizationUnitId == organizationUnit.Id - select user; + IQueryable query; + if (includeChildren) + { + var childrenIds = await (await GetDbSetAsync()) + .Where(ou => ou.Code.StartsWith(organizationUnit.Code)) + .Select(x => x.Id) + .ToListAsync(); + + query = from userOu in dbContext.Set() + join user in dbContext.Users on userOu.UserId equals user.Id + where childrenIds.Contains(userOu.OrganizationUnitId) + select user; + } + else + { + query = from userOu in dbContext.Set() + join user in dbContext.Users on userOu.UserId equals user.Id + where userOu.OrganizationUnitId == organizationUnit.Id + select user; + } if (!filter.IsNullOrWhiteSpace()) { diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs index 78838c9c6c..5515015438 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoOrganizationUnitRepository.cs @@ -193,7 +193,7 @@ public class MongoOrganizationUnitRepository CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, false, cancellationToken); return await query .OrderBy(sorting.IsNullOrEmpty() ? nameof(IdentityUser.UserName) : sorting) .As>() @@ -212,10 +212,11 @@ public class MongoOrganizationUnitRepository public virtual async Task GetMembersCountAsync( OrganizationUnit organizationUnit, string filter = null, + bool includeChildren = false, CancellationToken cancellationToken = default) { cancellationToken = GetCancellationToken(cancellationToken); - var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, cancellationToken); + var query = await CreateGetMembersFilteredQueryAsync(organizationUnit, filter, includeChildren, cancellationToken); return await query.CountAsync(cancellationToken); } @@ -286,8 +287,27 @@ public class MongoOrganizationUnitRepository protected virtual async Task> CreateGetMembersFilteredQueryAsync( OrganizationUnit organizationUnit, string filter = null, + bool includeChildren = false, CancellationToken cancellationToken = default) { + if (includeChildren) + { + var childrenIds = await (await GetMongoQueryableAsync(cancellationToken)) + .Where(ou => ou.Code.StartsWith(organizationUnit.Code)) + .Select(ou => ou.Id) + .ToListAsync(GetCancellationToken(cancellationToken)); + + return (await GetMongoQueryableAsync(cancellationToken)) + .Where(u => u.OrganizationUnits.Any(uou => childrenIds.Contains(uou.OrganizationUnitId))) + .WhereIf>( + !filter.IsNullOrWhiteSpace(), + u => + u.UserName.Contains(filter) || + u.Email.Contains(filter) || + (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) + ); + } + return (await GetMongoQueryableAsync(cancellationToken)) .Where(u => u.OrganizationUnits.Any(uou => uou.OrganizationUnitId == organizationUnit.Id)) .WhereIf>( diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs index 8746c3a1fd..ce78147ace 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/OrganizationUnitRepository_Tests.cs @@ -267,6 +267,10 @@ public abstract class OrganizationUnitRepository_Tests : AbpIden var usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou); usersCount.ShouldBeGreaterThan(1); + + usersCount = await _organizationUnitRepository.GetMembersCountAsync(ou, includeChildren: true); + + usersCount.ShouldBeGreaterThanOrEqualTo(2); } [Fact] @@ -301,6 +305,9 @@ public abstract class OrganizationUnitRepository_Tests : AbpIden await _organizationUnitRepository.RemoveAllMembersAsync(ou); var newCount = await _organizationUnitRepository.GetMembersCountAsync(ou); newCount.ShouldBe(0); + + newCount = await _organizationUnitRepository.GetMembersCountAsync(ou, includeChildren: true); + newCount.ShouldBe(0); } [Fact]