using System.Data; using System.Text; using Dlhis.Entity.Basic.Entity; using Dlhis.ScheduledTask.SyncSapInfo.Dto; using Dlhis.ScheduledTask.SyncSapInfo.Comparers; using Dlhis.ScheduledTask.SyncSapInfo.Services; using Dlhis.Entity.Basic.Enums; using Dlhis.Sys.Api; using Dlhis.Sys.Api.Response; using SqlSugar; using Dlhis.Basic.Api; using Kurisu.Scheduled; using Kurisu.Scheduled.Attributes; namespace Dlhis.ScheduledTask.Jobs; /// /// SAP人员信息同步 /// [RecurringJob(nameof(SyncPersonJob), "0 0 3,12,18 * * ?", Name = "SAP人员信息同步")] public class SyncPersonJob : BaseJob { private readonly IJinkoSapService _jinkoSapService; private readonly ITenantApi _tenantApi; private readonly IDevicePermissionApi _devicePermissionApi; private List _tenants; private List _departmentChanges; private List _jobChanges; public SyncPersonJob( IJinkoSapService jinkoSapService, ITenantApi tenantApi, IServiceProvider serviceProvider, IDevicePermissionApi devicePermissionApi) : base(serviceProvider) { _jinkoSapService = jinkoSapService; _tenantApi = tenantApi; _devicePermissionApi = devicePermissionApi; } public override async Task RunAsync(IServiceProvider serviceProvider) { Logger.LogWarning("开始获取SAP人员"); DbContext.Client.QueryFilter.ClearAndBackup(); var personResp = await _jinkoSapService.GetPersonsAsync(); var persons = personResp.Person.Items; _departmentChanges = personResp.DepartmentInfo.Items; _jobChanges = personResp.JobStatusInfo.Items; Logger.LogWarning("获取SAP人员数量为:{count}", persons.Count); if (persons.Count > 0) { var modifiedPersons = GetModifiedPerson(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList()); Logger.LogWarning("SAP人员差异数量为:{count}", modifiedPersons.Count); if (modifiedPersons.Count > 0) { await SavePersonAsync(modifiedPersons); } } Logger.LogWarning("同步SAP人员数据结束"); } private async Task SavePersonAsync(List persons) { var tenantResult = await _tenantApi.GetTenantsInternalAsync(); _tenants = tenantResult.Data; var workCodes = persons.Select(x => x.ZWORKCODE).ToList(); var chunks = workCodes.Chunk(4000).ToList(); var dtoResult = await _devicePermissionApi.GetPermissionUsersInfoAsync(); var dto = dtoResult.Data; foreach (var searchCodes in chunks) { Logger.LogWarning("SAP分批处理Chunk数量:{count}", searchCodes.Length); var existsWorkCodes = DbContext.Queryable() .Where(x => searchCodes.Contains(x.ename)) .Select(x => x.ename) .ToList(); 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(); int i = 0; var updates = ToGainfoSap(originUpdates); Logger.LogWarning("SAP分批更新数:{count}", updates.Count); var inserts = ToGainfoSap(originInserts); Logger.LogWarning("SAP分批新增数:{count}", inserts.Count); foreach (var item in inserts) { i++; try { InsertPerson(item); Logger.LogWarning("执行新增成功 工号:{code},姓名:{name}", item.ename, item.gname); } catch (Exception ex) { Logger.LogError(ex, "执行新增失败:{message}", ex.Message); } } foreach (var item in updates) { i++; try { UpdatePerson(item); Logger.LogWarning("执行更新成功 工号:{code},姓名:{name}", item.ename, item.gname); } catch (Exception ex) { Logger.LogError(ex, "执行更新失败:{message}", ex.Message); } } } var rResult = await _devicePermissionApi.RePermissionUsersInfoAsync(dto); var r = rResult.Data; Logger.LogWarning("生成下发任务数量:{count}", r); } private void InsertPerson(GainfoSapEntity item) { DbContext.Client.Insertable(item).ExecuteCommand(); var info = GainfoSapToGainfo(item); if (item.isowner == "T") { DbContext.Client.Insertable(info).ExecuteCommand(); } else { DbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommand(); } } private GainfoEntity GainfoSapToGainfo(GainfoSapEntity item) { var info = new GainfoEntity { No = Guid.NewGuid().ToString(), SapNo = item.PERNR, Type = item.@class, 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 = (DateTime)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, Workplace = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM, Factory = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM, }; return info; } private void UpdatePerson(GainfoSapEntity item) { var gainfoSap = DbContext.Queryable().Where(x => x.ename == item.ename).First(); DbContext.Updateable().SetColumns(g => new GainfoSapEntity { PERNR = item.PERNR, gname = item.gname, web = item.web, 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, ZZ_GZDJDNM = item.ZZ_GZDJDNM, ZZ_GZDCQNM = item.ZZ_GZDCQNM, }) .Where(x => x.ename == item.ename) .ExecuteCommand(); var gainfo = DbContext.Queryable().Where(x => x.Code == item.ename).First(); if (item.isowner == "T") { if (gainfo != null) { var workplace = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM; var factory = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM; DbContext.Updateable().SetColumns(g => new GainfoEntity { SapNo = 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, Workplace = workplace, Factory = factory }) .Where(x => x.Code == item.ename) .ExecuteCommand(); } else { var info = GainfoSapToGainfo(item); DbContext.Client.Insertable(info).ExecuteCommand(); } } else { if (gainfo != null) { DbContext.Client.Deleteable(gainfo).ExecuteCommand(); gainfo.Id = 0; DbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommand(); } } } private List GetModifiedPerson(List sapList) { var last = LoadData(); if (last.Count <= 0) { return sapList; } var now = DateTime.Now; foreach (var item in sapList) { var a = _jobChanges.FirstOrDefault(x => x.ZWORKCODE == item.ZWORKCODE); if (a != null) { if (a.BEGDA >= now && a.ENDDA <= now) { if (a.STAT2 == "0") { item.STAT2 = "0"; item.ZSTATUS = "5"; } } } var b = _departmentChanges.FirstOrDefault(x => x.ZWORKCODE == item.ZWORKCODE); if (b != null) { if (b.BEGDA >= now && b.ENDDA <= now) { item.ORGEH = b.ORGEH; item.WERKS = b.WERKS; } } } var needRemove = sapList.Intersect(last, new SapPersonComparer()); return sapList.Except(needRemove, new SapPersonComparer()).ToList(); } private List LoadData() { var gainfo = DbContext.Queryable().ToList(); return gainfo.Select(x => new SapPersonItem { NAME = x.gname, ZWORKCODE = x.ename, ZZ_SFZH = x.idno, GBDAT = x.birthday?.ToString("yyyy-MM-dd") ?? "0000-00-00", ZZ_KLX = x.ZZ_KLX, ZXUELI = x.email?.Trim() ?? string.Empty, ORGEH = x.appellation, ZMOBILE = x.phone, ZSTATUS = x.ZSTATUS, ZRZRQ = x.createdate?.ToString("yyyy-MM-dd"), PERNR = x.PERNR, WERKS = x.WERKS, KOSTL = x.KOSTL, ZZ_ZD = x.ZZ_ZD, Z_ZJ = x.Z_ZJ, STELL = x.STELL, STELL_NM = x.STELL_NM, ZLZRQ = x.ZLZRQ?.ToString("yyyy-MM-dd"), MASSN = x.MASSN, MNTXT = x.MNTXT, ZZ_COUNNM = x.ZZ_COUNNM, ZZ_GZDJDNM = x.ZZ_GZDJDNM, ZZ_GZDCQNM = x.ZZ_GZDCQNM }) .ToList(); } private List ToGainfoSap(List data) { return data.Select(person => { GainfoSapEntity o = null; try { //var position = _positions.FirstOrDefault(x => x.No == person.PLANS); var rzrq = SafeParseDate(person.ZRZRQ); var lzrq = SafeParseDate(person.ZLZRQ); var rmk = ""; if (rzrq != null) rmk = $"入职时间:{rzrq.Value.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)} "; if (lzrq != null && lzrq.Value.ToString("yyyy-MM-dd") != "1900-01-01") rmk += $"离职时间:{lzrq.Value.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)} "; if (!string.IsNullOrWhiteSpace(person.MGTXT)) rmk += $"变更原因:{person.MGTXT}"; var native = GetNative(person.ZZ_SFZH); var sex = person.GESCH == "2" ? "F" : "M"; person.ZZ_SFZH = person.ZZ_SFZH?.TrimStart(); o = new GainfoSapEntity { gname = person.NAME, ename = person.ZWORKCODE, idno = SubString(person.ZZ_SFZH, 18), birthday = SafeParseDate(person.GBDAT).Value, ZZ_KLX = person.ZZ_KLX, email = person.ZXUELI, appellation = person.ORGEH, phone = person.ZMOBILE, ZSTATUS = person.ZSTATUS, createdate = Convert.ToDateTime(person.ZRZRQ), PERNR = person.PERNR, WERKS = person.WERKS, KOSTL = person.KOSTL, ZZ_ZD = person.ZZ_ZD, Z_ZJ = person.Z_ZJ, STELL = person.STELL, STELL_NM = person.STELL_NM, ZLZRQ = SafeParseDate(person.ZLZRQ).Value, MASSN = person.MASSN, MNTXT = person.MNTXT, remark = rmk, native = native, sex = sex, //web = SubString(position?.Name ?? "", 30), logdate = DateTime.Now, isowner = int.Parse(person.ZSTATUS) < 5 ? "T" : "F", @class = "C", country = person.ZZ_COUNNM, log_ip = "127.0.0.1", log_shift = "1", log_id = "XX", address = "", occupation = "99", nation = "01", idcls = "ID", ZZ_COUNNM = person.ZZ_COUNNM, ZZ_GZDJDNM = person.ZZ_GZDJDNM, ZZ_GZDCQNM = person.ZZ_GZDCQNM, }; return o; } catch (Exception) { throw; } }).ToList(); } private static string GetNative(string idno) { if (string.IsNullOrWhiteSpace(idno) || idno.Length < 6) return null; idno = idno.TrimStart(); return idno[..6]; } private static DateTime? SafeParseDate(string str) { if (string.IsNullOrEmpty(str)) { str = "1900-01-01"; } if ("0000-00-00".Equals(str)) { str = "1900-01-01"; } if (DateTime.TryParse(str, out var d)) { return d; } return null; } private string SubString(string s, int len) { if (string.IsNullOrWhiteSpace(s)) { return s?.Trim() ?? ""; } s = s.Trim(); var bs = Encoding.UTF8.GetBytes(s); if (bs.Length <= len) { return s; } var bytes = new byte[len]; Buffer.BlockCopy(bs, 0, bytes, 0, len); return Encoding.UTF8.GetString(bytes); } }