fix 重构数据同步
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Entities;
|
namespace Dlhis.Entity.Basic.Entity;
|
||||||
|
|
||||||
[SugarTable(TableName = "GainfoSap")]
|
[SugarTable(TableName = "GainfoSap")]
|
||||||
public class GainfoSapEntity
|
public class GainfoSapEntity
|
||||||
35
Src/Dlhis.Entity/Basic/Entity/PositionEntity.cs
Normal file
35
Src/Dlhis.Entity/Basic/Entity/PositionEntity.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using Kurisu.SqlSugar;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace Dlhis.Entity.Basic.Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 职位表
|
||||||
|
/// </summary>
|
||||||
|
[SugarTable(TableName = "Position", TableDescription = "职位表")]
|
||||||
|
public class PositionEntity : SugarBaseEntity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 岗位编码
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDescription = "岗位编码")]
|
||||||
|
public string No { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 岗位名称
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDescription = "岗位名称")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 职等
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDescription = "职等")]
|
||||||
|
public string Grade { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属部门ID
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDescription = "所属部门ID")]
|
||||||
|
public string DepartmentNo { get; set; }
|
||||||
|
}
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
using Dlhis.Entity;
|
|
||||||
using Kurisu.SqlSugar;
|
|
||||||
using SqlSugar;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Entities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 部门
|
|
||||||
/// </summary>
|
|
||||||
[SugarTable(TableName = "T_ORG", TableDescription = "部门表")]
|
|
||||||
public class ZHRF_SYN_01Entity : SugarBaseEntity
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 开始日期
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "开始日期")]
|
|
||||||
public string BEGDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结束日期
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "结束日期")]
|
|
||||||
public string ENDDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 语言代码
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "语言代码")]
|
|
||||||
public int LANGU { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门id
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "部门id")]
|
|
||||||
public int OBJID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "部门名称")]
|
|
||||||
public string STEXT { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上级部门
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "上级部门")]
|
|
||||||
public string SOBID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门层级
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "部门层级")]
|
|
||||||
public string ZZ_BMCJ { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 公司
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "公司")]
|
|
||||||
public string ORGID01 { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 事业部
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "事业部")]
|
|
||||||
public string ORGID02 { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 一级部门
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "一级部门")]
|
|
||||||
public string ORGID03 { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 二级部门
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "二级部门")]
|
|
||||||
public string ORGID04 { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 三级部门
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "三级部门")]
|
|
||||||
public string ORGID05 { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 四级部门
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "四级部门")]
|
|
||||||
|
|
||||||
public string ORGID06 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
using Dlhis.Entity;
|
|
||||||
using Kurisu.SqlSugar;
|
|
||||||
using SqlSugar;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Entities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 职位表
|
|
||||||
/// </summary>
|
|
||||||
[SugarTable(TableName = "T_POST", TableDescription = "职位表")]
|
|
||||||
public class ZHRF_SYN_02Entity : SugarBaseEntity
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 开始日期
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "开始日期")]
|
|
||||||
public string BEGDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结束日期
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "结束日期")]
|
|
||||||
public string ENDDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 语言代码
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "语言代码")]
|
|
||||||
public int LANGU { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 岗位编码
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "岗位编码")]
|
|
||||||
public string ZJOBID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 岗位名称
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "岗位名称")]
|
|
||||||
public string ZJOBANME { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 职等
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "职等")]
|
|
||||||
public string ZJOBACTID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所属部门ID
|
|
||||||
/// </summary>
|
|
||||||
[SugarColumn(ColumnDescription = "所属部门ID")]
|
|
||||||
public string ZDEPID { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Entities;
|
|
||||||
using Dlhis.ScheduledTask.Extensions;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Comparers
|
|
||||||
{
|
|
||||||
internal class ZHRS_ORGComparer : IEqualityComparer<ZHRS_ORG>
|
|
||||||
{
|
|
||||||
public bool Equals(ZHRS_ORG x, ZHRS_ORG y)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(x, y)) return true;
|
|
||||||
if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;
|
|
||||||
if (x.GetType() != y.GetType()) return false;
|
|
||||||
|
|
||||||
return x.BEGDA == y.BEGDA
|
|
||||||
&& x.ENDDA == y.ENDDA
|
|
||||||
&& x.LANGU == y.LANGU
|
|
||||||
&& x.OBJID == y.OBJID
|
|
||||||
&& x.STEXT == y.STEXT
|
|
||||||
&& x.SOBID == y.SOBID
|
|
||||||
&& x.ORGID01 == y.ORGID01
|
|
||||||
&& x.ORGID02 == y.ORGID02;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHashCode(ZHRS_ORG obj)
|
|
||||||
{
|
|
||||||
return obj.BEGDA.SafeGetHashCode() ^ obj.ENDDA.SafeGetHashCode()
|
|
||||||
^ obj.LANGU.SafeGetHashCode() ^ obj.OBJID.SafeGetHashCode()
|
|
||||||
^ obj.STEXT.SafeGetHashCode() ^ obj.SOBID.SafeGetHashCode()
|
|
||||||
^ obj.ORGID01.SafeGetHashCode() ^ obj.ORGID02.SafeGetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Dto;
|
|
||||||
using Dlhis.ScheduledTask.Extensions;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Comparers
|
|
||||||
{
|
|
||||||
internal class ZHRS_PERSONComparer : IEqualityComparer<PersonDetail>
|
|
||||||
{
|
|
||||||
public bool Equals(PersonDetail x, PersonDetail y)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(x, y)) return true;
|
|
||||||
if (ReferenceEquals(x, null)) return false;
|
|
||||||
if (ReferenceEquals(y, null)) return false;
|
|
||||||
|
|
||||||
return x.PERNR == y.PERNR
|
|
||||||
&& x.WERKS == y.WERKS
|
|
||||||
&& SubString(x.ORGEH, 10) == SubString(y.ORGEH, 10)
|
|
||||||
&& SubString(x.NAME, 50) == SubString(y.NAME, 50)
|
|
||||||
&& SafeParseDate(x.GBDAT) == SafeParseDate(y.GBDAT)
|
|
||||||
&& SubString(x.ZZ_SFZH, 18) == SubString(y.ZZ_SFZH, 18)
|
|
||||||
&& SubString(x.ZWORKCODE, 50) == SubString(y.ZWORKCODE, 50)
|
|
||||||
&& SubString(x.ZMOBILE, 20) == SubString(y.ZMOBILE, 20)
|
|
||||||
&& x.ZSTATUS == y.ZSTATUS
|
|
||||||
&& x.KOSTL == y.KOSTL
|
|
||||||
&& x.ZZ_ZD == y.ZZ_ZD
|
|
||||||
&& x.Z_ZJ == y.Z_ZJ
|
|
||||||
&& x.ZRZRQ == y.ZRZRQ
|
|
||||||
&& SafeParseDate(x.ZLZRQ) == SafeParseDate(y.ZLZRQ)
|
|
||||||
&& x.STELL == y.STELL
|
|
||||||
&& x.STELL_NM == y.STELL_NM
|
|
||||||
&& x.MASSN == y.MASSN
|
|
||||||
&& x.MNTXT == y.MNTXT
|
|
||||||
&& (x.ZXUELI ?? string.Empty).Trim() == (y.ZXUELI ?? string.Empty).Trim()
|
|
||||||
&& (x.ZZ_KLX ?? string.Empty) == (y.ZZ_KLX ?? string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHashCode(PersonDetail obj)
|
|
||||||
{
|
|
||||||
return obj.PERNR.SafeGetHashCode()
|
|
||||||
^ obj.WERKS.SafeGetHashCode()
|
|
||||||
^ SubString(obj.ORGEH, 10).SafeGetHashCode()
|
|
||||||
^ SubString(obj.NAME, 50).SafeGetHashCode()
|
|
||||||
^ SafeParseDate(obj.GBDAT).SafeGetHashCode()
|
|
||||||
^ SubString(obj.ZZ_SFZH, 18).SafeGetHashCode()
|
|
||||||
^ SubString(obj.ZWORKCODE, 50).SafeGetHashCode()
|
|
||||||
^ SubString(obj.ZMOBILE, 20).SafeGetHashCode()
|
|
||||||
^ obj.ZSTATUS.SafeGetHashCode()
|
|
||||||
^ obj.KOSTL.SafeGetHashCode()
|
|
||||||
^ obj.ZZ_ZD.SafeGetHashCode()
|
|
||||||
^ obj.Z_ZJ.SafeGetHashCode()
|
|
||||||
^ obj.ZRZRQ.SafeGetHashCode()
|
|
||||||
^ SafeParseDate(obj.ZLZRQ).SafeGetHashCode()
|
|
||||||
^ obj.STELL.SafeGetHashCode()
|
|
||||||
^ obj.STELL_NM.SafeGetHashCode()
|
|
||||||
^ obj.MASSN.SafeGetHashCode()
|
|
||||||
^ obj.MNTXT.SafeGetHashCode()
|
|
||||||
^ obj.ZXUELI.SafeGetHashCode()
|
|
||||||
^ (obj.ZZ_KLX ?? "").SafeGetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private DateTime? SafeParseDate(string str)
|
|
||||||
{
|
|
||||||
if (str == "0000-00-00" || str == "0001-01-01" || str == "1900-01-01")
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (DateTime.TryParse(str, out var d))
|
|
||||||
{
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Entities;
|
|
||||||
using Dlhis.ScheduledTask.Extensions;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Comparers
|
|
||||||
{
|
|
||||||
internal class ZHRS_POSTComparer : IEqualityComparer<ZHRS_POST>
|
|
||||||
{
|
|
||||||
public bool Equals(ZHRS_POST x, ZHRS_POST y)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(x, y)) return true;
|
|
||||||
if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;
|
|
||||||
if (x.GetType() != y.GetType()) return false;
|
|
||||||
|
|
||||||
return x.BEGDA == y.BEGDA
|
|
||||||
&& x.ENDDA == y.ENDDA
|
|
||||||
&& x.LANGU == y.LANGU
|
|
||||||
&& x.ZJOBID == y.ZJOBID
|
|
||||||
&& x.ZJOBANME == y.ZJOBANME
|
|
||||||
&& x.ZZWID == y.ZZWID
|
|
||||||
&& x.ZDEPID == y.ZDEPID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetHashCode(ZHRS_POST obj)
|
|
||||||
{
|
|
||||||
return obj.BEGDA.SafeGetHashCode() ^ obj.ENDDA.SafeGetHashCode()
|
|
||||||
^ obj.LANGU.SafeGetHashCode() ^ obj.ZJOBID.SafeGetHashCode()
|
|
||||||
^ obj.ZJOBANME.SafeGetHashCode() ^ obj.ZZWID.SafeGetHashCode()
|
|
||||||
^ obj.ZDEPID.SafeGetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
using Kurisu.Core.ConfigurableOptions.Attributes;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Configurations
|
|
||||||
{
|
|
||||||
[Configuration]
|
|
||||||
public class ServiceSettings
|
|
||||||
{
|
|
||||||
public string ServerUrl { get; private set; }
|
|
||||||
|
|
||||||
public string UserName { get; private set; }
|
|
||||||
|
|
||||||
public string Password { get; private set; }
|
|
||||||
|
|
||||||
public string SyncTime { get; private set; }
|
|
||||||
public int AttendanceUploadInterval { get; private set; }
|
|
||||||
public string AttendanceUploadUrl { get; private set; }
|
|
||||||
public string DlhisDatabase { get; private set; }
|
|
||||||
|
|
||||||
public string Werks { get; private set; }
|
|
||||||
|
|
||||||
public DateTime BeginSyncDate { get; private set; }
|
|
||||||
public int ApiPort { get; private set; }
|
|
||||||
public string EHRWebServiceUserName { get; set; }
|
|
||||||
public string EHRWebServicePassword { get; set; }
|
|
||||||
public string EHRInsertRecordApiUrl { get; set; }
|
|
||||||
public string EHRDeleteRecordApiUrl { get; set; }
|
|
||||||
|
|
||||||
public string EHRSavePhotoApiUrl { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取员工卡片信息RESUT地址
|
|
||||||
/// </summary>
|
|
||||||
public string EHR_GET_WORK_CARD_INFOApiUrl { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// REST账号
|
|
||||||
/// </summary>
|
|
||||||
public string RestUserName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// REST密码
|
|
||||||
/// </summary>
|
|
||||||
public string RestPassword { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
private static int SafeParseInt(string value, int defaultValue = 0)
|
|
||||||
{
|
|
||||||
if (int.TryParse(value, out int i))
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool SafeParseBoolean(string value, bool defaultValue = false)
|
|
||||||
{
|
|
||||||
if (bool.TryParse(value, out var b))
|
|
||||||
{
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DateTime SafeParseDate(string value, DateTime defaultValue)
|
|
||||||
{
|
|
||||||
if (DateTime.TryParse(value, out var b))
|
|
||||||
{
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
Src/Dlhis.ScheduledTask/ContainerJobActivator.cs
Normal file
18
Src/Dlhis.ScheduledTask/ContainerJobActivator.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Hangfire;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask;
|
||||||
|
|
||||||
|
public class ContainerJobActivator : JobActivator
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public ContainerJobActivator(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ActivateJob(Type job)
|
||||||
|
{
|
||||||
|
return _serviceProvider.GetService(job);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
|
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
|
||||||
|
<ProjectReference Include="..\Dlhis.User.Api\Dlhis.User.Api.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,203 +0,0 @@
|
|||||||
namespace Dlhis.ScheduledTask.Dto
|
|
||||||
{
|
|
||||||
public class PersonDetail
|
|
||||||
{
|
|
||||||
public string KOSTL { get; set; }
|
|
||||||
|
|
||||||
public string ZLZRQ { get; set; }
|
|
||||||
public string ZZ_SFZH { get; set; }
|
|
||||||
|
|
||||||
public string STELL { get; set; }
|
|
||||||
|
|
||||||
public string STELL_NM { get; set; }
|
|
||||||
|
|
||||||
public string ZZ_KLX { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string PERNR { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZWORKCODE { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string MASSN { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 数据变更
|
|
||||||
/// </summary>
|
|
||||||
public string MNTXT { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string MASSG { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 数据变更
|
|
||||||
/// </summary>
|
|
||||||
public string MGTXT { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZSTATUS { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string STAT2 { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string BEGDA { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ENDDA { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string WERKS { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string PERSG { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string PERSK { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string BTRTL { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ANSVH { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string MOABW { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ORGEH { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string PLANS { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_ZYSF { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_AQJB { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_ZD { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_SJGH { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_BGZT { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Z_ZJ { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_XSQY { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 上海
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_LOC { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_COUN { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_CITY { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string NACHN { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string VORNA { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string NAME { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string GESCH { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string GBDAT { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string NATIO { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_QFRQ { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZMOBILE { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZEMAIL { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZADZH { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZRZRQ { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string DAT01 { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZCJRQ { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZZRQ { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 本科
|
|
||||||
/// </summary>
|
|
||||||
public string ZXUELI { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZ_ZPQD { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class T_PERSON
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public List<PersonDetail> item { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
using System.Security.Cryptography;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Entities
|
|
||||||
{
|
|
||||||
public partial class ZHRS_ORG
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 开始日期
|
|
||||||
/// </summary>
|
|
||||||
public string BEGDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结束日期
|
|
||||||
/// </summary>
|
|
||||||
public string ENDDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 语言
|
|
||||||
/// </summary>
|
|
||||||
public int LANGU { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门id
|
|
||||||
/// </summary>
|
|
||||||
public int OBJID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 部门名称
|
|
||||||
/// </summary>
|
|
||||||
public string STEXT { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上级部门
|
|
||||||
/// </summary>
|
|
||||||
public string SOBID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 公司
|
|
||||||
/// </summary>
|
|
||||||
public string ORGID01 { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 事业部
|
|
||||||
/// </summary>
|
|
||||||
public string ORGID02 { get; set; }
|
|
||||||
}
|
|
||||||
public partial class ZHRS_ORG : IEquatable<ZHRS_ORG>
|
|
||||||
{
|
|
||||||
public bool Equals(ZHRS_ORG other)
|
|
||||||
{
|
|
||||||
if (other is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return this.BEGDA == other.BEGDA
|
|
||||||
&& this.ENDDA == other.ENDDA
|
|
||||||
&& this.LANGU == other.LANGU
|
|
||||||
&& this.OBJID == other.OBJID
|
|
||||||
&& this.STEXT == other.STEXT
|
|
||||||
&& this.SOBID == other.SOBID
|
|
||||||
&& this.ORGID01 == other.ORGID01
|
|
||||||
&& this.ORGID02 == other.ORGID02;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj) => Equals(obj as ZHRS_ORG);
|
|
||||||
public override int GetHashCode() => (BEGDA, ENDDA, LANGU, OBJID, STEXT, SOBID, ORGID01, ORGID02).GetHashCode();
|
|
||||||
}
|
|
||||||
public class T_ORG
|
|
||||||
{
|
|
||||||
public List<ZHRS_ORG> item { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ZHRS_ORGResult
|
|
||||||
{
|
|
||||||
public T_ORG T_ORG { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
namespace Dlhis.ScheduledTask.Entities
|
|
||||||
{
|
|
||||||
public partial class ZHRS_POST
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 开始日期
|
|
||||||
/// </summary>
|
|
||||||
public string BEGDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 结束日期
|
|
||||||
/// </summary>
|
|
||||||
public string ENDDA { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 语言代码
|
|
||||||
/// </summary>
|
|
||||||
public int LANGU { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 岗位编码
|
|
||||||
/// </summary>
|
|
||||||
public string ZJOBID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 岗位名称
|
|
||||||
/// </summary>
|
|
||||||
public string ZJOBANME { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string ZZWID { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 所属部门ID
|
|
||||||
/// </summary>
|
|
||||||
public string ZDEPID { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class ZHRS_POST : IEquatable<ZHRS_POST>
|
|
||||||
{
|
|
||||||
public bool Equals(ZHRS_POST other)
|
|
||||||
{
|
|
||||||
if (other is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return this.BEGDA == other.BEGDA
|
|
||||||
&& this.ENDDA == other.ENDDA
|
|
||||||
&& this.LANGU == other.LANGU
|
|
||||||
&& this.ZJOBID == other.ZJOBID
|
|
||||||
&& this.ZJOBANME == other.ZJOBANME
|
|
||||||
&& this.ZZWID == other.ZZWID
|
|
||||||
&& this.ZDEPID == other.ZDEPID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj) => Equals(obj as ZHRS_POST);
|
|
||||||
public override int GetHashCode() => (BEGDA, ENDDA, LANGU, ZJOBID, ZJOBANME, ZZWID, ZDEPID).GetHashCode();
|
|
||||||
}
|
|
||||||
public class T_POST
|
|
||||||
{
|
|
||||||
public List<ZHRS_POST> item { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ZHRS_POSTResult
|
|
||||||
{
|
|
||||||
public T_POST T_POST { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
namespace Dlhis.ScheduledTask.Extensions
|
|
||||||
{
|
|
||||||
internal static class GetHashCodeExtensions
|
|
||||||
{
|
|
||||||
public static int SafeGetHashCode(this object o)
|
|
||||||
{
|
|
||||||
if (o == null) return 0;
|
|
||||||
return o.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int SafeGetHashCode(this int o)
|
|
||||||
{
|
|
||||||
return o.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using Hangfire;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Job
|
|
||||||
{
|
|
||||||
public class HangfireActivator : JobActivator
|
|
||||||
{
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
|
|
||||||
public HangfireActivator(IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override object? ActivateJob(Type jobType)
|
|
||||||
{
|
|
||||||
return _serviceProvider.GetService(jobType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Comparers;
|
|
||||||
using Dlhis.ScheduledTask.Entities;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using Mapster;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Job
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 部门同步定时任务
|
|
||||||
/// </summary>
|
|
||||||
public class SyncOrgInfoJob
|
|
||||||
{
|
|
||||||
private List<ZHRS_ORG> lastUpdatedOrgList = new List<ZHRS_ORG>();
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
|
|
||||||
public SyncOrgInfoJob(IDbContext dbContext)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task SyncOrgInfo()
|
|
||||||
{
|
|
||||||
HttpClient httpClient = new HttpClient();
|
|
||||||
httpClient.Timeout = TimeSpan.FromMinutes(10);
|
|
||||||
var credentials = string.Format("{0}:{1}", "EHS_USER", "y3R1hd2h*RICAC");
|
|
||||||
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);
|
|
||||||
|
|
||||||
string apiUrl = "http://sappidap.jinkosolar.cn:51000/RESTAdapter/Rest/EHR_ORGANIZATION/";
|
|
||||||
|
|
||||||
|
|
||||||
string requestBody = "{\"I_DATE\":\"2021-01-01\",\"I_DATE_TO\":\"2022-05-29\",\"I_LANGU\":\"1\",\"T_ID\":{\"item\":[{\"OBJID\":\"50007967\"},{\"OBJID\":\"50008308\"}]}}";
|
|
||||||
|
|
||||||
HttpResponseMessage response = await httpClient.PostAsync(apiUrl, new StringContent(requestBody, Encoding.UTF8, "application/json"));
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
string responseData = await response.Content.ReadAsStringAsync();
|
|
||||||
ZHRS_ORGResult orgResult = JsonSerializer.Deserialize<ZHRS_ORGResult>(responseData);
|
|
||||||
|
|
||||||
if (orgResult.T_ORG != null && orgResult.T_ORG.item.Count > 0)
|
|
||||||
{
|
|
||||||
var modifiedOrgList = GetModifiedOrg(orgResult.T_ORG?.item);
|
|
||||||
|
|
||||||
// 使用 SQLSugar 将新数据同步到数据库
|
|
||||||
await SaveOrg(modifiedOrgList);
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// Console.WriteLine($"HTTP请求失败,状态码:{response.StatusCode}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ZHRS_ORG> GetModifiedOrg(List<ZHRS_ORG> sapList)
|
|
||||||
{
|
|
||||||
if (lastUpdatedOrgList.Count <= 0)
|
|
||||||
{
|
|
||||||
return sapList;
|
|
||||||
}
|
|
||||||
|
|
||||||
var needRemove = sapList.Intersect(lastUpdatedOrgList, new ZHRS_ORGComparer());
|
|
||||||
return sapList.Except(needRemove, new ZHRS_ORGComparer()).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveOrg(List<ZHRS_ORG> modifiedOrgList)
|
|
||||||
{
|
|
||||||
if (modifiedOrgList == null || modifiedOrgList.Count == 0) return;
|
|
||||||
|
|
||||||
foreach (ZHRS_ORG item in modifiedOrgList)
|
|
||||||
{
|
|
||||||
var existingOrgs = await _dbContext.Queryable<ZHRF_SYN_01Entity>().Where(x => x.OBJID == item.OBJID).FirstAsync();
|
|
||||||
|
|
||||||
if (existingOrgs != null)
|
|
||||||
{
|
|
||||||
var org = item.Adapt(existingOrgs);
|
|
||||||
await _dbContext.UpdateAsync(org);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var org = item.Adapt<ZHRF_SYN_01Entity>();
|
|
||||||
await _dbContext.InsertAsync(org);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,452 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Comparers;
|
|
||||||
using Dlhis.ScheduledTask.Dto;
|
|
||||||
using Dlhis.ScheduledTask.Entities;
|
|
||||||
using Dlhis.ScheduledTask.Response;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Data.SqlClient;
|
|
||||||
using System.Data;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using Dlhis.ScheduledTask.Configurations;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Basic.Enums;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Job
|
|
||||||
{
|
|
||||||
public class SyncPersonJob
|
|
||||||
{
|
|
||||||
|
|
||||||
private List<PersonDetail> lastUpdatedPersonList = new List<PersonDetail>();
|
|
||||||
private List<ZHRS_ORG> lastUpdatedOrgList = new List<ZHRS_ORG>();
|
|
||||||
private List<ZHRS_POST> lastUpdatedPositionList = new List<ZHRS_POST>();
|
|
||||||
private readonly ServiceSettings serviceSettings;
|
|
||||||
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
public SyncPersonJob(IDbContext dbContext)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SyncPersonInfo()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//var personResp = JsonConvert.DeserializeObject<PersonResult>(File.ReadAllText("C:\\Users\\79144\\Desktop\\request.json")); // GetPersons();
|
|
||||||
var personResp = GetPersons();// JsonConvert.DeserializeObject<PersonResult>(File.ReadAllText("Cache/request.json")); // GetPersons();
|
|
||||||
var persons = personResp.T_PERSON.item;
|
|
||||||
//log.Info("获取人员信息成功,count:" + persons.Count);
|
|
||||||
File.WriteAllText("Cache/request.json", JsonConvert.SerializeObject(personResp));
|
|
||||||
//log.Info("请求数据保存到Cache/request.json");
|
|
||||||
|
|
||||||
if (persons.Count > 0)
|
|
||||||
{
|
|
||||||
var modifiedPersons = GetModifiedPerson(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
|
|
||||||
//WhyDiff(modifiedPersons.Last());
|
|
||||||
//log.Info($"同步人员差异数据:{modifiedPersons.Count}");
|
|
||||||
if (modifiedPersons.Count > 0)
|
|
||||||
{
|
|
||||||
var failedRecords = SavePerson(modifiedPersons);
|
|
||||||
//log.Info($"同步人员数据完成,成功{modifiedPersons.Count - failedRecords}条, 失败:{failedRecords}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//log.Info($"同步人员数据完成,无数据变更");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
//log.Error("同步人员信息失败", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<int> SavePerson(List<PersonDetail> persons)
|
|
||||||
{
|
|
||||||
|
|
||||||
var workCodes = persons.Select(x => x.ZWORKCODE).ToList();
|
|
||||||
|
|
||||||
var index = 1;
|
|
||||||
var count = 4000;
|
|
||||||
var failure = 0;
|
|
||||||
var total = persons.Count;
|
|
||||||
// log.Debug($"{i}/{persons.Count}\tName={person.NAME}\tIdNo={person.ZZ_SFZH}\tPERNR={person.PERNR}");
|
|
||||||
|
|
||||||
//log.Debug($"一共{persons.Count}条差异数据");
|
|
||||||
|
|
||||||
//var conn = OpenDlDbConnection();
|
|
||||||
|
|
||||||
var searchCodes = workCodes.Skip((index - 1) * count).Take(count).ToList();
|
|
||||||
while (searchCodes.Count > 0)
|
|
||||||
{
|
|
||||||
//var existsWorkCodes = conn.Query<string>($"select ename from gainfo_sap where ename in ( {string.Join(",", searchCodes.Select(x => $"'{x}'"))} )")
|
|
||||||
// .ToList();
|
|
||||||
var existsWorkCodes = _dbContext.Queryable<GainfoEntity>()
|
|
||||||
.Where(x => searchCodes.Contains(x.Code))
|
|
||||||
.Select(x => x.Code)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var originUpdates = persons.Where(x => existsWorkCodes.Contains(x.ZWORKCODE)).ToList();
|
|
||||||
var originInserts = persons.Where(x => searchCodes.Contains(x.ZWORKCODE)).Except(originUpdates, new ZHRS_PERSONComparer()).ToList();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
if (originUpdates.Count + originInserts.Count <= count)
|
|
||||||
{
|
|
||||||
var currentTotal = originUpdates.Count + originInserts.Count;
|
|
||||||
//log.Debug($"正在进行第{index}批次,需要处理{currentTotal}条数据");
|
|
||||||
|
|
||||||
var updates = ToGainfoSap(originUpdates);
|
|
||||||
var inserts = ToGainfoSap(originInserts);
|
|
||||||
|
|
||||||
foreach (var item in inserts)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await SavePerson(item);
|
|
||||||
//conn.Execute(SqlGeneration.InsertSql, item);
|
|
||||||
//log.Debug($"执行新增{i}/{currentTotal} name:{item.gname},ename:{item.ename}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
failure++;
|
|
||||||
//log.Error($"执行新增{i}/{currentTotal} name:{item.gname},ename:{item.ename}失败 \r\n{ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var item in updates)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await UpdatePerson(item);
|
|
||||||
//conn.Execute(SqlGeneration.UpdateSql, item);
|
|
||||||
//log.Debug($"执行更新{i}/{currentTotal} name:{item.gname},ename:{item.ename}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
failure++;
|
|
||||||
//log.Error($"执行更新{i}/{currentTotal} name:{item.gname},ename:{item.ename}失败 \r\n{ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
persons = persons.Except(originUpdates).Except(originUpdates).ToList();
|
|
||||||
searchCodes = workCodes.Skip((index - 1) * count).Take(count).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SavePerson(GainfoSapEntity item)
|
|
||||||
{
|
|
||||||
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.IdNo == item.idno).FirstAsync();
|
|
||||||
if (gainfo != null)
|
|
||||||
{
|
|
||||||
gainfo.No = item.guestno;
|
|
||||||
gainfo.SapNo = item.ano;
|
|
||||||
gainfo.Type = item.@class;
|
|
||||||
gainfo.Name = item.gname;
|
|
||||||
gainfo.Code = item.ename;
|
|
||||||
gainfo.CountryNo = item.country;
|
|
||||||
gainfo.IdClass = item.idcls;
|
|
||||||
gainfo.Native = item.native;
|
|
||||||
gainfo.Gender = item.sex == "F" ? GenderEnumType.Female : GenderEnumType.Male;
|
|
||||||
gainfo.Birthday = (DateTime)item.birthday;
|
|
||||||
gainfo.Address = item.address;
|
|
||||||
gainfo.DepartmentNo = item.appellation;
|
|
||||||
gainfo.Nation = item.nation;
|
|
||||||
gainfo.Phone = item.phone;
|
|
||||||
gainfo.Degree = item.email;
|
|
||||||
gainfo.Position = item.web;
|
|
||||||
gainfo.Remark = item.remark;
|
|
||||||
gainfo.Werks = item.WERKS;
|
|
||||||
gainfo.Employed = item.isowner; //int.Parse(person.ZSTATUS) < 4 ? "T" : "F", 是否离职
|
|
||||||
await _dbContext.UpdateAsync(gainfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var info = new GainfoEntity
|
|
||||||
{
|
|
||||||
No = item.guestno,
|
|
||||||
SapNo = item.ano,
|
|
||||||
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,
|
|
||||||
//Marital 已婚未婚
|
|
||||||
//Occuption = item.occuption,
|
|
||||||
DepartmentNo = item.appellation,
|
|
||||||
Nation =item.nation,
|
|
||||||
Phone = item.phone,
|
|
||||||
Degree = item.email,
|
|
||||||
Position = item.web,
|
|
||||||
//CarNo
|
|
||||||
Remark = item.remark,
|
|
||||||
Werks = item.WERKS,
|
|
||||||
Employed = item.isowner,
|
|
||||||
};
|
|
||||||
await _dbContext.InsertAsync(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async Task UpdatePerson(GainfoSapEntity item)
|
|
||||||
{
|
|
||||||
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.IdNo == item.idno).FirstAsync();
|
|
||||||
if (gainfo != null)
|
|
||||||
{
|
|
||||||
_dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
|
||||||
{
|
|
||||||
SapNo = item.PERNR,
|
|
||||||
Name = item.gname,
|
|
||||||
Code = item.ename,
|
|
||||||
Position = item.web,
|
|
||||||
Phone = item.phone,
|
|
||||||
DepartmentNo = item.appellation,
|
|
||||||
Employed = item.isowner,
|
|
||||||
Remark = item.remark,
|
|
||||||
Degree = item.email,
|
|
||||||
Werks = item.WERKS
|
|
||||||
})
|
|
||||||
.Where(g => g.IdNo == item.idno
|
|
||||||
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.IdNo == item.idno && g.SapNo != item.PERNR && g.Employed == "T")
|
|
||||||
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.IdNo == item.idno && int.Parse(g.SapNo) > int.Parse(item.PERNR) && g.Employed == item.isowner));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
|
||||||
{
|
|
||||||
SapNo = item.PERNR,
|
|
||||||
Name = item.gname,
|
|
||||||
Code = item.ename,
|
|
||||||
Position = item.web,
|
|
||||||
Phone = item.phone,
|
|
||||||
DepartmentNo = item.appellation,
|
|
||||||
Employed = item.isowner,
|
|
||||||
Remark = item.remark,
|
|
||||||
Degree = item.email,
|
|
||||||
Werks = item.WERKS
|
|
||||||
})
|
|
||||||
.Where(g => g.SapNo == item.PERNR
|
|
||||||
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.Code == item.ename && g.Employed == "T")
|
|
||||||
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.IdNo == item.idno && int.Parse(g.SapNo) > int.Parse(item.PERNR) && g.Employed == item.isowner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private PersonResult GetPersons()
|
|
||||||
{
|
|
||||||
HttpClient httpClient = new HttpClient();
|
|
||||||
httpClient.Timeout = TimeSpan.FromMinutes(10);
|
|
||||||
var credentials = string.Format("{0}:{1}", "EHS_USER", "y3R1hd2h*RICAC");
|
|
||||||
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);
|
|
||||||
|
|
||||||
List<PersonDetail> persons = new();
|
|
||||||
//foreach (var item in werks)
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var body = new
|
|
||||||
// {
|
|
||||||
// T_WERKS = new
|
|
||||||
// {
|
|
||||||
// item = new List<object>
|
|
||||||
// {
|
|
||||||
// new
|
|
||||||
// {
|
|
||||||
// item.WERKS
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// T_PERSON = Array.Empty<string>(),
|
|
||||||
// T_PNO = Array.Empty<string>(),
|
|
||||||
// };
|
|
||||||
// var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
// var response = httpClient.PostAsync("http://sappipap01.jinkosolar.cn:50100/RESTAdapter/Rest/EHR_PERSONNEL/", content).Result;
|
|
||||||
|
|
||||||
// var jsonResponse = response.Content.ReadAsStringAsync().Result;
|
|
||||||
// if (response.IsSuccessStatusCode)
|
|
||||||
// {
|
|
||||||
// PersonResult personResp = JsonConvert.DeserializeObject<PersonResult>(jsonResponse);
|
|
||||||
// if (personResp?.T_PERSON?.item?.Any() == true)
|
|
||||||
// {
|
|
||||||
// persons.AddRange(personResp.T_PERSON.item);
|
|
||||||
// //log.Info($"人事范围[{item.WERKS}]获取{personResp.T_PERSON.item.Count}条数据");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// throw new Exception($"请求异常:{response.StatusCode}:" + jsonResponse);
|
|
||||||
// }
|
|
||||||
// // this is webservice call
|
|
||||||
// //var personResp = archivesClient.ZHRF_SYN_03(new ZHRF_SYN_03()
|
|
||||||
// //{
|
|
||||||
// // //I_DATE = Settings.BeginSyncDate.ToString("yyy-MM-dd"),
|
|
||||||
// // T_PERSON = Array.Empty<ZHRS_PERSON>(),
|
|
||||||
// // T_PNO = Array.Empty<ZHRS_PNO>(),
|
|
||||||
// // T_WERKS = new ZHRS_WERKS[] { item },
|
|
||||||
// //});
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// //log.Error($"人事范围[{item.WERKS}]获取失败:{ex.Message}", ex);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
return new PersonResult()
|
|
||||||
{
|
|
||||||
T_PERSON = new T_PERSON
|
|
||||||
{
|
|
||||||
item = persons
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
private List<PersonDetail> GetModifiedPerson(List<PersonDetail> sapList)
|
|
||||||
{
|
|
||||||
if (lastUpdatedPersonList.Count <= 0)
|
|
||||||
{
|
|
||||||
return sapList;
|
|
||||||
}
|
|
||||||
var needRemove = sapList.Intersect(lastUpdatedPersonList, new ZHRS_PERSONComparer());
|
|
||||||
return sapList.Except(needRemove, new ZHRS_PERSONComparer()).ToList();
|
|
||||||
}
|
|
||||||
private List<GainfoSapEntity> ToGainfoSap(List<PersonDetail> data)
|
|
||||||
{
|
|
||||||
return data.Select(person =>
|
|
||||||
{
|
|
||||||
GainfoSapEntity o = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
var position = lastUpdatedPositionList.FirstOrDefault(x => x.ZJOBID == 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)
|
|
||||||
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?.ZJOBANME, 30),
|
|
||||||
logdate = DateTime.Now,
|
|
||||||
isowner = int.Parse(person.ZSTATUS) < 4 ? "T" : "F",
|
|
||||||
@class = "C",
|
|
||||||
country = "CN",
|
|
||||||
log_ip = "127.0.0.1",
|
|
||||||
log_shift = "1",
|
|
||||||
log_id = "XX",
|
|
||||||
address = "",
|
|
||||||
occupation = "99",
|
|
||||||
nation = "01"
|
|
||||||
};
|
|
||||||
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
private string GetNative(string idno)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(idno) || idno.Length < 6) return null;
|
|
||||||
idno = idno.TrimStart();
|
|
||||||
return idno.Substring(0, 6);
|
|
||||||
}
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
private IDbConnection OpenDlDbConnection()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IDbConnection conn = new SqlConnection(serviceSettings.DlhisDatabase);
|
|
||||||
if (conn.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
conn.Open();
|
|
||||||
}
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"打开迪联数据库错误:{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Comparers;
|
|
||||||
using Dlhis.ScheduledTask.Entities;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using Mapster;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Job
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 职位同步定时任务
|
|
||||||
/// </summary>
|
|
||||||
public class SyncPositionJob
|
|
||||||
{
|
|
||||||
private List<ZHRS_POST> lastUpdatedPositionList = new List<ZHRS_POST>();
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
|
|
||||||
public SyncPositionJob(IDbContext dbContext)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
}
|
|
||||||
public async Task SyncPositionInfo()
|
|
||||||
{
|
|
||||||
HttpClient httpClient = new HttpClient();
|
|
||||||
httpClient.Timeout = TimeSpan.FromMinutes(10);
|
|
||||||
var credentials = string.Format("{0}:{1}", "EHS_USER", "y3R1hd2h*RICAC");
|
|
||||||
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
|
|
||||||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);
|
|
||||||
|
|
||||||
string url = "http://sappidap.jinkosolar.cn:51000/RESTAdapter/Rest/EHR_POSITION/";
|
|
||||||
|
|
||||||
string requestBody = "{\"I_DATE\":\"2022-05-26\",\"I_DATE_TO\":\"2022-05-29\",\"I_LANGU\":\"1\",\"I_ALLINFO\":\"X\"}";
|
|
||||||
|
|
||||||
StringContent content = new StringContent(requestBody, Encoding.UTF8, "application/json");
|
|
||||||
|
|
||||||
HttpResponseMessage response = await httpClient.PostAsync(url, content);
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
string responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
var postResult = JsonConvert.DeserializeObject<ZHRS_POSTResult>(responseContent);
|
|
||||||
|
|
||||||
if (postResult.T_POST != null && postResult.T_POST.item.Count > 0)
|
|
||||||
{
|
|
||||||
var modifiedOrgList = GetModifiedPosition(postResult.T_POST.item);
|
|
||||||
|
|
||||||
// 步骤 4:使用 SQLSugar 将新数据同步到数据库
|
|
||||||
SaveOrg(modifiedOrgList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"HTTP请求失败,状态码:{response.StatusCode}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ZHRS_POST> GetModifiedPosition(List<ZHRS_POST> spaList)
|
|
||||||
{
|
|
||||||
if (lastUpdatedPositionList.Count <= 0)
|
|
||||||
{
|
|
||||||
return spaList;
|
|
||||||
}
|
|
||||||
var needRemove = spaList.Intersect(lastUpdatedPositionList, new ZHRS_POSTComparer());
|
|
||||||
return spaList.Except(needRemove, new ZHRS_POSTComparer()).ToList();
|
|
||||||
}
|
|
||||||
private async void SaveOrg(List<ZHRS_POST> modifiedPostList)
|
|
||||||
{
|
|
||||||
if (modifiedPostList == null || modifiedPostList.Count == 0) return;
|
|
||||||
|
|
||||||
foreach (var item in modifiedPostList)
|
|
||||||
{
|
|
||||||
var existingPosts = await _dbContext.Queryable<ZHRF_SYN_02Entity>().Where(x =>x.ZJOBID == item.ZJOBID).FirstAsync();
|
|
||||||
if (existingPosts != null)
|
|
||||||
{
|
|
||||||
var entity = item.Adapt(existingPosts);
|
|
||||||
await _dbContext.UpdateAsync(entity);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var entity = item.Adapt<ZHRF_SYN_02Entity>();
|
|
||||||
await _dbContext.InsertAsync(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using Hangfire;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Job;
|
|
||||||
|
|
||||||
public static class UseHangfire
|
|
||||||
{
|
|
||||||
public static void UseHangfireto(this IServiceCollection services)
|
|
||||||
{
|
|
||||||
GlobalConfiguration.Configuration.UseActivator(new HangfireActivator(services.BuildServiceProvider()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using Dlhis.ScheduledTask.Configurations;
|
using Dlhis.ScheduledTask.SyncSapInfo.Job;
|
||||||
using Dlhis.ScheduledTask.Job;
|
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
using Hangfire.Dashboard.BasicAuthorization;
|
using Hangfire.Dashboard.BasicAuthorization;
|
||||||
using Hangfire.MySql;
|
using Hangfire.MySql;
|
||||||
@@ -10,17 +9,17 @@ namespace Dlhis.ScheduledTask.Packs;
|
|||||||
|
|
||||||
public class HangfirePack : BaseAppPack
|
public class HangfirePack : BaseAppPack
|
||||||
{
|
{
|
||||||
|
public override int Order => 999;
|
||||||
|
|
||||||
public override bool IsBeforeUseRouting { get; }
|
public override bool IsBeforeUseRouting { get; }
|
||||||
|
|
||||||
public override void ConfigureServices(IServiceCollection services)
|
public override void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
||||||
services.Configure<ServiceSettings>(Configuration.GetSection("ServiceSettings"));
|
|
||||||
services.AddHangfire(configuration =>
|
services.AddHangfire(configuration =>
|
||||||
{
|
{
|
||||||
var options = new MySqlStorageOptions
|
var options = new MySqlStorageOptions
|
||||||
{
|
{
|
||||||
TablesPrefix = "Hangfire"
|
TablesPrefix = "hangfire"
|
||||||
};
|
};
|
||||||
|
|
||||||
configuration.UseSimpleAssemblyNameTypeSerializer()
|
configuration.UseSimpleAssemblyNameTypeSerializer()
|
||||||
@@ -28,12 +27,13 @@ public class HangfirePack : BaseAppPack
|
|||||||
.UseStorage(new MySqlStorage(Configuration.GetConnectionString("HangfireConnection"), options));
|
.UseStorage(new MySqlStorage(Configuration.GetConnectionString("HangfireConnection"), options));
|
||||||
|
|
||||||
});
|
});
|
||||||
services.UseHangfireto();
|
|
||||||
services.AddHangfireServer();
|
services.AddHangfireServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
|
GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(app.ApplicationServices));
|
||||||
|
|
||||||
app.UseHangfireDashboard("/hangfire", new DashboardOptions
|
app.UseHangfireDashboard("/hangfire", new DashboardOptions
|
||||||
{
|
{
|
||||||
@@ -61,13 +61,10 @@ public class HangfirePack : BaseAppPack
|
|||||||
|
|
||||||
#region 周期任务
|
#region 周期任务
|
||||||
//0:00
|
//0:00
|
||||||
RecurringJob.AddOrUpdate<SyncOrgInfoJob>("SyncOrgInfoJob_id", s => s.SyncOrgInfo(), "0 0 16 * * ?");
|
RecurringJob.AddOrUpdate<SyncOrganizationJob>("SysSap", s => s.SyncOrgInfo(), "30 * * * * ?", new RecurringJobOptions
|
||||||
|
{
|
||||||
//1:00
|
TimeZone = TimeZoneInfo.Local
|
||||||
RecurringJob.AddOrUpdate<SyncPositionJob>("SyncPositionJob_id", s => s.SyncPositionInfo(), "0 0 17 * * ?");
|
});
|
||||||
|
|
||||||
//2:00
|
|
||||||
RecurringJob.AddOrUpdate<SyncPersonJob>("SyncPersonJob_id", s => s.SyncPersonInfo(), "0 0 18 * * ?");
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
Src/Dlhis.ScheduledTask/Packs/JinkoSapHttpClientPack.cs
Normal file
22
Src/Dlhis.ScheduledTask/Packs/JinkoSapHttpClientPack.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text;
|
||||||
|
using Kurisu.AspNetCore.Startup;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Packs;
|
||||||
|
|
||||||
|
public class JinkoSapHttpClientPack : BaseAppPack
|
||||||
|
{
|
||||||
|
public override bool IsBeforeUseRouting { get; }
|
||||||
|
|
||||||
|
public override void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddHttpClient("jinko:sap", (sp, httpClient) =>
|
||||||
|
{
|
||||||
|
httpClient.Timeout = TimeSpan.FromMinutes(10);
|
||||||
|
|
||||||
|
var credentials = string.Format("{0}:{1}", "EHS_USER", "y3R1hd2h*RICAC");
|
||||||
|
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
|
||||||
|
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using Dlhis.ScheduledTask.Dto;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Response
|
|
||||||
{
|
|
||||||
public class PersonResult
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public T_PERSON T_PERSON { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机构数据比较器
|
||||||
|
/// </summary>
|
||||||
|
public class SapOrganizationComparer : IEqualityComparer<SapOrganizationItem>
|
||||||
|
{
|
||||||
|
public bool Equals(SapOrganizationItem x, SapOrganizationItem y)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(x, y)) return true;
|
||||||
|
if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;
|
||||||
|
if (x.GetType() != y.GetType()) return false;
|
||||||
|
|
||||||
|
return x.BEGDA == y.BEGDA
|
||||||
|
&& x.ENDDA == y.ENDDA
|
||||||
|
&& x.LANGU == y.LANGU
|
||||||
|
&& x.OBJID == y.OBJID
|
||||||
|
&& x.STEXT == y.STEXT
|
||||||
|
&& x.SOBID == y.SOBID
|
||||||
|
&& x.ORGID01 == y.ORGID01
|
||||||
|
&& x.ORGID02 == y.ORGID02;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(SapOrganizationItem obj)
|
||||||
|
{
|
||||||
|
return obj.BEGDA.SafeGetHashCode() ^ obj.ENDDA.SafeGetHashCode()
|
||||||
|
^ obj.LANGU.SafeGetHashCode() ^ obj.OBJID.SafeGetHashCode()
|
||||||
|
^ obj.STEXT.SafeGetHashCode() ^ obj.SOBID.SafeGetHashCode()
|
||||||
|
^ obj.ORGID01.SafeGetHashCode() ^ obj.ORGID02.SafeGetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 人员信息比较器
|
||||||
|
/// </summary>
|
||||||
|
public class SapPersonComparer : IEqualityComparer<SapPersonItem>
|
||||||
|
{
|
||||||
|
public bool Equals(SapPersonItem x, SapPersonItem y)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(x, y)) return true;
|
||||||
|
if (ReferenceEquals(x, null)) return false;
|
||||||
|
if (ReferenceEquals(y, null)) return false;
|
||||||
|
|
||||||
|
return x.PERNR == y.PERNR
|
||||||
|
&& x.WERKS == y.WERKS
|
||||||
|
&& SubString(x.ORGEH, 10) == SubString(y.ORGEH, 10)
|
||||||
|
&& SubString(x.NAME, 50) == SubString(y.NAME, 50)
|
||||||
|
&& SafeParseDate(x.GBDAT) == SafeParseDate(y.GBDAT)
|
||||||
|
&& SubString(x.ZZ_SFZH, 18) == SubString(y.ZZ_SFZH, 18)
|
||||||
|
&& SubString(x.ZWORKCODE, 50) == SubString(y.ZWORKCODE, 50)
|
||||||
|
&& SubString(x.ZMOBILE, 20) == SubString(y.ZMOBILE, 20)
|
||||||
|
&& x.ZSTATUS == y.ZSTATUS
|
||||||
|
&& x.KOSTL == y.KOSTL
|
||||||
|
&& x.ZZ_ZD == y.ZZ_ZD
|
||||||
|
&& x.Z_ZJ == y.Z_ZJ
|
||||||
|
&& x.ZRZRQ == y.ZRZRQ
|
||||||
|
&& SafeParseDate(x.ZLZRQ) == SafeParseDate(y.ZLZRQ)
|
||||||
|
&& x.STELL == y.STELL
|
||||||
|
&& x.STELL_NM == y.STELL_NM
|
||||||
|
&& x.MASSN == y.MASSN
|
||||||
|
&& x.MNTXT == y.MNTXT
|
||||||
|
&& (x.ZXUELI ?? string.Empty).Trim() == (y.ZXUELI ?? string.Empty).Trim()
|
||||||
|
&& (x.ZZ_KLX ?? string.Empty) == (y.ZZ_KLX ?? string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(SapPersonItem obj)
|
||||||
|
{
|
||||||
|
return obj.PERNR.SafeGetHashCode()
|
||||||
|
^ obj.WERKS.SafeGetHashCode()
|
||||||
|
^ SubString(obj.ORGEH, 10).SafeGetHashCode()
|
||||||
|
^ SubString(obj.NAME, 50).SafeGetHashCode()
|
||||||
|
^ SafeParseDate(obj.GBDAT).SafeGetHashCode()
|
||||||
|
^ SubString(obj.ZZ_SFZH, 18).SafeGetHashCode()
|
||||||
|
^ SubString(obj.ZWORKCODE, 50).SafeGetHashCode()
|
||||||
|
^ SubString(obj.ZMOBILE, 20).SafeGetHashCode()
|
||||||
|
^ obj.ZSTATUS.SafeGetHashCode()
|
||||||
|
^ obj.KOSTL.SafeGetHashCode()
|
||||||
|
^ obj.ZZ_ZD.SafeGetHashCode()
|
||||||
|
^ obj.Z_ZJ.SafeGetHashCode()
|
||||||
|
^ obj.ZRZRQ.SafeGetHashCode()
|
||||||
|
^ SafeParseDate(obj.ZLZRQ).SafeGetHashCode()
|
||||||
|
^ obj.STELL.SafeGetHashCode()
|
||||||
|
^ obj.STELL_NM.SafeGetHashCode()
|
||||||
|
^ obj.MASSN.SafeGetHashCode()
|
||||||
|
^ obj.MNTXT.SafeGetHashCode()
|
||||||
|
^ obj.ZXUELI.SafeGetHashCode()
|
||||||
|
^ (obj.ZZ_KLX ?? "").SafeGetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DateTime? SafeParseDate(string str)
|
||||||
|
{
|
||||||
|
if (str == "0000-00-00" || str == "0001-01-01" || str == "1900-01-01")
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (DateTime.TryParse(str, out var d))
|
||||||
|
{
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 岗位信息比较器
|
||||||
|
/// </summary>
|
||||||
|
public class SapPositionComparer : IEqualityComparer<SapPositionItem>
|
||||||
|
{
|
||||||
|
public bool Equals(SapPositionItem x, SapPositionItem y)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(x, y)) return true;
|
||||||
|
if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;
|
||||||
|
if (x.GetType() != y.GetType()) return false;
|
||||||
|
|
||||||
|
return x.BEGDA == y.BEGDA
|
||||||
|
&& x.ENDDA == y.ENDDA
|
||||||
|
&& x.LANGU == y.LANGU
|
||||||
|
&& x.ZJOBID == y.ZJOBID
|
||||||
|
&& x.ZJOBANME == y.ZJOBANME
|
||||||
|
&& x.ZZWID == y.ZZWID
|
||||||
|
&& x.ZDEPID == y.ZDEPID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(SapPositionItem obj)
|
||||||
|
{
|
||||||
|
return obj.BEGDA.SafeGetHashCode() ^ obj.ENDDA.SafeGetHashCode()
|
||||||
|
^ obj.LANGU.SafeGetHashCode() ^ obj.ZJOBID.SafeGetHashCode()
|
||||||
|
^ obj.ZJOBANME.SafeGetHashCode() ^ obj.ZZWID.SafeGetHashCode()
|
||||||
|
^ obj.ZDEPID.SafeGetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapOrganization.cs
Normal file
15
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapOrganization.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sap机构信息
|
||||||
|
/// </summary>
|
||||||
|
public class SapOrganization
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 机构项
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("item")]
|
||||||
|
public List<SapOrganizationItem> Items { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
public class SapOrganizationItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 开始日期
|
||||||
|
/// </summary>
|
||||||
|
public string BEGDA { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 结束日期
|
||||||
|
/// </summary>
|
||||||
|
public string ENDDA { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 语言
|
||||||
|
/// </summary>
|
||||||
|
public int LANGU { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门id
|
||||||
|
/// </summary>
|
||||||
|
public string OBJID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门名称
|
||||||
|
/// </summary>
|
||||||
|
public string STEXT { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上级部门
|
||||||
|
/// </summary>
|
||||||
|
public string SOBID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公司
|
||||||
|
/// </summary>
|
||||||
|
public string ORGID01 { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 事业部
|
||||||
|
/// </summary>
|
||||||
|
public string ORGID02 { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//public partial class SapOrganizationItem : IEquatable<SapOrganizationItem>
|
||||||
|
//{
|
||||||
|
// public bool Equals(SapOrganizationItem other)
|
||||||
|
// {
|
||||||
|
// if (other is null)
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
// return this.BEGDA == other.BEGDA
|
||||||
|
// && this.ENDDA == other.ENDDA
|
||||||
|
// && this.LANGU == other.LANGU
|
||||||
|
// && this.OBJID == other.OBJID
|
||||||
|
// && this.STEXT == other.STEXT
|
||||||
|
// && this.SOBID == other.SOBID
|
||||||
|
// && this.ORGID01 == other.ORGID01
|
||||||
|
// && this.ORGID02 == other.ORGID02;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override bool Equals(object obj) => Equals(obj as SapOrganizationItem);
|
||||||
|
// public override int GetHashCode() => (BEGDA, ENDDA, LANGU, OBJID, STEXT, SOBID, ORGID01, ORGID02).GetHashCode();
|
||||||
|
//}
|
||||||
12
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPerson.cs
Normal file
12
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPerson.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
public class SapPerson
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("item")]
|
||||||
|
public List<SapPersonItem> Items { get; set; }
|
||||||
|
}
|
||||||
192
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPersonItem.cs
Normal file
192
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPersonItem.cs
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
public class SapPersonItem
|
||||||
|
{
|
||||||
|
public string KOSTL { get; set; }
|
||||||
|
|
||||||
|
public string ZLZRQ { get; set; }
|
||||||
|
public string ZZ_SFZH { get; set; }
|
||||||
|
|
||||||
|
public string STELL { get; set; }
|
||||||
|
|
||||||
|
public string STELL_NM { get; set; }
|
||||||
|
|
||||||
|
public string ZZ_KLX { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string PERNR { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZWORKCODE { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string MASSN { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 数据变更
|
||||||
|
/// </summary>
|
||||||
|
public string MNTXT { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string MASSG { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 数据变更
|
||||||
|
/// </summary>
|
||||||
|
public string MGTXT { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZSTATUS { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string STAT2 { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string BEGDA { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ENDDA { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string WERKS { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string PERSG { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string PERSK { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string BTRTL { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ANSVH { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string MOABW { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ORGEH { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string PLANS { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_ZYSF { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_AQJB { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_ZD { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_SJGH { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_BGZT { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string Z_ZJ { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_XSQY { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 上海
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_LOC { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_COUN { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_CITY { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string NACHN { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string VORNA { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string NAME { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string GESCH { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string GBDAT { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string NATIO { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_QFRQ { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZMOBILE { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZEMAIL { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZADZH { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZRZRQ { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string DAT01 { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZCJRQ { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZZRQ { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 本科
|
||||||
|
/// </summary>
|
||||||
|
public string ZXUELI { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZ_ZPQD { get; set; }
|
||||||
|
}
|
||||||
10
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPosition.cs
Normal file
10
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPosition.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
|
||||||
|
public class SapPosition
|
||||||
|
{
|
||||||
|
|
||||||
|
[JsonProperty("item")]
|
||||||
|
public List<SapPositionItem> Items { get; set; }
|
||||||
|
}
|
||||||
40
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPositionItem.cs
Normal file
40
Src/Dlhis.ScheduledTask/SyncSapInfo/Dto/SapPositionItem.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Dto
|
||||||
|
{
|
||||||
|
public class SapPositionItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 开始日期
|
||||||
|
/// </summary>
|
||||||
|
public string BEGDA { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 结束日期
|
||||||
|
/// </summary>
|
||||||
|
public string ENDDA { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 语言代码
|
||||||
|
/// </summary>
|
||||||
|
public int LANGU { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 岗位编码
|
||||||
|
/// </summary>
|
||||||
|
public string ZJOBID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 岗位名称
|
||||||
|
/// </summary>
|
||||||
|
public string ZJOBANME { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public string ZZWID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所属部门ID
|
||||||
|
/// </summary>
|
||||||
|
public string ZDEPID { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Src/Dlhis.ScheduledTask/SyncSapInfo/GetHashCodeExtensions.cs
Normal file
15
Src/Dlhis.ScheduledTask/SyncSapInfo/GetHashCodeExtensions.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo;
|
||||||
|
|
||||||
|
internal static class GetHashCodeExtensions
|
||||||
|
{
|
||||||
|
public static int SafeGetHashCode(this object o)
|
||||||
|
{
|
||||||
|
if (o == null) return 0;
|
||||||
|
return o.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SafeGetHashCode(this int o)
|
||||||
|
{
|
||||||
|
return o.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
|
using Hangfire;
|
||||||
|
using Kurisu.SqlSugar.Services;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 部门同步定时任务
|
||||||
|
/// </summary>
|
||||||
|
public class SyncOrganizationJob
|
||||||
|
{
|
||||||
|
private List<SapOrganizationItem> lastUpdatedOrgList = new();
|
||||||
|
private readonly IDbContext _dbContext;
|
||||||
|
private readonly IJinkoSapService _jinkoSapService;
|
||||||
|
|
||||||
|
public SyncOrganizationJob(IDbContext dbContext, IJinkoSapService jinkoSapService)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_jinkoSapService = jinkoSapService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SyncOrgInfo()
|
||||||
|
{
|
||||||
|
var orgResult = await _jinkoSapService.GetSapOrganizationsAsync();
|
||||||
|
|
||||||
|
if (orgResult.Org != null && orgResult.Org.Items.Count > 0)
|
||||||
|
{
|
||||||
|
var modifiedOrgList = GetModifiedOrg(orgResult.Org?.Items);
|
||||||
|
await SaveOrg(modifiedOrgList);
|
||||||
|
}
|
||||||
|
|
||||||
|
var syncPositionJob = BackgroundJob.ContinueJobWith<SyncPositionJob>("SyncOrganizationJob", job => job.SyncPositionInfo(), JobContinuationOptions.OnlyOnSucceededState);
|
||||||
|
BackgroundJob.ContinueJobWith<SyncPersonJob>(syncPositionJob, job => job.SyncPersonInfo(), JobContinuationOptions.OnlyOnSucceededState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SapOrganizationItem> GetModifiedOrg(List<SapOrganizationItem> sapList)
|
||||||
|
{
|
||||||
|
if (lastUpdatedOrgList.Count <= 0)
|
||||||
|
{
|
||||||
|
return sapList;
|
||||||
|
}
|
||||||
|
|
||||||
|
var needRemove = sapList.Intersect(lastUpdatedOrgList, new SapOrganizationComparer());
|
||||||
|
return sapList.Except(needRemove, new SapOrganizationComparer()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveOrg(List<SapOrganizationItem> modifiedOrgList)
|
||||||
|
{
|
||||||
|
if (modifiedOrgList == null || modifiedOrgList.Count == 0) return;
|
||||||
|
|
||||||
|
foreach (SapOrganizationItem item in modifiedOrgList)
|
||||||
|
{
|
||||||
|
var department = await _dbContext.Queryable<DepartmentEntity>().Where(x => x.No == item.OBJID).FirstAsync();
|
||||||
|
if (department == null)
|
||||||
|
{
|
||||||
|
department = new DepartmentEntity
|
||||||
|
{
|
||||||
|
No = item.OBJID,
|
||||||
|
Name = item.STEXT,
|
||||||
|
PNo = item.SOBID,
|
||||||
|
};
|
||||||
|
|
||||||
|
await _dbContext.InsertAsync(department);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
department.PNo = item.SOBID;
|
||||||
|
department.Name = item.STEXT;
|
||||||
|
|
||||||
|
await _dbContext.UpdateAsync(department);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
370
Src/Dlhis.ScheduledTask/SyncSapInfo/Job/SyncPersonJob.cs
Normal file
370
Src/Dlhis.ScheduledTask/SyncSapInfo/Job/SyncPersonJob.cs
Normal file
@@ -0,0 +1,370 @@
|
|||||||
|
using System.Data;
|
||||||
|
using System.Text;
|
||||||
|
using Kurisu.SqlSugar.Services;
|
||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Basic.Enums;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
||||||
|
|
||||||
|
public class SyncPersonJob
|
||||||
|
{
|
||||||
|
private readonly IDbContext _dbContext;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly IJinkoSapService _jinkoSapService;
|
||||||
|
|
||||||
|
public SyncPersonJob(IDbContext dbContext, ILogger logger, IJinkoSapService jinkoSapService)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_logger = logger;
|
||||||
|
_jinkoSapService = jinkoSapService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SyncPersonInfo()
|
||||||
|
{
|
||||||
|
var personResp = await _jinkoSapService.GetPersonsAsync();
|
||||||
|
var persons = personResp.Person.Items;
|
||||||
|
|
||||||
|
if (persons.Count > 0)
|
||||||
|
{
|
||||||
|
var modifiedPersons = await GetModifiedPersonAsync(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
|
||||||
|
if (modifiedPersons.Count > 0)
|
||||||
|
{
|
||||||
|
var failedRecords = SavePerson(modifiedPersons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<int> SavePerson(List<SapPersonItem> persons)
|
||||||
|
{
|
||||||
|
|
||||||
|
var workCodes = persons.Select(x => x.ZWORKCODE).ToList();
|
||||||
|
|
||||||
|
var index = 1;
|
||||||
|
var count = 4000;
|
||||||
|
var failure = 0;
|
||||||
|
var total = persons.Count;
|
||||||
|
|
||||||
|
var searchCodes = workCodes.Skip((index - 1) * count).Take(count).ToList();
|
||||||
|
while (searchCodes.Count > 0)
|
||||||
|
{
|
||||||
|
var existsWorkCodes = _dbContext.Queryable<GainfoEntity>()
|
||||||
|
.Where(x => searchCodes.Contains(x.Code))
|
||||||
|
.Select(x => x.Code)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var originUpdates = persons.Where(x => existsWorkCodes.Contains(x.ZWORKCODE)).ToList();
|
||||||
|
var originInserts = persons.Where(x => searchCodes.Contains(x.ZWORKCODE)).Except(originUpdates, new SapPersonComparer()).ToList();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
if (originUpdates.Count + originInserts.Count <= count)
|
||||||
|
{
|
||||||
|
var currentTotal = originUpdates.Count + originInserts.Count;
|
||||||
|
|
||||||
|
var updates = ToGainfoSap(originUpdates);
|
||||||
|
var inserts = ToGainfoSap(originInserts);
|
||||||
|
|
||||||
|
foreach (var item in inserts)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await SavePerson(item);
|
||||||
|
//conn.Execute(SqlGeneration.InsertSql, item);
|
||||||
|
//log.Debug($"执行新增{i}/{currentTotal} name:{item.gname},ename:{item.ename}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
failure++;
|
||||||
|
//log.Error($"执行新增{i}/{currentTotal} name:{item.gname},ename:{item.ename}失败 \r\n{ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in updates)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await UpdatePerson(item);
|
||||||
|
//conn.Execute(SqlGeneration.UpdateSql, item);
|
||||||
|
//log.Debug($"执行更新{i}/{currentTotal} name:{item.gname},ename:{item.ename}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
failure++;
|
||||||
|
//log.Error($"执行更新{i}/{currentTotal} name:{item.gname},ename:{item.ename}失败 \r\n{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
persons = persons.Except(originUpdates).Except(originUpdates).ToList();
|
||||||
|
searchCodes = workCodes.Skip((index - 1) * count).Take(count).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SavePerson(GainfoSapEntity item)
|
||||||
|
{
|
||||||
|
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.IdNo == item.idno).FirstAsync();
|
||||||
|
if (gainfo != null)
|
||||||
|
{
|
||||||
|
gainfo.No = item.guestno;
|
||||||
|
gainfo.SapNo = item.ano;
|
||||||
|
gainfo.Type = item.@class;
|
||||||
|
gainfo.Name = item.gname;
|
||||||
|
gainfo.Code = item.ename;
|
||||||
|
gainfo.CountryNo = item.country;
|
||||||
|
gainfo.IdClass = item.idcls;
|
||||||
|
gainfo.Native = item.native;
|
||||||
|
gainfo.Gender = item.sex == "F" ? GenderEnumType.Female : GenderEnumType.Male;
|
||||||
|
gainfo.Birthday = (DateTime)item.birthday;
|
||||||
|
gainfo.Address = item.address;
|
||||||
|
gainfo.DepartmentNo = item.appellation;
|
||||||
|
gainfo.Nation = item.nation;
|
||||||
|
gainfo.Phone = item.phone;
|
||||||
|
gainfo.Degree = item.email;
|
||||||
|
gainfo.Position = item.web;
|
||||||
|
gainfo.Remark = item.remark;
|
||||||
|
gainfo.Werks = item.WERKS;
|
||||||
|
gainfo.Employed = item.isowner; //int.Parse(person.ZSTATUS) < 4 ? "T" : "F", 是否离职
|
||||||
|
await _dbContext.UpdateAsync(gainfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var info = new GainfoEntity
|
||||||
|
{
|
||||||
|
No = item.guestno,
|
||||||
|
SapNo = item.ano,
|
||||||
|
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,
|
||||||
|
//Marital 已婚未婚
|
||||||
|
//Occuption = item.occuption,
|
||||||
|
DepartmentNo = item.appellation,
|
||||||
|
Nation = item.nation,
|
||||||
|
Phone = item.phone,
|
||||||
|
Degree = item.email,
|
||||||
|
Position = item.web,
|
||||||
|
//CarNo
|
||||||
|
Remark = item.remark,
|
||||||
|
Werks = item.WERKS,
|
||||||
|
Employed = item.isowner,
|
||||||
|
};
|
||||||
|
await _dbContext.InsertAsync(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async Task UpdatePerson(GainfoSapEntity item)
|
||||||
|
{
|
||||||
|
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.IdNo == item.idno).FirstAsync();
|
||||||
|
if (gainfo != null)
|
||||||
|
{
|
||||||
|
_dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
||||||
|
{
|
||||||
|
SapNo = item.PERNR,
|
||||||
|
Name = item.gname,
|
||||||
|
Code = item.ename,
|
||||||
|
Position = item.web,
|
||||||
|
Phone = item.phone,
|
||||||
|
DepartmentNo = item.appellation,
|
||||||
|
Employed = item.isowner,
|
||||||
|
Remark = item.remark,
|
||||||
|
Degree = item.email,
|
||||||
|
Werks = item.WERKS
|
||||||
|
})
|
||||||
|
.Where(g => g.IdNo == item.idno
|
||||||
|
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.IdNo == item.idno && g.SapNo != item.PERNR && g.Employed == "T")
|
||||||
|
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.IdNo == item.idno && int.Parse(g.SapNo) > int.Parse(item.PERNR) && g.Employed == item.isowner));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
||||||
|
{
|
||||||
|
SapNo = item.PERNR,
|
||||||
|
Name = item.gname,
|
||||||
|
Code = item.ename,
|
||||||
|
Position = item.web,
|
||||||
|
Phone = item.phone,
|
||||||
|
DepartmentNo = item.appellation,
|
||||||
|
Employed = item.isowner,
|
||||||
|
Remark = item.remark,
|
||||||
|
Degree = item.email,
|
||||||
|
Werks = item.WERKS
|
||||||
|
})
|
||||||
|
.Where(g => g.SapNo == item.PERNR
|
||||||
|
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.Code == item.ename && g.Employed == "T")
|
||||||
|
&& !_dbContext.Queryable<GainfoEntity>().Any(g => g.IdNo == item.idno && int.Parse(g.SapNo) > int.Parse(item.PERNR) && g.Employed == item.isowner));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 gainfo = await _dbContext.Queryable<GainfoSapEntity>().ToListAsync();
|
||||||
|
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<GainfoSapEntity> ToGainfoSap(List<SapPersonItem> data)
|
||||||
|
{
|
||||||
|
return data.Select(person =>
|
||||||
|
{
|
||||||
|
GainfoSapEntity o = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var position = string.Empty; //lastUpdatedPositionList.FirstOrDefault(x => x.ZJOBID == 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)
|
||||||
|
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?.ZJOBANME, 30), todo
|
||||||
|
logdate = DateTime.Now,
|
||||||
|
isowner = int.Parse(person.ZSTATUS) < 4 ? "T" : "F",
|
||||||
|
@class = "C",
|
||||||
|
country = "CN",
|
||||||
|
log_ip = "127.0.0.1",
|
||||||
|
log_shift = "1",
|
||||||
|
log_id = "XX",
|
||||||
|
address = "",
|
||||||
|
occupation = "99",
|
||||||
|
nation = "01"
|
||||||
|
};
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetNative(string idno)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(idno) || idno.Length < 6) return null;
|
||||||
|
idno = idno.TrimStart();
|
||||||
|
return idno.Substring(0, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
81
Src/Dlhis.ScheduledTask/SyncSapInfo/Job/SyncPositionJob.cs
Normal file
81
Src/Dlhis.ScheduledTask/SyncSapInfo/Job/SyncPositionJob.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
|
using Kurisu.SqlSugar.Services;
|
||||||
|
using Mapster;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 职位同步定时任务
|
||||||
|
/// </summary>
|
||||||
|
public class SyncPositionJob
|
||||||
|
{
|
||||||
|
private List<SapPositionItem> lastUpdatedPositionList = new List<SapPositionItem>();
|
||||||
|
private readonly IDbContext _dbContext;
|
||||||
|
private readonly IJinkoSapService _jinkoSapService;
|
||||||
|
|
||||||
|
public SyncPositionJob(IDbContext dbContext, IJinkoSapService jinkoSapService)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_jinkoSapService = jinkoSapService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SyncPositionInfo()
|
||||||
|
{
|
||||||
|
var positionResult = await _jinkoSapService.GetPositionsAsync();
|
||||||
|
|
||||||
|
if (positionResult.Position != null && positionResult.Position.Items.Count > 0)
|
||||||
|
{
|
||||||
|
var modifiedOrgList = GetModifiedPosition(positionResult.Position.Items);
|
||||||
|
await SaveOrg(modifiedOrgList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SapPositionItem> GetModifiedPosition(List<SapPositionItem> spaList)
|
||||||
|
{
|
||||||
|
if (lastUpdatedPositionList.Count <= 0)
|
||||||
|
{
|
||||||
|
return spaList;
|
||||||
|
}
|
||||||
|
var needRemove = spaList.Intersect(lastUpdatedPositionList, new SapPositionComparer());
|
||||||
|
return spaList.Except(needRemove, new SapPositionComparer()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveOrg(List<SapPositionItem> modifiedPostList)
|
||||||
|
{
|
||||||
|
if (modifiedPostList == null || modifiedPostList.Count == 0) return;
|
||||||
|
|
||||||
|
var addItems = new List<PositionEntity>();
|
||||||
|
var updateItems = new List<PositionEntity>();
|
||||||
|
|
||||||
|
foreach (var item in modifiedPostList)
|
||||||
|
{
|
||||||
|
var position = await _dbContext.Queryable<PositionEntity>().Where(x => x.No == item.ZJOBID).FirstAsync();
|
||||||
|
if (position == null)
|
||||||
|
{
|
||||||
|
position = new PositionEntity
|
||||||
|
{
|
||||||
|
No = item.ZJOBANME,
|
||||||
|
Name = item.ZJOBANME,
|
||||||
|
DepartmentNo = item.ZDEPID,
|
||||||
|
Grade = item.ZZWID
|
||||||
|
};
|
||||||
|
|
||||||
|
addItems.Add(position);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
position.Name = item.ZJOBANME;
|
||||||
|
position.DepartmentNo = item.ZDEPID;
|
||||||
|
position.Grade = item.ZZWID;
|
||||||
|
|
||||||
|
updateItems.Add(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await _dbContext.InsertAsync(addItems);
|
||||||
|
await _dbContext.UpdateAsync(updateItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Response;
|
||||||
|
|
||||||
|
public class SapOrganizationResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("T_ORG")]
|
||||||
|
public SapOrganization Org { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Response;
|
||||||
|
|
||||||
|
public class SapPersonResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("T_PERSON")]
|
||||||
|
public SapPerson Person { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Response;
|
||||||
|
|
||||||
|
public class SapPositionResponse
|
||||||
|
{
|
||||||
|
[JsonProperty("T_POST")]
|
||||||
|
public SapPosition Position { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Response;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
|
|
||||||
|
public interface IJinkoSapService : IScopeDependency
|
||||||
|
{
|
||||||
|
Task<SapOrganizationResponse> GetSapOrganizationsAsync();
|
||||||
|
|
||||||
|
Task<SapPositionResponse> GetPositionsAsync();
|
||||||
|
|
||||||
|
Task<SapPersonResponse> GetPersonsAsync();
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Response;
|
||||||
|
using Dlhis.User.Api;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo.Services.Implements;
|
||||||
|
|
||||||
|
public class JinkoSapService : IJinkoSapService
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly ILogger<JinkoSapService> _logger;
|
||||||
|
private readonly ITenantApi _tenantApi;
|
||||||
|
|
||||||
|
public JinkoSapService(IHttpClientFactory httpClientFactory, ILogger<JinkoSapService> logger, ITenantApi tenantApi)
|
||||||
|
{
|
||||||
|
_httpClient = httpClientFactory.CreateClient("jinko:sap");
|
||||||
|
_logger = logger;
|
||||||
|
_tenantApi = tenantApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SapOrganizationResponse> GetSapOrganizationsAsync()
|
||||||
|
{
|
||||||
|
string apiUrl = "http://sappidap.jinkosolar.cn:51000/RESTAdapter/Rest/EHR_ORGANIZATION/";
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsync(apiUrl, new StringContent("{}", Encoding.UTF8, "application/json"));
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
string responseJson = await response.Content.ReadAsStringAsync();
|
||||||
|
var result = JsonConvert.DeserializeObject<SapOrganizationResponse>(responseJson);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SapPositionResponse> GetPositionsAsync()
|
||||||
|
{
|
||||||
|
string apiUrl = "http://sappidap.jinkosolar.cn:51000/RESTAdapter/Rest/EHR_POSITION/";
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsync(apiUrl, new StringContent("{}", Encoding.UTF8, "application/json"));
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
string responseJson = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
var result = JsonConvert.DeserializeObject<SapPositionResponse>(responseJson);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SapPersonResponse> GetPersonsAsync()
|
||||||
|
{
|
||||||
|
var apiUrl = "http://sappipap01.jinkosolar.cn:50100/RESTAdapter/Rest/EHR_PERSONNEL/";
|
||||||
|
|
||||||
|
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
|
||||||
|
var tenants = tenantResult.Data;
|
||||||
|
|
||||||
|
List<SapPersonItem> persons = new();
|
||||||
|
foreach (var item in tenants)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var body = new
|
||||||
|
{
|
||||||
|
T_WERKS = new
|
||||||
|
{
|
||||||
|
item = new List<object>
|
||||||
|
{
|
||||||
|
new
|
||||||
|
{
|
||||||
|
WERKS = item.Code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
T_PERSON = Array.Empty<string>(),
|
||||||
|
T_PNO = Array.Empty<string>(),
|
||||||
|
};
|
||||||
|
var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var response = await _httpClient.PostAsync(apiUrl, content);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
|
||||||
|
var personResp = JsonConvert.DeserializeObject<SapPersonResponse>(jsonResponse);
|
||||||
|
if (personResp?.Person?.Items?.Any() == true)
|
||||||
|
{
|
||||||
|
persons.AddRange(personResp.Person.Items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "获取人事范围{werk}失败:" + ex.Message, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SapPersonResponse()
|
||||||
|
{
|
||||||
|
Person = new SapPerson
|
||||||
|
{
|
||||||
|
Items = persons
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Src/Dlhis.ScheduledTask/SyncSapInfo/SyncOptions.cs
Normal file
75
Src/Dlhis.ScheduledTask/SyncSapInfo/SyncOptions.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using Kurisu.Core.ConfigurableOptions.Attributes;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.SyncSapInfo;
|
||||||
|
|
||||||
|
[Configuration]
|
||||||
|
public class SyncOptions
|
||||||
|
{
|
||||||
|
public string ServerUrl { get; private set; }
|
||||||
|
|
||||||
|
public string UserName { get; private set; }
|
||||||
|
|
||||||
|
public string Password { get; private set; }
|
||||||
|
|
||||||
|
public string SyncTime { get; private set; }
|
||||||
|
|
||||||
|
public int AttendanceUploadInterval { get; private set; }
|
||||||
|
|
||||||
|
public string AttendanceUploadUrl { get; private set; }
|
||||||
|
|
||||||
|
public string DlhisDatabase { get; private set; }
|
||||||
|
|
||||||
|
public DateTime BeginSyncDate { get; private set; }
|
||||||
|
|
||||||
|
public string EHRWebServiceUserName { get; set; }
|
||||||
|
public string EHRWebServicePassword { get; set; }
|
||||||
|
public string EHRInsertRecordApiUrl { get; set; }
|
||||||
|
public string EHRDeleteRecordApiUrl { get; set; }
|
||||||
|
|
||||||
|
public string EHRSavePhotoApiUrl { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取员工卡片信息RESUT地址
|
||||||
|
/// </summary>
|
||||||
|
public string EHR_GET_WORK_CARD_INFOApiUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// REST账号
|
||||||
|
/// </summary>
|
||||||
|
public string RestUserName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// REST密码
|
||||||
|
/// </summary>
|
||||||
|
public string RestPassword { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
private static int SafeParseInt(string value, int defaultValue = 0)
|
||||||
|
{
|
||||||
|
if (int.TryParse(value, out int i))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool SafeParseBoolean(string value, bool defaultValue = false)
|
||||||
|
{
|
||||||
|
if (bool.TryParse(value, out var b))
|
||||||
|
{
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTime SafeParseDate(string value, DateTime defaultValue)
|
||||||
|
{
|
||||||
|
if (DateTime.TryParse(value, out var b))
|
||||||
|
{
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"EnableSqlLog": true
|
"EnableSqlLog": true
|
||||||
},
|
},
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"HangfireConnection": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=HangFire;charset=utf8mb4;Allow User Variables=true;"
|
"HangfireConnection": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=hangfire;charset=utf8mb4;Allow User Variables=true;"
|
||||||
},
|
},
|
||||||
"FaceUrlOptions": {
|
"FaceUrlOptions": {
|
||||||
"Url": "https://yikatong.isawesome.cn/api/basic/gainfos/face?token=",
|
"Url": "https://yikatong.isawesome.cn/api/basic/gainfos/face?token=",
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ public interface ITenantApi
|
|||||||
[Get("/api/tenants/list")]
|
[Get("/api/tenants/list")]
|
||||||
Task<DefaultApiResult<List<TenantResponse>>> GetTenantsAsync();
|
Task<DefaultApiResult<List<TenantResponse>>> GetTenantsAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取所有租户(内部使用)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Get("/api/tenants/list-internal")]
|
||||||
|
Task<DefaultApiResult<List<TenantResponse>>> GetTenantsInternalAsync();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据code获取租户信息
|
/// 根据code获取租户信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -40,6 +40,17 @@ public class TenantsController : ControllerBase
|
|||||||
return await _tenantService.GetListAsync();
|
return await _tenantService.GetListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内部使用接口
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpGet("list-internal")]
|
||||||
|
public async Task<List<TenantResponse>> GetListInternalAsync()
|
||||||
|
{
|
||||||
|
return await _tenantService.GetListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取租户
|
/// 获取租户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user