617 lines
24 KiB
C#
617 lines
24 KiB
C#
using Dlhis.Basic.Common.Message.Requests;
|
||
using Dlhis.Basic.Common.Message.Services;
|
||
using Dlhis.Basic.Organization.Comparers;
|
||
using Dlhis.Basic.Organization.Repositories;
|
||
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;
|
||
private readonly IGainfoSapRepository _gainfoSapRepository;
|
||
|
||
public GainfoUpdateService(IDbContext dbContext,
|
||
ILogger<GainfoUpdateService> logger,
|
||
IJinkoSapService jinkoSapService,
|
||
IGainfoPermissionService gainfoPermissionService,
|
||
IJinkoApiService dingTalkApi,
|
||
IIdentityUserSyncService identityUserSyncService,
|
||
IGainfoSapRepository gainfoSapRepository)
|
||
{
|
||
_dbContext = dbContext;
|
||
_logger = logger;
|
||
_jinkoSapService = jinkoSapService;
|
||
_gainfoPermissionService = gainfoPermissionService;
|
||
_dingTalkApi = dingTalkApi;
|
||
_identityUserSyncService = identityUserSyncService;
|
||
_gainfoSapRepository = gainfoSapRepository;
|
||
}
|
||
|
||
|
||
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.Persons;
|
||
|
||
werkInfo.HandleMessage = "SAP人员数量" + persons.Count;
|
||
werkInfo.DiffNumber = 0;
|
||
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.Persons;
|
||
|
||
_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 thirdPartPersons = persons.Where(x => !string.IsNullOrWhiteSpace(x.ZWORKCODE)).ToList();
|
||
if (thirdPartPersons.Count <= 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var workCodes = thirdPartPersons.Select(x => x.ZWORKCODE).Distinct().ToList();
|
||
var chunks = workCodes.Chunk(4000).ToList();
|
||
var comparer = new SapPersonComparer();
|
||
|
||
foreach (var searchCodes in chunks)
|
||
{
|
||
_logger.LogWarning("SAP分批处理Chunk数量:{count}", searchCodes.Length);
|
||
var chunkThirdPartPersons = thirdPartPersons.Where(x => searchCodes.Contains(x.ZWORKCODE)).ToList();
|
||
|
||
var latestHistoryPersons = (await _gainfoSapRepository.GetLatestPersonsAsync(searchCodes.ToList()))
|
||
.ToDictionary(x => x.ZWORKCODE, x => x);
|
||
|
||
foreach (var person in chunkThirdPartPersons)
|
||
{
|
||
try
|
||
{
|
||
await _dbContext.UseTransactionAsync(async () =>
|
||
{
|
||
var item = ToGainfoSap(person);
|
||
|
||
if (!latestHistoryPersons.TryGetValue(person.ZWORKCODE, out var latestHistory)
|
||
|| !comparer.Equals(person, latestHistory))
|
||
{
|
||
await _dbContext.InsertAsync(item);
|
||
}
|
||
|
||
var no = await _dbContext.Queryable<GainfoEntity>()
|
||
.Where(x => x.Code == item.ename)
|
||
.Select(x => x.No)
|
||
.SingleAsync();
|
||
|
||
if (no.IsEmpty())
|
||
{
|
||
await InsertCurrentPersonCoreAsync(item);
|
||
}
|
||
else
|
||
{
|
||
await UpdatePersonAsync(item, false);
|
||
}
|
||
});
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "执行人员同步失败,工号:{workCode},错误:{message}", person.ZWORKCODE, ex.Message);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private async Task InsertCurrentPersonCoreAsync(GainfoSapEntity item)
|
||
{
|
||
var info = GainfoSapToGainfo(item);
|
||
//只有身份证号存在才进行新增
|
||
if (info.IdNo.IsPresent())
|
||
{
|
||
if (item.isowner == "T")
|
||
{
|
||
if (!await _dbContext.Queryable<GainfoEntity>().AnyAsync(x => x.Code == item.ename))
|
||
{
|
||
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,
|
||
NameEn = item.gname2,
|
||
Code = item.ename,
|
||
CountryNo = item.country,
|
||
IdClass = item.idcls,
|
||
IdNo = item.idno.ToUpperInvariant(),
|
||
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;
|
||
}
|
||
|
||
public async Task UpdatePersonAsync(GainfoSapEntity item, bool useTransaction = true)
|
||
{
|
||
if (useTransaction)
|
||
{
|
||
await _dbContext.Client.Ado.BeginTranAsync();
|
||
}
|
||
|
||
try
|
||
{
|
||
//获取当前在职人员
|
||
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, null, $"异动生成({change})");
|
||
}
|
||
|
||
|
||
await _dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
||
{
|
||
InternalNo = item.PERNR,
|
||
Name = item.gname,
|
||
NameEn = item.gname2,
|
||
IdNo = item.idno.ToUpperInvariant(),
|
||
Birthday = item.birthday,
|
||
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, null, $"异动生成({change})");
|
||
|
||
//只有厂区变更才需要处理工作网格
|
||
if (hasFactoryChange)
|
||
{
|
||
await HandleWorkGridChangeAsync(gainfo, DateOnly.FromDateTime(DateTime.Now));
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
await _gainfoPermissionService.ResetPermissionsAsync(gainfo.No, DeviceTaskEnumType.Delete, null, 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();
|
||
|
||
await HandleWorkGridChangeAsync(gainfo, DateOnly.FromDateTime(gainfo.ResignationDate!.Value));
|
||
|
||
gainfo.Id = gainfo.IdentityUserId;
|
||
await _dbContext.DeleteReallyAsync(gainfo);
|
||
await _identityUserSyncService.LockAccountAsync(gainfo.Code);
|
||
}
|
||
}
|
||
|
||
if (useTransaction)
|
||
{
|
||
await _dbContext.Client.Ado.CommitTranAsync();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (useTransaction)
|
||
{
|
||
await _dbContext.Client.Ado.RollbackTranAsync();
|
||
}
|
||
|
||
_logger.LogError(ex, "更新人员失败:{message}", ex.Message);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
private async Task HandleWorkGridChangeAsync(GainfoEntity gainfo, DateOnly effectiveDate)
|
||
{
|
||
try
|
||
{
|
||
var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>()
|
||
.Where(x => x.UserCode == gainfo.Code)
|
||
.SingleAsync();
|
||
if (workGridUser == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>()
|
||
.Where(x => x.UserCode == gainfo.Code)
|
||
.Where(x => x.Date >= effectiveDate)
|
||
.ToListAsync();
|
||
|
||
if (workGridSchedules.Any())
|
||
{
|
||
try
|
||
{
|
||
var workGrid = await _dbContext.Queryable<WorkGridEntity>()
|
||
.Where(x => x.Code == workGridUser.WorkGridCode)
|
||
.Select(x => new
|
||
{
|
||
x.LeaderUserCode,
|
||
x.Name
|
||
})
|
||
.SingleAsync();
|
||
|
||
if (workGrid != null)
|
||
{
|
||
var dates = workGridSchedules
|
||
.Select(x => $"{x.Date:yyyy年-MM月-dd日}的{x.PeriodType.GetDescription()}")
|
||
.Join(",");
|
||
var content =
|
||
$"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
|
||
|
||
await _dingTalkApi.SendWorkMessageByWorkGridAsync(new DingTalkWorkMessageRequest
|
||
{
|
||
Content = content,
|
||
WorkCodes = new List<string> { workGrid.LeaderUserCode }
|
||
});
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "工作网格消息通知失败,工号:{workCode},错误:{error}", gainfo.Code, ex.Message);
|
||
}
|
||
}
|
||
|
||
await _dbContext.DeleteAsync(workGridUser);
|
||
await _dbContext.DeleteAsync(workGridSchedules);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "网格异动处理异常,工号:{workCode},错误:{error}", gainfo.Code, ex.Message);
|
||
}
|
||
}
|
||
|
||
private async Task<List<SapPersonItem>> GetModifiedPersonAsync(List<SapPersonItem> sapList)
|
||
{
|
||
if (sapList.Count <= 0)
|
||
{
|
||
return new List<SapPersonItem>();
|
||
}
|
||
|
||
var comparer = new SapPersonComparer();
|
||
var workCodes = sapList
|
||
.Select(x => x.ZWORKCODE)
|
||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||
.Distinct()
|
||
.ToList();
|
||
|
||
if (workCodes.Count <= 0)
|
||
{
|
||
return sapList;
|
||
}
|
||
|
||
var last = await _gainfoSapRepository.GetLatestPersonsAsync(workCodes);
|
||
if (last.Count <= 0)
|
||
{
|
||
return sapList;
|
||
}
|
||
|
||
var lastMap = last
|
||
.Where(x => !string.IsNullOrWhiteSpace(x.ZWORKCODE))
|
||
.GroupBy(x => x.ZWORKCODE)
|
||
.ToDictionary(x => x.Key, x => x.First());
|
||
|
||
var existingCodes = await _dbContext.Queryable<GainfoEntity>()
|
||
.Where(x => workCodes.Contains(x.Code))
|
||
.Select(x => x.Code)
|
||
.ToListAsync();
|
||
|
||
var modifiedPersons = new List<SapPersonItem>();
|
||
foreach (var person in sapList)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(person.ZWORKCODE))
|
||
{
|
||
modifiedPersons.Add(person);
|
||
continue;
|
||
}
|
||
|
||
var existsInGainfo = existingCodes.Contains(person.ZWORKCODE);
|
||
var isOwner = int.Parse(person.ZSTATUS) < 5;
|
||
if ((isOwner && !existsInGainfo) || (!isOwner && existsInGainfo))
|
||
{
|
||
modifiedPersons.Add(person);
|
||
continue;
|
||
}
|
||
|
||
if (!lastMap.TryGetValue(person.ZWORKCODE, out var latestHistory))
|
||
{
|
||
modifiedPersons.Add(person);
|
||
continue;
|
||
}
|
||
|
||
if (comparer.Equals(person, latestHistory))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
modifiedPersons.Add(person);
|
||
}
|
||
|
||
if (modifiedPersons.Count > 0)
|
||
{
|
||
var first = modifiedPersons[0];
|
||
var historyCandidates = !string.IsNullOrWhiteSpace(first.ZWORKCODE)
|
||
&& lastMap.TryGetValue(first.ZWORKCODE, out var currentHistoryPerson)
|
||
? currentHistoryPerson
|
||
: null;
|
||
var hasHistory = historyCandidates != null;
|
||
var diffType = hasHistory ? "Update" : "Insert";
|
||
var diffMessage = hasHistory
|
||
? string.Join("; ", GetFirstDiffFields(first, historyCandidates))
|
||
: "历史记录不存在";
|
||
_logger.LogWarning("SAP首条差异 DiffType:{diffType}, ZWORKCODE:{workCode}, HasHistory:{hasHistory}, Diffs:{diffs}",
|
||
diffType, first.ZWORKCODE, hasHistory, diffMessage);
|
||
}
|
||
|
||
return modifiedPersons;
|
||
}
|
||
|
||
private static GainfoSapEntity ToGainfoSap(SapPersonItem 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();
|
||
return new GainfoSapEntity
|
||
{
|
||
gname = person.NAME,
|
||
gname2 = person.NAME2,
|
||
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_XJ,
|
||
ZZ_ZD = person.ZZ_ZD,
|
||
Z_ZJ = person.Z_ZJ,
|
||
STELL = person.PLANS, //person.STELL, 20251129变更
|
||
STELL_NM = person.STELL_NM ?? string.Empty,
|
||
ZLZRQ = person.ZLZRQ,
|
||
MASSN = person.MASSN ?? string.Empty,
|
||
MNTXT = person.MNTXT ?? string.Empty,
|
||
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
|
||
};
|
||
}
|
||
|
||
private static string GetNative(string idNo)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(idNo) || idNo.Length < 6) return null;
|
||
idNo = idNo.TrimStart();
|
||
return idNo[..6];
|
||
}
|
||
|
||
private static List<string> GetFirstDiffFields(SapPersonItem current, SapPersonItem history)
|
||
{
|
||
var diffs = new List<string>();
|
||
AddDiff(diffs, "PERNR", current.PERNR, history.PERNR);
|
||
AddDiff(diffs, "WERKS", current.WERKS, history.WERKS);
|
||
AddDiff(diffs, "ORGEH", current.ORGEH, history.ORGEH);
|
||
AddDiff(diffs, "NAME", current.NAME, history.NAME);
|
||
AddDiff(diffs, "GBDAT", FormatDate(current.GBDAT), FormatDate(history.GBDAT));
|
||
AddDiff(diffs, "ZZ_SFZH", NormalizeIdNo(current.ZZ_SFZH), NormalizeIdNo(history.ZZ_SFZH));
|
||
AddDiff(diffs, "ZWORKCODE", current.ZWORKCODE, history.ZWORKCODE);
|
||
AddDiff(diffs, "ZMOBILE", Normalize(current.ZMOBILE), Normalize(history.ZMOBILE));
|
||
AddDiff(diffs, "ZSTATUS", Normalize(current.ZSTATUS), Normalize(history.ZSTATUS));
|
||
AddDiff(diffs, "KOSTL_XJ", Normalize(current.KOSTL_XJ), Normalize(history.KOSTL_XJ));
|
||
AddDiff(diffs, "NAME2", Normalize(current.NAME2), Normalize(history.NAME2));
|
||
AddDiff(diffs, "ZZ_ZD", Normalize(current.ZZ_ZD), Normalize(history.ZZ_ZD));
|
||
AddDiff(diffs, "Z_ZJ", Normalize(current.Z_ZJ), Normalize(history.Z_ZJ));
|
||
AddDiff(diffs, "ZRZRQ", FormatDate(current.ZRZRQ), FormatDate(history.ZRZRQ));
|
||
AddDiff(diffs, "ZLZRQ", FormatDate(current.ZLZRQ), FormatDate(history.ZLZRQ));
|
||
AddDiff(diffs, "PLANS", Normalize(current.PLANS), Normalize(history.PLANS));
|
||
AddDiff(diffs, "STELL_NM", Normalize(current.STELL_NM), Normalize(history.STELL_NM));
|
||
AddDiff(diffs, "MASSN", Normalize(current.MASSN), Normalize(history.MASSN));
|
||
AddDiff(diffs, "MNTXT", Normalize(current.MNTXT), Normalize(history.MNTXT));
|
||
AddDiff(diffs, "ZZ_GZDJD", Normalize(current.ZZ_GZDJD), Normalize(history.ZZ_GZDJD));
|
||
AddDiff(diffs, "ZZ_GZDCQ", Normalize(current.ZZ_GZDCQ), Normalize(history.ZZ_GZDCQ));
|
||
|
||
return diffs;
|
||
}
|
||
|
||
private static void AddDiff(List<string> diffs, string field, string current, string history)
|
||
{
|
||
if (!string.Equals(current ?? string.Empty, history ?? string.Empty, StringComparison.Ordinal))
|
||
{
|
||
diffs.Add($"{field}: [{history}] -> [{current}]");
|
||
}
|
||
}
|
||
|
||
private static string Normalize(string value) => value?.Trim() ?? string.Empty;
|
||
|
||
private static string NormalizeIdNo(string value) => value?.TrimStart() ?? string.Empty;
|
||
|
||
private static string FormatDate(DateTime? value) => value?.ToString("yyyy-MM-dd HH:mm:ss") ?? string.Empty;
|
||
|
||
private static string FormatDate(DateTime value) => value.ToString("yyyy-MM-dd HH:mm:ss");
|
||
}
|