Files
jinko.yikatong/Src/Dlhis.Basic/Organization/Services/Implements/GainfoUpdateService.cs
2025-12-29 16:57:56 +08:00

554 lines
22 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.

using Dlhis.Basic.Common.Message.Requests;
using Dlhis.Basic.Common.Message.Services;
using Dlhis.Basic.Organization.Comparers;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums;
using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Sys.Entities;
using Dlhis.Entity.Sys.Enums;
using Dlhis.Jip.Api.Dto;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.Basic.Organization.Services.Implements;
public class GainfoUpdateService : IGainfoUpdateService
{
private readonly IDbContext _dbContext;
private readonly ILogger<GainfoUpdateService> _logger;
private readonly IJinkoSapService _jinkoSapService;
private readonly IGainfoPermissionService _gainfoPermissionService;
private readonly IJinkoApiService _dingTalkApi;
private readonly IIdentityUserSyncService _identityUserSyncService;
public GainfoUpdateService(IDbContext dbContext,
ILogger<GainfoUpdateService> logger,
IJinkoSapService jinkoSapService,
IGainfoPermissionService gainfoPermissionService,
IJinkoApiService dingTalkApi,
IIdentityUserSyncService identityUserSyncService)
{
_dbContext = dbContext;
_logger = logger;
_jinkoSapService = jinkoSapService;
_gainfoPermissionService = gainfoPermissionService;
_dingTalkApi = dingTalkApi;
_identityUserSyncService = identityUserSyncService;
}
public async Task TodoByWerkAsync(string werk)
{
var werkInfo = await _dbContext.Queryable<WerkEntity>().Where(x => x.Werk == werk).SingleAsync();
werkInfo.LastSyncStartTime = DateTime.Now;
werkInfo.HandleMessage = "任务执行中";
await _dbContext.UpdateAsync(werkInfo);
try
{
var personResp = await _jinkoSapService.GetPersonsByWerkAsync(werk);
var persons = personResp.Person.Items;
werkInfo.HandleMessage = "SAP人员数量" + persons.Count;
werkInfo.Total = persons.Count;
await _dbContext.UpdateAsync(werkInfo);
if (persons.Count > 0)
{
var modifiedPersons = await GetModifiedPersonAsync(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
werkInfo.HandleMessage = "SAP人员差异数量" + modifiedPersons.Count;
werkInfo.DiffNumber = modifiedPersons.Count;
await _dbContext.UpdateAsync(werkInfo);
if (modifiedPersons.Count > 0)
{
await SavePersonAsync(modifiedPersons);
}
}
werkInfo.HandleMessage = "同步结束";
werkInfo.LastSyncEndTime = DateTime.Now;
werkInfo.BackgroundJobKey = string.Empty;
await _dbContext.UpdateAsync(werkInfo);
}
catch (Exception ex)
{
_logger.LogError(ex, "{werk}同步处理异常:{message}", werk, ex.Message);
werkInfo.HandleMessage = ex.Message;
werkInfo.LastSyncEndTime = DateTime.Now;
werkInfo.BackgroundJobKey = string.Empty;
await _dbContext.UpdateAsync(werkInfo);
}
}
public async Task TodoByCodeAsync(string code)
{
_logger.LogInformation("SAP根据学工号同步开始:{code}", code);
try
{
var personResp = await _jinkoSapService.GetPersonsByCodeAsync(code);
var persons = personResp.Person.Items;
_logger.LogInformation("获取SAP人员数量为:{count}", persons.Count);
if (persons.Count > 0)
{
var modifiedPersons = await GetModifiedPersonAsync(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
_logger.LogInformation("SAP人员差异数量为:{count}", modifiedPersons.Count);
if (modifiedPersons.Count > 0)
{
await SavePersonAsync(modifiedPersons);
}
}
_logger.LogInformation("SAP根据学工号同步结束:{code}", code);
}
catch (Exception e)
{
_logger.LogError(e, "同步人员异常:{msg}", e.Message);
}
}
private async Task SavePersonAsync(List<SapPersonItem> persons)
{
var workCodes = persons.Select(x => x.ZWORKCODE).ToList();
var chunks = workCodes.Chunk(4000).ToList();
foreach (var searchCodes in chunks)
{
_logger.LogWarning("SAP分批处理Chunk数量:{count}", searchCodes.Length);
var existsWorkCodes = await _dbContext.Queryable<GainfoSapEntity>()
.Where(x => searchCodes.Contains(x.ename))
.Select(x => x.ename)
.ToListAsync();
var originUpdates = persons.Where(x => existsWorkCodes.Contains(x.ZWORKCODE)).ToList();
var existsUpdateWorkCodes = originUpdates.Select(x => x.ZWORKCODE).ToList();
var originInserts = persons.Where(x => searchCodes.Contains(x.ZWORKCODE)).Where(x => !existsUpdateWorkCodes.Contains(x.ZWORKCODE)).ToList();
var updates = ToGainfoSap(originUpdates);
var inserts = ToGainfoSap(originInserts);
foreach (var item in inserts)
{
try
{
await InsertPersonAsync(item);
}
catch (Exception ex)
{
_logger.LogError(ex, "执行新增失败:{message}", ex.Message);
}
}
foreach (var item in updates)
{
try
{
var no = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).Select(x => x.No).SingleAsync();
if (no.IsEmpty())
{
await InsertPersonAsync(item);
}
else
{
await UpdatePersonAsync(item);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "执行更新失败:{message}", ex.Message);
}
}
}
}
private async Task InsertPersonAsync(GainfoSapEntity item)
{
var info = GainfoSapToGainfo(item);
//只有身份证号存在才进行新增
if (info.IdNo.IsPresent())
{
await _dbContext.UseTransactionAsync(async () =>
{
await _dbContext.InsertAsync(item);
if (item.isowner == "T")
{
await _dbContext.InsertAsync(info);
await _identityUserSyncService.SyncAccountAsync(info.Code, info.Name, info.IdNo, info.Factory);
}
else
{
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommandAsync();
}
}
});
}
else
{
_logger.LogWarning("SAP新增人员失败,身份证号不存在:{userCode},{userName}", info.Code, info.Name);
}
}
private static GainfoEntity GainfoSapToGainfo(GainfoSapEntity item)
{
var info = new GainfoEntity
{
No = Guid.NewGuid().ToString(),
InternalNo = item.PERNR,
Type = GainfoUserTypeEnumType.Normal,
Name = item.gname,
Code = item.ename,
CountryNo = item.country,
IdClass = item.idcls,
IdNo = item.idno,
Native = item.native,
Gender = item.sex == "F" ? GenderEnumType.Female : GenderEnumType.Male,
Birthday = item.birthday,
Address = item.address,
DepartmentNo = item.appellation,
Nation = item.nation,
Phone = item.phone,
Degree = item.email,
Grade = item.ZZ_ZD,
Title = item.Z_ZJ,
PositionNo = item.STELL,
Remark = item.remark,
Werks = item.WERKS,
CostId = item.KOSTL,
EntryDate = item.createdate,
ResignationDate = item.ZLZRQ,
Workplace = item.ZZ_GZDJD,
Factory = item.ZZ_GZDCQ
};
return info;
}
private async Task UpdatePersonAsync(GainfoSapEntity item)
{
await _dbContext.Client.Ado.BeginTranAsync();
try
{
await _dbContext.Updateable<GainfoSapEntity>().SetColumns(g => new GainfoSapEntity
{
PERNR = item.PERNR,
gname = item.gname,
phone = item.phone,
appellation = item.appellation,
isowner = item.isowner,
remark = item.remark,
email = item.email,
WERKS = item.WERKS,
KOSTL = item.KOSTL,
STELL = item.STELL,
Z_ZJ = item.Z_ZJ,
ZZ_ZD = item.ZZ_ZD,
MNTXT = item.MNTXT,
MASSN = item.MASSN,
ZSTATUS = item.ZSTATUS,
ZLZRQ = item.ZLZRQ,
STELL_NM = item.STELL_NM,
createdate = item.createdate,
ZZ_GZDJD = item.ZZ_GZDJD,
ZZ_GZDCQ = item.ZZ_GZDCQ,
}).Where(x => x.ename == item.ename).ExecuteCommandAsync();
//获取当前在职人员
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).SingleAsync();
//默认人员存在
if (gainfo != null)
{
var workplace = item.ZZ_GZDJD;
var factory = item.ZZ_GZDCQ;
if (item.isowner == "T")
{
var change = string.Empty;
var hasFactoryChange = gainfo.Factory != factory || gainfo.Workplace != workplace;
var hasDepartmentChange = gainfo.DepartmentNo != item.appellation;
if (hasFactoryChange)
{
await _identityUserSyncService.SyncAccountAsync(gainfo.Code, gainfo.Name, gainfo.IdNo, factory);
change = $"{gainfo.Factory}->{factory}";
}
if (hasDepartmentChange)
{
change += $"{gainfo.DepartmentNo}->{item.appellation}";
}
if (change.IsPresent())
{
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Delete, null, $"异动生成({change})");
}
await _dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
{
InternalNo = item.PERNR,
Name = item.gname,
PositionNo = item.STELL,
Grade = item.ZZ_ZD,
Title = item.Z_ZJ,
Phone = item.phone,
DepartmentNo = item.appellation,
Remark = item.remark,
Degree = item.email,
Werks = item.WERKS,
CostId = item.KOSTL,
EntryDate = item.createdate,
ResignationDate = item.ZLZRQ,
Workplace = workplace,
Factory = factory,
ModifiedTime = DateTime.Now
}).Where(x => x.Code == item.ename).ExecuteCommandAsync();
//有变更就重新下发
if (change.IsPresent())
{
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Add, null, $"异动生成({change})");
//只有厂区变更才需要处理工作网格
if (hasFactoryChange)
{
var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync();
if (workGridUser != null)
{
try
{
var resignationDate = DateOnly.FromDateTime(DateTime.Now);
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>()
.Where(x => x.UserCode == gainfo.Code)
.Where(x => x.Date >= resignationDate)
.ToListAsync();
if (workGridSchedules.Any())
{
var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(",");
var workGrid = await _dbContext.Queryable<WorkGridEntity>()
.Where(x => x.Code == workGridUser.WorkGridCode)
.Select(x => new
{
x.LeaderUserCode, x.Name
}).SingleAsync();
var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
await _dingTalkApi.SendWorkMessageByWorkGridAsync(new DingTalkWorkMessageRequest
{
Content = content,
WorkCodes = new List<string> { workGrid.LeaderUserCode }
});
}
await _dbContext.DeleteAsync(workGridUser);
await _dbContext.DeleteAsync(workGridSchedules);
}
catch (Exception e)
{
_logger.LogError(e, "网格异动处理异常:{error}", e.Message);
}
}
}
}
}
else
{
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Delete, null, "人员离职生成");
//先写入离职表
gainfo.IdentityUserId = (int)gainfo.Id; //记录原始id
gainfo.Id = 0;
gainfo.ResignationDate = item.ZLZRQ;
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommandAsync();
}
await _dbContext.Deleteable<GainfoGroupRelationshipEntity>()
.Where(x => x.UserNo == gainfo.No)
.ExecuteCommandAsync();
await _dbContext.Deleteable<DevicePermissionEntity>()
.Where(x => x.AssignType == AssignTypeEnumType.User && x.AssignValue == gainfo.No)
.ExecuteCommandAsync();
var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>()
.Where(x => x.UserCode == gainfo.Code)
.SingleAsync();
if (workGridUser != null)
{
try
{
var resignationDate = DateOnly.FromDateTime(gainfo.ResignationDate!.Value);
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>()
.Where(x => x.UserCode == gainfo.Code)
.Where(x => x.Date >= resignationDate)
.ToListAsync();
if (workGridSchedules.Any())
{
var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(",");
var workGrid = await _dbContext.Queryable<WorkGridEntity>()
.Where(x => x.Code == workGridUser.WorkGridCode)
.Select(x => new
{
x.LeaderUserCode, x.Name
}).SingleAsync();
var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
await _dingTalkApi.SendWorkMessageByWorkGridAsync(new DingTalkWorkMessageRequest
{
Content = content,
WorkCodes = new List<string> { workGrid.LeaderUserCode }
});
}
await _dbContext.DeleteAsync(workGridUser);
await _dbContext.DeleteAsync(workGridSchedules);
}
catch (Exception e)
{
_logger.LogError(e, "网格异动处理异常:{error}", e.Message);
}
}
gainfo.Id = gainfo.IdentityUserId;
await _dbContext.DeleteReallyAsync(gainfo);
await _identityUserSyncService.LockAccountAsync(gainfo.Code);
}
}
await _dbContext.Client.Ado.CommitTranAsync();
}
catch (Exception ex)
{
await _dbContext.Client.Ado.RollbackTranAsync();
_logger.LogError(ex, "更新人员失败:{message}", ex.Message);
}
}
private async Task<List<SapPersonItem>> GetModifiedPersonAsync(List<SapPersonItem> sapList)
{
var last = await LoadDataAsync();
if (last.Count <= 0)
{
return sapList;
}
var needRemove = sapList.Intersect(last, new SapPersonComparer());
return sapList.Except(needRemove, new SapPersonComparer()).ToList();
}
private async Task<List<SapPersonItem>> LoadDataAsync()
{
var gainfos = await _dbContext.Queryable<GainfoSapEntity>().ToListAsync();
return gainfos.Select(x => new SapPersonItem
{
NAME = x.gname,
ZWORKCODE = x.ename,
ZZ_SFZH = x.idno,
GBDAT = x.birthday,
ZXUELI = x.email,
ORGEH = x.appellation,
ZMOBILE = x.phone,
ZSTATUS = x.ZSTATUS,
ZRZRQ = x.createdate,
PERNR = x.PERNR,
WERKS = x.WERKS,
KOSTL = x.KOSTL,
ZZ_ZD = x.ZZ_ZD,
Z_ZJ = x.Z_ZJ,
PLANS = x.STELL, //x.STELL, 20251129变更
STELL = x.STELL,
STELL_NM = x.STELL_NM,
ZLZRQ = x.ZLZRQ,
MASSN = x.MASSN,
MNTXT = x.MNTXT,
ZZ_COUNNM = x.ZZ_COUNNM,
ZZ_GZDJD = x.ZZ_GZDJD,
ZZ_GZDCQ = x.ZZ_GZDCQ
}).ToList();
}
private static List<GainfoSapEntity> ToGainfoSap(List<SapPersonItem> data)
{
return data.Select(person =>
{
var entryDate = person.ZRZRQ;
var resignDate = person.ZLZRQ;
var rmk = $"入职时间:{entryDate.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)} ";
if (resignDate != null && resignDate.Value.ToString("yyyy-MM-dd") != "1900-01-01")
rmk += $"离职时间:{resignDate.Value.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)} ";
if (!string.IsNullOrWhiteSpace(person.MGTXT))
rmk += $"变更原因:{person.MGTXT}";
var native = GetNative(person.ZZ_SFZH);
var gender = person.GESCH == "2" ? "F" : "M";
person.ZZ_SFZH = person.ZZ_SFZH.TrimStart();
GainfoSapEntity o = new()
{
gname = person.NAME,
ename = person.ZWORKCODE,
idno = person.ZZ_SFZH,
birthday = person.GBDAT,
email = person.ZXUELI,
appellation = person.ORGEH,
phone = person.ZMOBILE,
ZSTATUS = person.ZSTATUS,
createdate = person.ZRZRQ,
PERNR = person.PERNR,
WERKS = person.WERKS,
KOSTL = person.KOSTL,
ZZ_ZD = person.ZZ_ZD,
Z_ZJ = person.Z_ZJ,
STELL = person.PLANS,//person.STELL, 20251129变更
STELL_NM = person.STELL_NM,
ZLZRQ = person.ZLZRQ,
MASSN = person.MASSN,
MNTXT = person.MNTXT,
remark = rmk,
native = native,
sex = gender,
logdate = DateTime.Now,
isowner = int.Parse(person.ZSTATUS) < 5 ? "T" : "F",
country = person.ZZ_COUNNM,
address = "",
occupation = "99",
nation = "01",
idcls = "ID",
ZZ_COUNNM = person.ZZ_COUNNM,
ZZ_GZDJD = person.ZZ_GZDJD,
ZZ_GZDCQ = person.ZZ_GZDCQ
};
return o;
}).ToList();
}
private static string GetNative(string idNo)
{
if (string.IsNullOrWhiteSpace(idNo) || idNo.Length < 6) return null;
idNo = idNo.TrimStart();
return idNo[..6];
}
}