This commit is contained in:
2024-11-25 12:10:54 +08:00
parent f67b906ea0
commit 9e337b90cd
4 changed files with 16 additions and 518 deletions

View File

@@ -1,8 +0,0 @@
namespace Dlhis.ScheduledTask.Common.Services;
public interface IGainfoUpdateService : IScopeDependency
{
Task TodoByWerkAsync(string werk);
Task TodoByCodeAsync(string code);
}

View File

@@ -5,11 +5,13 @@ namespace Dlhis.ScheduledTask.Common.Services;
public interface IJinkoJipService : ISingletonDependency
{
Task<UploadAttendanceResponse> UploadAttendancesAsync(List<UploadAttendanceRequest> requests);
/// <summary>
/// 同步餐补处理结果
/// </summary>
/// <param name="requests"></param>
/// <returns></returns>
Task<string> SyncMealSupplementRecordsAsync(List<SyncMealSupplementRecordRequest> requests);
/// <summary>
/// 获取出差信息
/// </summary>
@@ -28,9 +30,14 @@ public interface IJinkoJipService : ISingletonDependency
/// <returns></returns>
Task<SapBusinessTripInfoResponse> GetTravelInfosByUserCodeAsync(DateTime begin, DateTime end, string userCode);
/// <summary>
/// 同步人脸数据到SAP
/// </summary>
/// <param name="userCode"></param>
/// <param name="base64"></param>
/// <returns></returns>
Task<SapFaceSyncResponse> SyncFaceToSapAsync(string userCode, string base64);
string IssueToken();
Task<UploadAttendanceResponse> UploadAttendancesAsync(UploadAttendanceRequest request);
}

View File

@@ -1,496 +0,0 @@
using Dlhis.Basic.Api;
using Dlhis.Basic.Api.Dto;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums;
using Dlhis.Sys.Api;
using Dlhis.Sys.Api.Response;
using Dlhis.ScheduledTask.Common.Dto;
using Dlhis.ScheduledTask.Common.Comparers;
using Kurisu.AspNetCore.Utils.Extensions;
using Dlhis.Basic.Api.Request;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
namespace Dlhis.ScheduledTask.Common.Services.Implements;
public class GainfoUpdateService : IGainfoUpdateService
{
private readonly IDbContext _dbContext;
private readonly ILogger<GainfoUpdateService> _logger;
private readonly ITenantApi _tenantApi;
private readonly IIdentityUserSyncService _identityUserSyncService;
private readonly IGainfoPermissionApi _gainfoPermissionApi;
private readonly IDevicePermissionApi _devicePermissionApi;
private readonly IJinkoSapService _jinkoSapService;
private List<TenantResponse> _tenants;
public GainfoUpdateService(IDbContext dbContext,
ILogger<GainfoUpdateService> logger,
ITenantApi tenantApi,
IIdentityUserSyncService identityUserSyncService,
IGainfoPermissionApi gainfoPermissionApi,
IDevicePermissionApi devicePermissionApi,
IJinkoSapService jinkoSapService)
{
_dbContext = dbContext;
_dbContext.Client.QueryFilter.Clear();
_logger = logger;
_tenantApi = tenantApi;
_identityUserSyncService = identityUserSyncService;
_gainfoPermissionApi = gainfoPermissionApi;
_devicePermissionApi = devicePermissionApi;
_jinkoSapService = jinkoSapService;
}
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);
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);
}
private async Task SavePersonAsync(List<SapPersonItem> persons)
{
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
_tenants = tenantResult.Data;
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)
{
await _dbContext.InsertAsync(item);
var info = GainfoSapToGainfo(item);
if (item.isowner == "T")
{
await _dbContext.InsertAsync(info);
await _identityUserSyncService.SyncAccountAsync(info.Code, info.Name, info.IdNo, info.Factory);
await _devicePermissionApi.RePermissionUsersInfoAsync(new PermissionUsersInfoDto
{
UserNos = new List<string> { info.No },
PermissionInfos = new Dictionary<string, List<UserTenantDeviceCodeDto>>
{
[info.No] = new()
}
});
}
else
{
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommandAsync();
}
}
}
private 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,
CardType = SafeParseCardType(item.ZZ_KLX),
Workplace = _tenants.LastOrDefault(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 async Task UpdatePersonAsync(GainfoSapEntity item)
{
var info = GainfoSapToGainfo(item);
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,
ZZ_KLX = item.ZZ_KLX,
createdate = item.createdate,
ZZ_GZDJDNM = item.ZZ_GZDJDNM,
ZZ_GZDCQNM = item.ZZ_GZDCQNM,
}).Where(x => x.ename == item.ename).ExecuteCommandAsync();
//获取当前在职人员
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).SingleAsync();
var workplace = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM;
var factory = _tenants.LastOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM;
if (gainfo != null)
{
if (item.isowner == "T")
{
var dtoResult = await _devicePermissionApi.GetPermissionUsersInfoAsync(new List<string> { gainfo.No });
var dto = dtoResult.Data;
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,
CardType = SafeParseCardType(item.ZZ_KLX)
}).Where(x => x.Code == item.ename).ExecuteCommandAsync();
await _identityUserSyncService.SyncAccountAsync(gainfo.Code, gainfo.Name, gainfo.IdNo, factory);
await _devicePermissionApi.RePermissionUsersInfoAsync(dto);
}
else
{
try
{
await _gainfoPermissionApi.ResetAsync(new GainfoPermissionResetRequest
{
IsLeave = true,
UserNo = gainfo.No
});
}
catch (Exception ex)
{
_logger.LogError(ex, "离职任务生成失败:{message}", ex.Message);
}
//先写入离职表
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();
}
gainfo.Id = gainfo.IdentityUserId;
await _dbContext.DeleteReallyAsync(gainfo);
}
}
else
{
if (item.isowner == "T")
{
await _dbContext.InsertAsync(info);
await _identityUserSyncService.SyncAccountAsync(info.Code, info.Name, info.IdNo, factory);
}
else
{
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommandAsync();
}
else
{
await _dbContext.Updateable<GainfoLeaveEntity>().SetColumns(g => new GainfoLeaveEntity
{
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,
CardType = SafeParseCardType(item.ZZ_KLX)
}).Where(x => x.Code == item.ename).ExecuteCommandAsync();
}
}
}
}
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()).ToList();
return sapList.Except(needRemove, new SapPersonComparer()).ToList();
}
private async Task<List<SapPersonItem>> LoadDataAsync()
{
//var pJson = "{\"id\":0,\"ano\":null,\"class\":\"C\",\"passwd\":null,\"question\":null,\"answer\":null,\"gname\":\"岳文超\",\"ename\":\"098250\",\"country\":null,\"idcls\":\"ID\",\"idno\":\"\\\"140105200112051318\n\",\"native\":\"14010\",\"sex\":\"M\",\"birthday\":\"2001-12-05T00:00:00\",\"address\":\"\",\"postcode\":null,\"occupation\":\"99\",\"appellation\":\"00210591\",\"nation\":\"01\",\"phone\":\"13773151205\",\"fax\":null,\"mobile\":null,\"email\":\"高中/中专【失效】\",\"web\":\"\",\"vip\":null,\"sec\":null,\"cropsno\":null,\"cropname\":null,\"fancy\":null,\"remark\":\"入职时间:2023-05-05 离职时间:2023-10-30 变更原因:自离【失效】\",\"amount\":0,\"days\":0,\"consume01\":0.0000,\"consume02\":0.0000,\"consume03\":0.0000,\"consume04\":0.0000,\"log_id\":\"XX\",\"log_shift\":\"1\",\"log_date\":null,\"log_ip\":\"127.0.0.1\",\"times\":0,\"logmark\":0,\"rmcode\":null,\"mkt\":null,\"src\":null,\"isowner\":\"F\",\"createdate\":\"2023-05-05T00:00:00\",\"PERNR\":\"00281800\",\"WERKS\":\"1560\",\"ZSTATUS\":\"5\",\"KOSTL\":\"156020336\",\"ZZ_ZD\":\"3\",\"Z_ZJ\":\"T0\",\"STELL\":null,\"STELL_NM\":null,\"ZLZRQ\":\"2023-10-30T00:00:00\",\"MASSN\":\"ZD\",\"MNTXT\":\"离职\",\"MASSG\":null,\"MGTXT\":null,\"logdate\":\"2024-03-14T00:02:34\",\"updatelogdate\":null,\"guestno\":null,\"ZZ_KLX\":\"3\",\"DAT01\":null,\"ZZ_COUNNM\":null,\"ZZ_GZDJDNM\":\"海宁基地\",\"ZZ_GZDCQNM\":\"海宁尖山\"}";
//var gainfos = new List<GainfoSapEntity>() { pJson.ToObject<GainfoSapEntity>() };
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,
ZZ_KLX = x.ZZ_KLX,
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,
STELL = x.STELL,
STELL_NM = x.STELL_NM,
ZLZRQ = x.ZLZRQ,
MASSN = x.MASSN,
MNTXT = x.MNTXT,
ZZ_COUNNM = x.ZZ_COUNNM,
ZZ_GZDJDNM = x.ZZ_GZDJDNM,
ZZ_GZDCQNM = x.ZZ_GZDCQNM
}).ToList();
}
private static List<GainfoSapEntity> ToGainfoSap(List<SapPersonItem> data)
{
return data.Select(person =>
{
//var position = _positions.FirstOrDefault(x => x.No == person.PLANS);
var rzrq = person.ZRZRQ;
var lzrq = person.ZLZRQ;
var rmk = $"入职时间:{rzrq.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();
GainfoSapEntity o = new()
{
gname = person.NAME,
ename = person.ZWORKCODE,
idno = person.ZZ_SFZH,
birthday = person.GBDAT,
ZZ_KLX = person.ZZ_KLX,
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.STELL,
STELL_NM = person.STELL_NM,
ZLZRQ = person.ZLZRQ,
MASSN = person.MASSN,
MNTXT = person.MNTXT,
remark = rmk,
native = native,
sex = sex,
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;
}).ToList();
}
private static string GetNative(string idNo)
{
if (string.IsNullOrWhiteSpace(idNo) || idNo.Length < 6) return null;
idNo = idNo.TrimStart();
return idNo[..6];
}
private static int? SafeParseCardType(string ZZ_KLX)
{
if (int.TryParse(ZZ_KLX, out var cardType))
{
return cardType;
}
return null;
}
}

View File

@@ -32,16 +32,11 @@ public class JinkoJipService : IJinkoJipService
return httpClient;
}
public async Task<UploadAttendanceResponse> UploadAttendancesAsync(List<UploadAttendanceRequest> requests)
public async Task<UploadAttendanceResponse> UploadAttendancesAsync(UploadAttendanceRequest request)
{
var requestUrl = "/JIP/HCM/HCM_SWIPE_DATA_SAVE";
var body = new
{
T_DATA = requests,
};
var json = body.ToJson();
var json = request.ToJson();
//_logger.LogInformation("上传考勤记录请求:{json}", json);