Laservall_manager_system/VOL.HR/Services/DeptSync/Partial/HR_DeptSyncService.cs

246 lines
9.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*所有关于HR_DeptSync类的业务代码应在此处编写
*可使用repository.调用常用方法获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*HR_DeptSyncService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using VOL.Core.DBManager;
using VOL.Core.Extensions;
using VOL.DingTalk.Models.Biz;
using VOL.DingTalk.Services.Biz;
using VOL.Entity.DomainModels.DeptShip.SystemDept;
using VOL.HR.IRepositories;
using VOL.YSErp.Models.Biz;
using VOL.YSErp.Services.Biz;
namespace VOL.HR.Services
{
public partial class HR_DeptSyncService
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IHR_DeptSyncRepository _repository;//访问数据库
private readonly IHR_DeptShipRepository _shipRepository;//访问数据库
private readonly DingTalkService _dingTalkService;
private readonly YSERPService _ysService;
[ActivatorUtilitiesConstructor]
private Core.CacheManager.ICacheService _cacheService;
[ActivatorUtilitiesConstructor]
public HR_DeptSyncService(
IHR_DeptSyncRepository dbRepository,
IHR_DeptShipRepository shipDbRepository,
IHttpContextAccessor httpContextAccessor,
Core.CacheManager.ICacheService cacheService
)
: base(dbRepository)
{
_httpContextAccessor = httpContextAccessor;
_repository = dbRepository;
_shipRepository = shipDbRepository;
//多租户会用到这init代码其他情况可以不用
//base.Init(dbRepository);
_cacheService = cacheService;
_dingTalkService = new DingTalkService(new DingTalk.Models.SystemToken(), new DingTalk.Models.DingTalkConfig());
_ysService = new YSERPService(new YSErp.Models.SystemToken(), new YSErp.Models.YSConfig());
}
public async Task CacheYSDepartments()
{
var ysDepts = await _ysService.GetAllDepartmentsAsync();
if(ysDepts != null)
{
_cacheService.Remove("YS_DEPT_CACHE");
_cacheService.Add("YS_DEPT_CACHE", JsonConvert.SerializeObject(ysDepts), 60 * 60);
var db = DBServerProvider.SqlSugarClient;
// 自动建表
db.CodeFirst.InitTables<HR_YSDept>();
try
{
db.BeginTran();
// 通过缓存直接反序列化转换对象
var deptsData = _cacheService.Get<List<HR_YSDept>>("YS_DEPT_CACHE");
// 清空再插入
db.DbMaintenance.TruncateTable<HR_YSDept>();
db.Fastest<HR_YSDept>().BulkCopy(deptsData);
db.CommitTran();
}
catch (Exception ex)
{
db.RollbackTran();
throw;
}
}
}
public async Task CacheDingTalkDepartments()
{
var depts = await _dingTalkService.GetSubDepartmentsAsync();
if (depts != null)
{
_cacheService.Remove("DINGTALK_DEPT_CACHE");
_cacheService.Add("DINGTALK_DEPT_CACHE", JsonConvert.SerializeObject(depts), 60 * 60);
var db = DBServerProvider.SqlSugarClient;
try
{
// 自动建表
db.CodeFirst.InitTables<HR_DingTalkDept>();
db.BeginTran();
// 通过缓存直接反序列化转换对象
var deptsData = _cacheService.Get<List<HR_DingTalkDept>>("DINGTALK_DEPT_CACHE");
// 清空再插入
db.DbMaintenance.TruncateTable<HR_DingTalkDept>();
db.Fastest<HR_DingTalkDept>().BulkCopy(deptsData);
db.CommitTran();
}
catch (Exception ex)
{
db.RollbackTran();
throw;
}
}
}
public async Task CreateDingTalkDept(DingTalkDepartment dept)
{
}
public async Task SyncYSERPDeptToDingTalk()
{
var ysDepts = await _ysService.GetAllDepartmentsAsync();
//var depts = await _dingTalkService.GetSubDepartmentsAsync();
//var deptShip = _shipRepository.Find(i => i.IsRoot ?? false);
if(ysDepts.Count != 0)
{
var rootDept = _shipRepository.Find(i => i.IsRoot ?? false).FirstOrDefault();
BuildYSDeptTree(ysDepts).Where(i => i.id == rootDept.YSDeptId).ToList().ForEach(CreateOrUpdateDingTalkDept);
}
}
public void CreateOrUpdateDingTalkDept(YSERPDepartment ysDept)
{
var deptShip = _shipRepository.Find(i => i.YSDeptId == ysDept.id).FirstOrDefault();
if (deptShip != null && (!deptShip.IsRoot ?? true))
{
}
else
{
if (string.IsNullOrEmpty(ysDept.parentid))
{
var rootDept = _shipRepository.Find(i => i.IsRoot ?? false).FirstOrDefault();
var pId = int.Parse(rootDept?.DingTalkDeptId ?? "1");
try
{
_dingTalkService.CreateDingTalkDept(new DingTalkDepartment
{
parent_id = pId,
name = ysDept.name
});
}
catch (Exception)
{
throw;
}
}
}
}
/// <summary>
/// 将扁平的 YSERP 部门列表转换为树形结构
/// 规则:
/// - parentid 为 null/empty/"0" 或者父节点在列表中不存在时,视为根节点
/// - 避免将节点添加为自己的子节点
/// - 会初始化每个节点的 subDepts 列表并按 displayorder 排序(然后按 name 作为次级排序)
/// </summary>
/// <param name="flatList">扁平部门列表</param>
/// <returns>树形结构的根节点列表</returns>
private List<YSERPDepartment> BuildYSDeptTree(List<YSERPDepartment> flatList)
{
if (flatList == null || flatList.Count == 0)
return new List<YSERPDepartment>();
// 初始化 subDepts防止 null 引发 NRE
foreach (var d in flatList)
{
if (d.subDepts == null)
d.subDepts = new List<YSERPDepartment>();
else
d.subDepts.Clear();
}
// 建立 id -> node 的字典(只包含有 id 的节点)
var dict = flatList
.Where(d => !string.IsNullOrEmpty(d.id))
.GroupBy(d => d.id) // 防止重复 id 导致异常,取第一个
.ToDictionary(g => g.Key, g => g.First());
var roots = new List<YSERPDepartment>();
foreach (var node in flatList)
{
// 视为根的条件parentid 为空、等于 "0"、或父节点不存在、或者 parentid 与自身 id 相同(防止自引用)
if (string.IsNullOrEmpty(node.parentid) || node.parentid == "0" ||
!dict.ContainsKey(node.parentid) || node.parentid == node.id)
{
roots.Add(node);
}
else
{
// 将当前节点添加到父节点的子集合
if (dict.TryGetValue(node.parentid, out var parent))
{
if (parent.subDepts == null)
parent.subDepts = new List<YSERPDepartment>();
parent.subDepts.Add(node);
}
else
{
// 找不到父节点视为根
roots.Add(node);
}
}
}
// 递归排序子节点(按 displayorder再按 name
void SortRecursively(List<YSERPDepartment> list)
{
if (list == null || list.Count == 0) return;
list.Sort((a, b) =>
{
var c = a.displayorder.CompareTo(b.displayorder);
if (c == 0) return string.Compare(a.name, b.name, StringComparison.Ordinal);
return c;
});
foreach (var item in list)
{
SortRecursively(item.subDepts);
}
}
SortRecursively(roots);
return roots;
}
}
}