#nullable enable using Abp.Domain.Repositories; using Abp.Domain.Uow; using Abp.Linq; using Abp.UI; using VberZero.BaseSystem.Organizations; using VberZero.DomainService; namespace VberZero.Organizations; /// /// 为组织单位执行域逻辑。 /// public class OrganizationUnitManager : VzDomainServiceBase { protected IRepository OrganizationUnitRepository { get; private set; } public IAsyncQueryableExecuter AsyncQueryableExecuter { get; set; } public OrganizationUnitManager(IRepository organizationUnitRepository) { OrganizationUnitRepository = organizationUnitRepository; AsyncQueryableExecuter = NullAsyncQueryableExecuter.Instance; } public virtual async Task CreateAsync(OrganizationUnit organizationUnit) { using var uow = UnitOfWorkManager.Begin(); organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); await ValidateOrganizationUnitAsync(organizationUnit); await OrganizationUnitRepository.InsertAsync(organizationUnit); await uow.CompleteAsync(); } public virtual void Create(OrganizationUnit organizationUnit) { using var uow = UnitOfWorkManager.Begin(); organizationUnit.Code = GetNextChildCode(organizationUnit.ParentId); ValidateOrganizationUnit(organizationUnit); OrganizationUnitRepository.Insert(organizationUnit); uow.Complete(); } public virtual async Task UpdateAsync(OrganizationUnit organizationUnit) { await ValidateOrganizationUnitAsync(organizationUnit); await OrganizationUnitRepository.UpdateAsync(organizationUnit); } public virtual void Update(OrganizationUnit organizationUnit) { ValidateOrganizationUnit(organizationUnit); OrganizationUnitRepository.Update(organizationUnit); } public virtual async Task GetNextChildCodeAsync(long? parentId) { var lastChild = await GetLastChildOrNullAsync(parentId); if (lastChild == null) { var parentCode = parentId != null ? await GetPathAsync(parentId.Value) : null; return OrganizationUnit.AppendCode(parentCode, OrganizationUnit.CreateCode(1)); } return OrganizationUnit.CalculateNextCode(lastChild.Code); } public virtual string? GetNextChildCode(long? parentId) { var lastChild = GetLastChildOrNull(parentId); if (lastChild == null) { var parentCode = parentId != null ? GetPath(parentId.Value) : null; return OrganizationUnit.AppendCode(parentCode, OrganizationUnit.CreateCode(1)); } return OrganizationUnit.CalculateNextCode(lastChild.Code); } public virtual async Task GetLastChildOrNullAsync(long? parentId) { var query = OrganizationUnitRepository.GetAll() .Where(ou => ou.ParentId == parentId) .OrderByDescending(ou => ou.Code); return await AsyncQueryableExecuter.FirstOrDefaultAsync(query); } public virtual OrganizationUnit? GetLastChildOrNull(long? parentId) { var query = OrganizationUnitRepository.GetAll() .Where(ou => ou.ParentId == parentId) .OrderByDescending(ou => ou.Code); return query.FirstOrDefault(); } public virtual async Task GetPathAsync(long id) { return (await OrganizationUnitRepository.GetAsync(id)).Path; } public virtual string GetPath(long id) { return OrganizationUnitRepository.Get(id).Path; } public virtual async Task DeleteAsync(long id) { using var uow = UnitOfWorkManager.Begin(); var children = await FindChildrenAsync(id, true); foreach (var child in children) { await OrganizationUnitRepository.DeleteAsync(child); } await OrganizationUnitRepository.DeleteAsync(id); await uow.CompleteAsync(); } public virtual void Delete(long id) { using var uow = UnitOfWorkManager.Begin(); var children = FindChildren(id, true); foreach (var child in children) { OrganizationUnitRepository.Delete(child); } OrganizationUnitRepository.Delete(id); uow.Complete(); } public virtual async Task MoveAsync(long id, long? parentId) { using var uow = UnitOfWorkManager.Begin(); var organizationUnit = await OrganizationUnitRepository.GetAsync(id); if (organizationUnit.ParentId == parentId) { await uow.CompleteAsync(); return; } //Should find children before Code change var children = await FindChildrenAsync(id, true); //Store old code of OU var oldCode = organizationUnit.Code; //Move OU organizationUnit.Code = await GetNextChildCodeAsync(parentId); organizationUnit.ParentId = parentId; await ValidateOrganizationUnitAsync(organizationUnit); //Update Children Codes foreach (var child in children) { child.Code = OrganizationUnit.AppendCode(organizationUnit.Code, OrganizationUnit.GetRelativeCode(child.Code, oldCode)); } await uow.CompleteAsync(); } public virtual void Move(long id, long? parentId) { UnitOfWorkManager.WithUnitOfWork(() => { var organizationUnit = OrganizationUnitRepository.Get(id); if (organizationUnit.ParentId == parentId) { return; } //Should find children before Code change var children = FindChildren(id, true); //Store old code of OU var oldCode = organizationUnit.Code; //Move OU organizationUnit.Code = GetNextChildCode(parentId); organizationUnit.ParentId = parentId; ValidateOrganizationUnit(organizationUnit); //Update Children Codes foreach (var child in children) { child.Code = OrganizationUnit.AppendCode(organizationUnit.Code, OrganizationUnit.GetRelativeCode(child.Code, oldCode)); } }); } public async Task> FindChildrenAsync(long? parentId, bool recursive = false) { if (!recursive) { return await OrganizationUnitRepository.GetAllListAsync(ou => ou.ParentId == parentId); } if (!parentId.HasValue) { return await OrganizationUnitRepository.GetAllListAsync(); } var parentPath = await GetPathAsync(parentId.Value); return await OrganizationUnitRepository.GetAllListAsync( ou => parentPath != null && ou.Path.StartsWith(parentPath) && ou.Id != parentId.Value ); } public List FindChildren(long? parentId, bool recursive = false) { if (!recursive) { return OrganizationUnitRepository.GetAllList(ou => ou.ParentId == parentId); } if (!parentId.HasValue) { return OrganizationUnitRepository.GetAllList(); } var path = GetPath(parentId.Value); return OrganizationUnitRepository.GetAllList( ou => path != null && ou.Path.StartsWith(path) && ou.Id != parentId.Value ); } protected virtual async Task ValidateOrganizationUnitAsync(OrganizationUnit organizationUnit) { var siblings = (await FindChildrenAsync(organizationUnit.ParentId)) .Where(ou => ou.Id != organizationUnit.Id) .ToList(); if (siblings.Any(ou => ou.DisplayName == organizationUnit.DisplayName)) { throw new UserFriendlyException(L("OrganizationUnitDuplicateDisplayNameWarning", organizationUnit.DisplayName)); } } protected virtual void ValidateOrganizationUnit(OrganizationUnit organizationUnit) { var siblings = (FindChildren(organizationUnit.ParentId)) .Where(ou => ou.Id != organizationUnit.Id) .ToList(); if (siblings.Any(ou => ou.DisplayName == organizationUnit.DisplayName)) { throw new UserFriendlyException(L("OrganizationUnitDuplicateDisplayNameWarning", organizationUnit.DisplayName)); } } }