using JNPF.Common.Const;
using JNPF.Common.Core.Manager;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Filter;
using JNPF.Common.Manager;
using JNPF.Common.Security;
using JNPF.DependencyInjection;
using JNPF.DynamicApiController;
using JNPF.FriendlyException;
using JNPF.Systems.Entitys.Dto.Position;
using JNPF.Systems.Entitys.Permission;
using JNPF.Systems.Entitys.System;
using JNPF.Systems.Interfaces.Permission;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
namespace JNPF.Systems;
///
/// 业务实现:岗位管理.
/// 版 本:V3.2.0
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
/// 日 期:2021.06.07.
///
[ApiDescriptionSettings(Tag = "Permission", Name = "Position", Order = 162)]
[Route("api/Permission/[controller]")]
public class PositionService : IPositionService, IDynamicApiController, ITransient
{
///
/// 基础仓储.
///
private readonly ISqlSugarRepository _repository;
///
/// 组织管理.
///
private readonly IOrganizeService _organizeService;
///
/// 缓存管理器.
///
private readonly ICacheManager _cacheManager;
///
/// 用户管理器.
///
private readonly IUserManager _userManager;
///
/// 初始化一个类型的新实例.
///
public PositionService(
ISqlSugarRepository repository,
IOrganizeService organizeService,
ICacheManager cacheManager,
IUserManager userManager)
{
_repository = repository;
_organizeService = organizeService;
_cacheManager = cacheManager;
_userManager = userManager;
}
#region GET
///
/// 获取列表 根据organizeId.
///
/// 参数.
///
[HttpGet("getList/{organizeId}")]
public async Task GetListByOrganizeId(string organizeId)
{
List? oid = new List();
if (!string.IsNullOrWhiteSpace(organizeId))
{
// 获取组织下的所有组织 id 集合
List? oentity = await _repository.AsSugarClient().Queryable().ToChildListAsync(x => x.ParentId, organizeId);
oid = oentity.Select(x => x.Id).ToList();
}
List? data = await _repository.AsSugarClient().Queryable(
(a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
// 组织机构
.WhereIF(!string.IsNullOrWhiteSpace(organizeId), a => oid.Contains(a.OrganizeId))
.Where(a => a.DeleteMark == null).OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).OrderBy(a => a.LastModifyTime, OrderByType.Desc)
.Select((a, b, c) => new PositionListOutput
{
id = a.Id,
fullName = a.FullName,
enCode = a.EnCode,
type = c.FullName,
department = b.FullName,
enabledMark = a.EnabledMark,
creatorTime = a.CreatorTime,
description = a.Description,
sortCode = a.SortCode
}).ToListAsync();
return data.OrderBy(x => x.sortCode).ToList();
}
///
/// 获取列表.
///
/// 参数.
///
[HttpGet("")]
public async Task GetList([FromQuery] PositionListQuery input)
{
if (input.organizeId == "0") input.organizeId = _userManager.User.OrganizeId;
// 获取分级管理组织
var dataScope = _userManager.DataScope.Where(x => x.Select).Select(x => x.organizeId).Distinct().ToList();
List? childOrgIds = new List();
if (input.organizeId.IsNotEmptyOrNull())
{
childOrgIds.Add(input.organizeId);
// 根据组织Id 获取所有子组织Id集合
childOrgIds.AddRange(_repository.AsSugarClient().Queryable().ToChildList(x => x.ParentId, input.organizeId).Select(x => x.Id).ToList());
childOrgIds = childOrgIds.Distinct().ToList();
}
var data = await _repository.AsSugarClient().Queryable(
(a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
// 组织机构
.WhereIF(childOrgIds.Any(), a => childOrgIds.Contains(a.OrganizeId))
.WhereIF(!_userManager.IsAdministrator, a => dataScope.Contains(a.OrganizeId))
// 关键字(名称、编码)
.WhereIF(!input.keyword.IsNullOrEmpty(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
.Where(a => a.DeleteMark == null).OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).OrderBy(a => a.LastModifyTime, OrderByType.Desc)
.Select((a, b, c) => new PositionListOutput
{
id = a.Id,
fullName = a.FullName,
enCode = a.EnCode,
type = c.FullName,
department = b.FullName,
organizeId = b.OrganizeIdTree,
enabledMark = a.EnabledMark,
creatorTime = a.CreatorTime,
description = a.Description,
sortCode = a.SortCode
}).ToPagedListAsync(input.currentPage, input.pageSize);
// 处理组织树 名称
List? orgList = _organizeService.GetOrgListTreeName();
#region 处理岗位所属组织树
foreach (PositionListOutput? item in data.list)
{
// 获取用户组织集合
item.department = orgList.Where(x => x.Id == item.organizeId.Split(",").LastOrDefault()).Select(x => x.Description).FirstOrDefault();
}
#endregion
return PageResult.SqlSugarPageResult(data);
}
///
/// 获取列表.
///
///
[HttpGet("All")]
public async Task GetList()
{
List? data = await _repository.AsSugarClient().Queryable((a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
.Where(a => a.DeleteMark == null && a.EnabledMark == 1).OrderBy(a => a.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).OrderBy(a => a.LastModifyTime, OrderByType.Desc)
.Select((a, b, c) => new PositionListOutput
{
id = a.Id,
fullName = a.FullName,
enCode = a.EnCode,
type = c.FullName,
department = b.FullName,
enabledMark = a.EnabledMark,
creatorTime = a.CreatorTime,
description = a.Description,
sortCode = a.SortCode
}).ToListAsync();
return new { list = data.OrderBy(x => x.sortCode).ToList() };
}
///
/// 获取下拉框(公司+部门+岗位).
///
///
[HttpGet("Selector")]
public async Task GetSelector()
{
var orgInfoList = _organizeService.GetOrgListTreeName();
List? organizeList = await _organizeService.GetListAsync();
List? positionList = await _repository.AsQueryable().Where(t => t.EnabledMark == 1 && t.DeleteMark == null)
.OrderBy(o => o.SortCode).OrderBy(a => a.CreatorTime, OrderByType.Desc).OrderBy(a => a.LastModifyTime, OrderByType.Desc).ToListAsync();
List? treeList = new List();
organizeList.ForEach(item =>
{
treeList.Add(
new PositionSelectorOutput
{
id = item.Id,
parentId = item.ParentId,
fullName = item.FullName,
enabledMark = item.EnabledMark,
icon = item.Category.Equals("department") ? "icon-ym icon-ym-tree-department1" : "icon-ym icon-ym-tree-organization3",
type = item.Category,
organize = orgInfoList.Find(x => x.Id.Equals(item.Id)).Description,
organizeIdTree = item.OrganizeIdTree,
num = positionList.Count(x => x.OrganizeId.Equals(item.Id)),
sortCode = item.SortCode
});
});
positionList.ForEach(item =>
{
treeList.Add(
new PositionSelectorOutput
{
id = item.Id,
parentId = item.OrganizeId,
fullName = item.FullName,
enabledMark = item.EnabledMark,
organize = orgInfoList.FirstOrDefault(x => x.Id.Equals(item.OrganizeId))?.Description,
icon = "icon-ym icon-ym-tree-position1",
type = "position",
num = 1,
sortCode = -2
});
});
treeList.Where(x => !x.type.Equals("position")).ToList().ForEach(item =>
{
if (treeList.Any(x => !x.type.Equals("position") && x.num > 0 && x.organizeIdTree.Contains(item.organizeIdTree))) item.num = 1;
else item.num = 0;
});
return new { list = treeList.Where(x => x.num > 0).OrderBy(x => x.sortCode).ToList().ToTree("-1") };
}
///
/// 获取信息.
///
/// 主键.
///
[HttpGet("{id}")]
public async Task GetInfo(string id)
{
PositionEntity? entity = await _repository.GetSingleAsync(p => p.Id == id);
var res = entity.Adapt();
res.organizeIdTree = (await _organizeService.GetInfoById(entity.OrganizeId)).OrganizeIdTree.Split(",").ToList();
return res;
}
#endregion
#region POST
///
/// 获取岗位列表 根据组织Id集合.
///
/// 参数.
///
[HttpPost("getListByOrgIds")]
public async Task GetListByOrgIds([FromBody] PositionListQuery input)
{
List? data = await _repository.AsSugarClient().Queryable(
(a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
.Where(a => input.organizeIds.Contains(a.OrganizeId) && a.DeleteMark == null && a.EnabledMark == 1).OrderBy(a => a.SortCode)
.Select((a, b, c) => new PositionListOutput
{
id = a.Id,
type = "position",
parentId = b.Id,
fullName = a.FullName,
enabledMark = a.EnabledMark,
creatorTime = a.CreatorTime,
sortCode = -2,
isLeaf = true
}).ToListAsync();
// 获取所有组织
List? allOrgList = await _repository.AsSugarClient().Queryable().OrderBy(x => x.CreatorTime, OrderByType.Asc).ToListAsync();
allOrgList.ForEach(item =>
{
item.ParentId = "0";
if (item.OrganizeIdTree == null || item.OrganizeIdTree.Equals(string.Empty)) item.OrganizeIdTree = item.Id;
});
List? organizeList = allOrgList.Where(x => input.organizeIds.Contains(x.Id)).Select(x => new PositionListOutput()
{
id = x.Id,
type = x.Category,
parentId = "0",
fullName = string.Join("/", allOrgList.Where(all => x.OrganizeIdTree.Split(",").Contains(all.Id)).Select(x => x.FullName)),
num = data.Count(x => x.parentId == x.id)
}).ToList();
return new { list = organizeList.Union(data).OrderBy(x => x.sortCode).ToList().ToTree("0") };
}
///
/// 通过部门、岗位id获取岗位列表.
///
/// 参数.
///
[HttpPost("PositionCondition")]
public async Task PositionCondition([FromBody] PositionConditionInput input)
{
List? data = await _repository.AsSugarClient().Queryable(
(a, b, c) => new JoinQueryInfos(JoinType.Left, b.Id == a.OrganizeId, JoinType.Left, a.Type == c.EnCode && c.DictionaryTypeId == "dae93f2fd7cd4df999d32f8750fa6a1e"))
.Where(a => a.DeleteMark == null)
.Where(a => input.departIds.Contains(a.OrganizeId) || input.positionIds.Contains(a.Id))
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
.Select((a, b, c) => new PositionListOutput
{
id = a.Id,
organizeId = a.OrganizeId,
parentId = b.Id,
type = "position",
fullName = a.FullName,
enabledMark = a.EnabledMark,
creatorTime = a.CreatorTime,
icon = "icon-ym icon-ym-tree-position1",
sortCode = -2,
num = 1,
isLeaf = true
}).ToListAsync();
// 获取所有组织
List? allOrgList = _organizeService.GetOrgListTreeName();
List? organizeList = allOrgList.Where(x => data.Select(x => x.organizeId).Distinct().Contains(x.Id)).Select(x => new PositionListOutput()
{
id = x.Id,
type = x.Category,
parentId = x.ParentId.Equals("-1") ? "0" : x.ParentId,
icon = x.Category.Equals("department") ? "icon-ym icon-ym-tree-department1" : "icon-ym icon-ym-tree-organization3",
fullName = x.Description,
organizeId = x.OrganizeIdTree,
num = data.Count(xx => xx.parentId == x.Id),
sortCode = 99
}).ToList();
organizeList.OrderByDescending(x => x.organizeId.Length).ToList().ForEach(item =>
{
if (!organizeList.Any(x => item.parentId.Equals(x.id))) item.parentId = "0";
var pOrgTree = organizeList.Where(x => x.organizeId != item.organizeId && item.organizeId.Contains(x.organizeId)).FirstOrDefault()?.fullName;
if (organizeList.Any(x => item.parentId.Equals(x.id))) pOrgTree = organizeList.FirstOrDefault(x => item.parentId.Equals(x.id))?.fullName;
if (pOrgTree.IsNotEmptyOrNull() && item.organizeId.IsNotEmptyOrNull()) item.fullName = item.fullName.Replace(pOrgTree + "/", string.Empty);
});
organizeList.Where(x => !x.type.Equals("position")).ToList().ForEach(item =>
{
if (organizeList.Any(x => !x.type.Equals("position") && x.num > 0 && x.organizeId.Contains(item.organizeId))) item.num = 1;
else item.num = 0;
organizeList.Where(x => !x.type.Equals("position") && x.organizeId.Contains(item.organizeId) && x.organizeId != item.organizeId).ToList().ForEach(it =>
{
it.parentId = item.id;
});
});
return new { list = organizeList.Where(x => x.num > 0).ToList().Union(data).OrderBy(x => x.sortCode).ToList().ToTree("0") };
}
///
/// 新建.
///
/// 参数.
///
[HttpPost("")]
public async Task Create([FromBody] PositionCrInput input)
{
if (!_userManager.DataScope.Any(it => it.organizeId == input.organizeId && it.Add == true) && !_userManager.IsAdministrator)
throw Oops.Oh(ErrorCode.D1013);
if (await _repository.IsAnyAsync(p => p.OrganizeId == input.organizeId && p.FullName == input.fullName && p.DeleteMark == null))
throw Oops.Oh(ErrorCode.D6005);
if (await _repository.IsAnyAsync(p => p.EnCode == input.enCode && p.DeleteMark == null))
throw Oops.Oh(ErrorCode.D6000);
PositionEntity? entity = input.Adapt();
int isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
if (!(isOk > 0)) throw Oops.Oh(ErrorCode.D6001);
await DelPosition(string.Format("{0}_{1}", _userManager.TenantId, _userManager.UserId));
}
///
/// 删除.
///
/// 主键.
///
[HttpDelete("{id}")]
public async Task Delete(string id)
{
PositionEntity? entity = await _repository.GetSingleAsync(p => p.Id == id && p.DeleteMark == null);
if (!_userManager.DataScope.Any(it => it.organizeId == entity.OrganizeId && it.Delete == true) && !_userManager.IsAdministrator)
throw Oops.Oh(ErrorCode.D1013);
// 岗位下有用户不能删
if (await _repository.AsSugarClient().Queryable().AnyAsync(u => u.ObjectType == "Position" && u.ObjectId == id))
throw Oops.Oh(ErrorCode.D6007);
int isOk = await _repository.AsSugarClient().Updateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandAsync();
if (!(isOk > 0))
throw Oops.Oh(ErrorCode.D6002);
await DelPosition(string.Format("{0}_{1}", _userManager.TenantId, _userManager.UserId));
}
///
/// 更新.
///
/// 主键.
/// 参数.
///
[HttpPut("{id}")]
public async Task Update(string id, [FromBody] PositionUpInput input)
{
PositionEntity? oldEntity = await _repository.GetSingleAsync(it => it.Id == id);
if (oldEntity.OrganizeId != input.organizeId && !_userManager.DataScope.Any(it => it.organizeId == oldEntity.OrganizeId && it.Edit == true) && !_userManager.IsAdministrator)
throw Oops.Oh(ErrorCode.D1013);
if (!_userManager.DataScope.Any(it => it.organizeId == input.organizeId && it.Edit == true) && !_userManager.IsAdministrator)
throw Oops.Oh(ErrorCode.D1013);
if (await _repository.IsAnyAsync(p => p.OrganizeId == input.organizeId && p.FullName == input.fullName && p.DeleteMark == null && p.Id != id))
throw Oops.Oh(ErrorCode.D6005);
if (await _repository.IsAnyAsync(p => p.EnCode == input.enCode && p.DeleteMark == null && p.Id != id))
throw Oops.Oh(ErrorCode.D6000);
// 如果变更组织,该岗位下已存在成员,则不允许修改
if (input.organizeId != oldEntity.OrganizeId)
{
if (await _repository.AsSugarClient().Queryable().AnyAsync(u => u.ObjectType == "Position" && u.ObjectId == id))
throw Oops.Oh(ErrorCode.D6008);
}
PositionEntity? entity = input.Adapt();
int isOk = await _repository.AsSugarClient().Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();
if (!(isOk > 0))
throw Oops.Oh(ErrorCode.D6003);
await DelPosition(string.Format("{0}_{1}", _userManager.TenantId, _userManager.UserId));
}
///
/// 更新状态.
///
/// 主键.
///
[HttpPut("{id}/Actions/State")]
public async Task UpdateState(string id)
{
if (!_userManager.DataScope.Any(it => it.organizeId == id && it.Add == true) && !_userManager.IsAdministrator)
throw Oops.Oh(ErrorCode.D1013);
if (!await _repository.IsAnyAsync(r => r.Id == id && r.DeleteMark == null))
throw Oops.Oh(ErrorCode.D6006);
int isOk = await _repository.AsSugarClient().Updateable().UpdateColumns(it => new PositionEntity()
{
EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
LastModifyUserId = _userManager.UserId,
LastModifyTime = SqlFunc.GetDate()
}).Where(it => it.Id == id).ExecuteCommandAsync();
if (!(isOk > 0))
throw Oops.Oh(ErrorCode.D6004);
await DelPosition(string.Format("{0}_{1}", _userManager.TenantId, _userManager.UserId));
}
#endregion
#region PublicMethod
///
/// 获取信息.
///
/// 主键.
///
[NonAction]
public async Task GetInfoById(string id)
{
return await _repository.GetSingleAsync(p => p.Id == id);
}
///
/// 获取岗位列表.
///
///
[NonAction]
public async Task> GetListAsync()
{
return await _repository.AsQueryable().Where(u => u.DeleteMark == null).ToListAsync();
}
///
/// 名称.
///
/// 岗位ID组
///
[NonAction]
public string GetName(string ids)
{
if (ids.IsNullOrEmpty())
return string.Empty;
List? idList = ids.Split(",").ToList();
List? nameList = new List();
List? roleList = _repository.AsQueryable().Where(x => x.DeleteMark == null && x.EnabledMark == 1).ToList();
foreach (string item in idList)
{
var info = roleList.Find(x => x.Id == item);
if (info != null && info.FullName.IsNotEmptyOrNull())
{
nameList.Add(info.FullName);
}
}
return string.Join(",", nameList);
}
#endregion
#region PrivateMethod
///
/// 删除岗位缓存.
///
/// 适配多租户模式(userId:tenantId_userId).
///
private async Task DelPosition(string userId)
{
string? cacheKey = string.Format("{0}{1}", CommonConst.CACHEKEYPOSITION, userId);
await _cacheManager.DelAsync(cacheKey);
return await Task.FromResult(true);
}
#endregion
}