#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));
}
}
}