refactor 优化代码

This commit is contained in:
2024-11-26 15:26:12 +08:00
parent a32910f0d9
commit 623a5c4e49
88 changed files with 1820 additions and 941 deletions

View File

@@ -29,8 +29,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "External", "External", "{48
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dlhis.External", "Src\Dlhis.External\Dlhis.External.csproj", "{8472596E-0DE7-4A17-93D6-F0FC7D44FDF5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dlhis.Scheduled.Api", "Src\Dlhis.Scheduled.Api\Dlhis.Scheduled.Api.csproj", "{9EA85FB2-F320-4F97-B278-00652CF35BD8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dlhis.Canteen", "Src\Dlhis.Canteen\Dlhis.Canteen.csproj", "{A54426E2-1CA0-48AB-BBA6-07CDE2807E35}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Message", "Message", "{65E76F97-E78A-4C95-B788-4091236B1A79}"
@@ -45,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dlhis.DataPermission.Model"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.InfoCheck.Api", "Src\Dlhis.InfoCheck.Api\Dlhis.InfoCheck.Api.csproj", "{A501D16E-638F-4156-989C-2BACCC2FAC2B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dlhis.Jip.Api", "Src\Dlhis.Jip.Api\Dlhis.Jip.Api.csproj", "{841B7B43-5394-413F-9D68-A07EBDD6D4CD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -83,10 +83,6 @@ Global
{8472596E-0DE7-4A17-93D6-F0FC7D44FDF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8472596E-0DE7-4A17-93D6-F0FC7D44FDF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8472596E-0DE7-4A17-93D6-F0FC7D44FDF5}.Release|Any CPU.Build.0 = Release|Any CPU
{9EA85FB2-F320-4F97-B278-00652CF35BD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9EA85FB2-F320-4F97-B278-00652CF35BD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EA85FB2-F320-4F97-B278-00652CF35BD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EA85FB2-F320-4F97-B278-00652CF35BD8}.Release|Any CPU.Build.0 = Release|Any CPU
{A54426E2-1CA0-48AB-BBA6-07CDE2807E35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A54426E2-1CA0-48AB-BBA6-07CDE2807E35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A54426E2-1CA0-48AB-BBA6-07CDE2807E35}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -111,6 +107,10 @@ Global
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A501D16E-638F-4156-989C-2BACCC2FAC2B}.Release|Any CPU.Build.0 = Release|Any CPU
{841B7B43-5394-413F-9D68-A07EBDD6D4CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{841B7B43-5394-413F-9D68-A07EBDD6D4CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{841B7B43-5394-413F-9D68-A07EBDD6D4CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{841B7B43-5394-413F-9D68-A07EBDD6D4CD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -122,11 +122,11 @@ Global
{85A345C7-913E-4C1B-BE1C-600DE408A02F} = {57074FD8-1A2F-40C7-8476-001778A3F65D}
{1F337648-8A22-4601-A842-0F634FBA2825} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
{8472596E-0DE7-4A17-93D6-F0FC7D44FDF5} = {489252FB-A44B-46EE-B065-21CDCB724441}
{9EA85FB2-F320-4F97-B278-00652CF35BD8} = {AA987BDF-EF63-467B-AD04-59F9B10D9000}
{A54426E2-1CA0-48AB-BBA6-07CDE2807E35} = {3D8A98C1-83C9-4375-AEAB-4F72AFAF365B}
{053BF7B2-B1A0-435F-9C77-2EF5622CC5C5} = {65E76F97-E78A-4C95-B788-4091236B1A79}
{4D656761-8CE7-4316-A3DF-8C1722D69CCE} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
{A501D16E-638F-4156-989C-2BACCC2FAC2B} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
{841B7B43-5394-413F-9D68-A07EBDD6D4CD} = {4EBCE46B-CE3A-4A47-9432-82A1854CA58A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7439494A-E2FD-4FEA-8ABF-74AE57A4A5A0}

View File

@@ -0,0 +1,22 @@
using System.Text;
using Kurisu.RemoteCall;
using Kurisu.RemoteCall.Abstractions;
using Newtonsoft.Json;
namespace Dlhis.Basic.Api.ContentHandlers;
public class CodeContentHandler : IContentHandler
{
/// <inheritdoc />
public HttpContent Create(List<ParameterValue> values)
{
var code = values.First(x => x.Parameter.Name == "code").GetValue<string>();
var obj = new
{
code,
};
var json = JsonConvert.SerializeObject(obj);
return new StringContent(json, Encoding.UTF8, "application/json");
}
}

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.2" />
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.5" />
</ItemGroup>
</Project>

View File

@@ -1,13 +1,13 @@
using Dlhis.Basic.Api.Dto;
using Kurisu.RemoteCall.Attributes;
using Kurisu.RemoteCall.Default;
namespace Dlhis.Basic.Api;
[RequestResultHandler]
[EnableRemoteClient(Name = "basic-service", BaseUrl = "${InternalRequest:BasicRequestUrl}")]
public interface IBusinessPlacePermissionsApi
{
[Auth]
[Get("/api/businessplacepermissions/my")]
Task<DefaultApiResult<List<BusinessPlaceDto>>> GetMyAsync();
Task<List<BusinessPlaceDto>> GetMyAsync();
}

View File

@@ -1,16 +1,12 @@
using Dlhis.Basic.Api.Request;
using Kurisu.RemoteCall.Attributes;
using Kurisu.RemoteCall.Default;
using Kurisu.RemoteCall.Attributes;
namespace Dlhis.Basic.Api;
[RequestResultHandler]
[EnableRemoteClient(Name = "basic-service", BaseUrl = "${InternalRequest:BasicRequestUrl}")]
public interface IGainfoPermissionApi
{
[Post("/api/gainfoPermissions/reset")]
Task<DefaultApiResult> ResetAsync(GainfoPermissionResetRequest request);
[Auth]
[Get("/api/devicePermissions/userPermissionCodes")]
Task<DefaultApiResult<List<Guid>>> GetPermissionsDeviceCodesAsync(string userCode);
Task<List<Guid>> GetPermissionsDeviceCodesAsync(string userCode);
}

View File

@@ -0,0 +1,30 @@
using Dlhis.Basic.Api.ContentHandlers;
using Dlhis.Basic.Api.Response;
using Kurisu.RemoteCall.Attributes;
namespace Dlhis.Basic.Api;
[RequestResultHandler]
[EnableRemoteClient(Name = "basic-service", BaseUrl = "${InternalRequest:BasicRequestUrl}")]
public interface ISyncApi
{
[Post("/api/sync/gainfo/werk")]
[RequestContentHandler(typeof(CodeContentHandler))]
Task SyncGainfoByWerkAsync(string code);
[Post("/api/sync/gainfo/user")]
[RequestContentHandler(typeof(CodeContentHandler))]
Task SyncGainfoByUserCodeAsync(string code);
[Get("/api/sync/orgs")]
Task<SapOrganizationResponse> SyncOrganizationsAsync();
[Get("/api/sync/positions")]
Task<SapPositionResponse> GetPositionsAsync();
[Post("/api/sync/businessTrips")]
[RequestContentHandler(typeof(CodeContentHandler))]
Task HandlerBusinessTripsAsync(string code);
}

View File

@@ -0,0 +1,15 @@
using Newtonsoft.Json;
namespace Dlhis.Basic.Api.Response;
/// <summary>
/// sap机构信息
/// </summary>
public class SapOrganization
{
/// <summary>
/// 机构项
/// </summary>
[JsonProperty("item")]
public List<SapOrganizationItem> Items { get; set; }
}

View File

@@ -0,0 +1,66 @@
namespace Dlhis.Basic.Api.Response;
public class SapOrganizationItem
{
/// <summary>
/// 开始日期
/// </summary>
public string BEGDA { get; set; }
/// <summary>
/// 结束日期
/// </summary>
public string ENDDA { get; set; }
/// <summary>
/// 语言
/// </summary>
public string 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();
//}

View File

@@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Dlhis.Basic.Api.Response;
public class SapOrganizationResponse
{
[JsonProperty("T_ORG")]
public SapOrganization Org { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace Dlhis.ScheduledTask.Common.Dto;
namespace Dlhis.Jip.Api.Dto;
public class SapPersonItem
{

View File

@@ -1,6 +1,6 @@
using Newtonsoft.Json;
namespace Dlhis.ScheduledTask.Common.Dto;
namespace Dlhis.Basic.Api.Response;
public class SapPosition
{

View File

@@ -1,4 +1,4 @@
namespace Dlhis.ScheduledTask.Common.Dto
namespace Dlhis.Basic.Api.Response
{
public class SapPositionItem
{

View File

@@ -1,7 +1,7 @@
using Dlhis.ScheduledTask.Common.Dto;
using Dlhis.Jip.Api.Dto;
using Newtonsoft.Json;
namespace Dlhis.ScheduledTask.Common.Response;
namespace Dlhis.Basic.Api.Response;
public class SapPositionResponse
{

View File

@@ -140,8 +140,7 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
};
}
var tenantResult = await _tenantApi.GetTenantByCodeAsync(place.TenantId);
var tenantInfo = tenantResult.EnsureSuccessStatusCode();
var tenant = await _tenantApi.GetTenantByCodeAsync(place.TenantId);
var relationship = await _dbContext.Queryable<BusinessPlaceShiftRelationshipEntity>().Where(x => x.PlaceCode == place.Code).FirstAsync();
if (relationship == null)
@@ -150,8 +149,8 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
{
CustomCode = placeCustomCode,
Name = place.Name,
TenantCode = tenantInfo.Code,
TenantName = tenantInfo.Name,
TenantCode = tenant.Code,
TenantName = tenant.Name,
Shifts = new List<BusinessPlaceShiftTinyResponse>()
};
}
@@ -181,8 +180,8 @@ public class BusinessPlaceShiftService : IBusinessPlaceShiftService
{
CustomCode = placeCustomCode,
Name = place.Name,
TenantCode = tenantInfo.Code,
TenantName = tenantInfo.Name,
TenantCode = tenant.Code,
TenantName = tenant.Name,
Shifts = list.OrderBy(x => x.Sequence).ToList()
};
}

View File

@@ -33,9 +33,9 @@ public class DeviceGroupService : IDeviceGroupService
public async Task<List<DeviceGroupTreeResponse>> GetTreeAsync(DeviceTypeEnumType type)
{
var tenantResult = await _tenantApi.GetMyTenantsAsync();
var tenantIds = tenantResult.Data.Select(x => x.Code).ToList();
tenantIds.AddRange(tenantResult.Data.Select(x => x.PCode));
var tenants = await _tenantApi.GetMyTenantsAsync();
var tenantIds = tenants.Select(x => x.Code).ToList();
tenantIds.AddRange(tenants.Select(x => x.PCode));
var deviceGroups = await _dbContext.Queryable<DeviceGroupEntity>()
.Where(x => tenantIds.Contains(x.TenantId))

View File

@@ -379,8 +379,7 @@ public class DevicePermissionService : IDevicePermissionService
.Where(x => x.num == 1)
.ToListAsync();
var tenantsResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantsResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
page.Data.ForEach(x =>
{

View File

@@ -246,8 +246,8 @@ public class DeviceService : IDeviceService
var factory = device.TenantId;
try
{
var tenantResult = await _tenantApi.GetTenantByCodeAsync(device.TenantId);
factory = tenantResult?.Data?.Name ?? string.Empty;
var tenant = await _tenantApi.GetTenantByCodeAsync(device.TenantId);
factory = tenant?.Name ?? string.Empty;
}
catch (Exception)
{

View File

@@ -27,7 +27,7 @@
<ItemGroup>
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
<ProjectReference Include="..\Dlhis.InfoCheck.Api\Dlhis.InfoCheck.Api.csproj" />
<ProjectReference Include="..\Dlhis.Scheduled.Api\Dlhis.Scheduled.Api.csproj" />
<ProjectReference Include="..\Dlhis.Jip.Api\Dlhis.Jip.Api.csproj" />
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
</ItemGroup>

View File

@@ -2,7 +2,7 @@
using System.Text;
using Kurisu.AspNetCore.Startup;
namespace Dlhis.ScheduledTask.Packs;
namespace Dlhis.Basic;
public class JinkoSapHttpClientPack : BaseAppPack
{

View File

@@ -1,7 +1,7 @@
using Dlhis.ScheduledTask.Common.Dto;
using System.Text;
using Dlhis.Basic.Organization.Services.Implements;
using Dlhis.Jip.Api.Dto;
namespace Dlhis.ScheduledTask.Common.Comparers;
namespace Dlhis.Basic.Organization.Comparers;
/// <summary>
/// 人员信息比较器

View File

@@ -66,17 +66,4 @@ public class GainfoPermissionsController : ControllerBase
{
return await _gainfoPermissions.GetAssignGroupAsync(userNo);
}
/// <summary>
/// 权限下发重置
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("reset")]
[IgnoreTenant]
public async Task ResetPermissionsAsync(GainfoPermissionResetRequest request)
{
await _gainfoPermissions.ResetPermissionsAsync(request);
}
}

View File

@@ -0,0 +1,55 @@
using Dlhis.Basic.Organization.Request;
using Dlhis.Basic.Organization.Services;
using Dlhis.Jip.Api.Responses;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.Organization.Controllers;
[AllowAnonymous]
[ApiController]
[Route("/api/[controller]")]
public class SyncController : ControllerBase
{
private readonly IGainfoUpdateService _gainfoUpdateService;
private readonly IJinkoSapService _jinkoSapService;
private readonly ISapBusinessTripService _sapBusinessTripService;
public SyncController(IGainfoUpdateService gainfoUpdateService, IJinkoSapService jinkoSapService, ISapBusinessTripService sapBusinessTripService)
{
_gainfoUpdateService = gainfoUpdateService;
_jinkoSapService = jinkoSapService;
_sapBusinessTripService = sapBusinessTripService;
}
[HttpPost("/api/sync/gainfo/werk")]
public async Task TodoByWerkAsync(CodeRequest request)
{
await _gainfoUpdateService.TodoByWerkAsync(request.Code);
}
[HttpPost("/api/sync/gainfo/user")]
public async Task TodoByCodeAsync(CodeRequest request)
{
await _gainfoUpdateService.TodoByCodeAsync(request.Code);
}
[HttpGet("/api/sync/orgs")]
public async Task<SapOrganizationResponse> GetOrgsSync()
{
return await _jinkoSapService.GetSapOrganizationsAsync();
}
[HttpGet("/api/sync/positions")]
public async Task<SapPositionResponse> GetPositionsAsync()
{
return await _jinkoSapService.GetPositionsAsync();
}
[HttpPost("/api/sync/businessTrips")]
public async Task GetPositionsAsync(CodeRequest request)
{
await _sapBusinessTripService.HandlerBusinessTripsByFactoryAsync(request.Code);
}
}

View File

@@ -0,0 +1,6 @@
namespace Dlhis.Basic.Organization.Request;
public class CodeRequest
{
public string Code { get; set; }
}

View File

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

View File

@@ -1,4 +1,4 @@
namespace Dlhis.ScheduledTask.Common.Services;
namespace Dlhis.Basic.Organization.Services;
public interface IIdentityUserSyncService : IScopeDependency
{

View File

@@ -1,6 +1,6 @@
using Dlhis.ScheduledTask.Common.Response;
using Dlhis.Jip.Api.Responses;
namespace Dlhis.ScheduledTask.Common.Services;
namespace Dlhis.Basic.Organization.Services;
public interface IJinkoSapService : IScopeDependency
{

View File

@@ -79,8 +79,7 @@ public class FactorySettingService : IFactorySettingService
}
else
{
var apiResult = await _tenantApi.GetMyTenantsAsync();
factories = apiResult.Data;
factories = await _tenantApi.GetMyTenantsAsync();
}
var factoryCodes = factories.Select(x => x.Code).ToList();

View File

@@ -8,8 +8,7 @@ using Dlhis.Entity.Basic.Enums;
using Dlhis.Entity.Device.Enums;
using Dlhis.InfoCheck.Api;
using Dlhis.InfoCheck.Api.Requests;
using Dlhis.Scheduled.Api;
using Dlhis.Scheduled.Api.Request;
using Dlhis.Jip.Api;
using Kurisu.AspNetCore.Authentication.Abstractions;
using Kurisu.AspNetCore.CustomClass;
using Kurisu.AspNetCore.DataAccess.Extensions;
@@ -28,11 +27,11 @@ public class GainfoFaceService : IGainfoFaceService
private readonly ILogger<GainfoFaceService> _logger;
private readonly IConfiguration _configuration;
private readonly ICurrentUser _currentUser;
private readonly IHangfireApi _hangfireApi;
private readonly IDevicePermissionService _devicePermissionService;
private readonly IFactorySettingService _factorySettingService;
private readonly IHainingApi _hainingApi;
private readonly IInfoCheckApi _infoCheckApi;
private readonly IJinkoJipApi _jinkoJipApi;
private readonly IDataProtectionProvider _dataProtectionProvider;
public GainfoFaceService(IGainfoStore gainfoStore,
@@ -40,11 +39,11 @@ public class GainfoFaceService : IGainfoFaceService
ILogger<GainfoFaceService> logger,
IConfiguration configuration,
ICurrentUser currentUser,
IHangfireApi hangfireApi,
IDevicePermissionService devicePermissionService,
IFactorySettingService factorySettingService,
IHainingApi hainingApi,
IInfoCheckApi infoCheckApi,
IJinkoJipApi jinkoJipApi,
IDataProtectionProvider dataProtectionProvider)
{
_gainfoStore = gainfoStore;
@@ -53,11 +52,11 @@ public class GainfoFaceService : IGainfoFaceService
_logger = logger;
_configuration = configuration;
_currentUser = currentUser;
_hangfireApi = hangfireApi;
_devicePermissionService = devicePermissionService;
_factorySettingService = factorySettingService;
_hainingApi = hainingApi;
_infoCheckApi = infoCheckApi;
_jinkoJipApi = jinkoJipApi;
_dataProtectionProvider = dataProtectionProvider;
}
@@ -109,7 +108,7 @@ public class GainfoFaceService : IGainfoFaceService
var gainfo = await _gainfoStore.Queryable(GainfoStatusEnumType.External)
.Where(x => x.IdNo == request.UserNo)
.SingleAsync();
gainfo ??= await _gainfoStore.Queryable(GainfoStatusEnumType.Working)
.Where(x => x.IdNo == request.UserNo)
.SingleAsync();
@@ -231,11 +230,14 @@ public class GainfoFaceService : IGainfoFaceService
try
{
await _hangfireApi.SyncFaceToSapAsync(new FaceUploadToSapRequest
var r = await _jinkoJipApi.SyncFaceToSapAsync(face.UserCode, face.Face);
if (r.OLX == "S")
{
UserCode = face.UserCode,
Base64 = face.Face
});
await _faceDbContext.Updateable<GainfoFaceEntity>()
.SetColumns(x => x.IsSync == true)
.Where(x => x.UserCode == face.UserCode)
.ExecuteCommandAsync();
}
}
catch (Exception e)
{
@@ -372,7 +374,7 @@ public class GainfoFaceService : IGainfoFaceService
Level = (int)x.Level
}).ToList()
});
r = result.Data;
r = result;
}
catch (Exception ex)
{

View File

@@ -6,8 +6,6 @@ using Dlhis.Entity.Basic.Enums;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Visitor.Entity;
using Dlhis.Scheduled.Api;
using Dlhis.Scheduled.Api.Request;
using Dlhis.Sys.Api;
using Kurisu.AspNetCore.Authentication.Abstractions;
using Kurisu.AspNetCore.DataAccess.Dto;
@@ -26,7 +24,7 @@ public class GainfoService : IGainfoService
private readonly IDataProtectionProvider _dataProtectionProvider;
private readonly ICurrentUser _currentUser;
private readonly ITenantApi _tenantApi;
private readonly IHangfireApi _hangfireApi;
private readonly IJinkoSapService _jinkoSapService;
private readonly IDevicePermissionService _devicePermissionService;
private readonly IGainfoPermissionService _gainfoPermissionService;
private readonly ILogger<GainfoService> _logger;
@@ -36,7 +34,7 @@ public class GainfoService : IGainfoService
IDataProtectionProvider dataProtectionProvider,
ICurrentUser currentUser,
ITenantApi tenantApi,
IHangfireApi hangfireApi,
IJinkoSapService jinkoSapService,
IDevicePermissionService devicePermissionService,
IGainfoPermissionService gainfoPermissionService,
ILogger<GainfoService> logger)
@@ -46,7 +44,7 @@ public class GainfoService : IGainfoService
_dataProtectionProvider = dataProtectionProvider;
_currentUser = currentUser;
_tenantApi = tenantApi;
_hangfireApi = hangfireApi;
_jinkoSapService = jinkoSapService;
_devicePermissionService = devicePermissionService;
_gainfoPermissionService = gainfoPermissionService;
_logger = logger;
@@ -166,8 +164,7 @@ public class GainfoService : IGainfoService
.Select<GainfoAllPageResponse>()
.ToPageListAsync(new PageDto { PageIndex = 1, PageSize = 1 });
var tenantsResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantsResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
page.Data.ForEach(x =>
{
@@ -191,8 +188,9 @@ public class GainfoService : IGainfoService
if (gainfo == null)
{
//开启同步处理
await _hangfireApi.SyncSapPersonAsync(new SapNoRequest { Code = code });
return null;
await _jinkoSapService.GetPersonsByCodeAsync(code);
gainfo = await _gainfoStore.Queryable().Where(x => x.Code == code).SingleAsync();
if (gainfo == null) return null;
}
var info = await _gainfoStore.Queryable(GainfoStatusEnumType.Working)
@@ -217,11 +215,8 @@ public class GainfoService : IGainfoService
{
try
{
var tenantResult = await _tenantApi.GetTenantByCodeAsync(info.Factory);
if (tenantResult is { Data: not null })
{
info.FactoryName = tenantResult.Data.Name;
}
var tenant = await _tenantApi.GetTenantByCodeAsync(info.Factory);
info.FactoryName = tenant?.Name;
}
catch (Exception)
{
@@ -408,8 +403,7 @@ public class GainfoService : IGainfoService
try
{
var tenantsResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantsResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
info.Workplace = tenants.FirstOrDefault(x => x.Code == info.Workplace)?.Name;
info.Factory = tenants.FirstOrDefault(x => x.Code == info.Factory)?.Name;

View File

@@ -0,0 +1,506 @@
using Dlhis.Basic.Device.Services;
using Dlhis.Basic.Organization.Comparers;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums;
using Dlhis.Jip.Api.Dto;
using Dlhis.Sys.Api;
using Dlhis.Sys.Api.Response;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.Basic.Organization.Services.Implements;
public class GainfoUpdateService : IGainfoUpdateService
{
private readonly IDbContext _dbContext;
private readonly ILogger<GainfoUpdateService> _logger;
private readonly ITenantApi _tenantApi;
private readonly IJinkoSapService _jinkoSapService;
private readonly IDevicePermissionService _devicePermissionService;
private readonly IIdentityUserSyncService _identityUserSyncService;
private List<TenantResponse> _tenants;
public GainfoUpdateService(IDbContext dbContext,
ILogger<GainfoUpdateService> logger,
ITenantApi tenantApi,
IJinkoSapService jinkoSapService,
IDevicePermissionService devicePermissionService,
IIdentityUserSyncService identityUserSyncService)
{
_dbContext = dbContext;
_dbContext.Client.QueryFilter.Clear();
_logger = logger;
_tenantApi = tenantApi;
_jinkoSapService = jinkoSapService;
_devicePermissionService = devicePermissionService;
_identityUserSyncService = identityUserSyncService;
}
public async Task TodoByWerkAsync(string werk)
{
var werkInfo = await _dbContext.Queryable<WerkEntity>().Where(x => x.Werk == werk).SingleAsync();
werkInfo.LastSyncStartTime = DateTime.Now;
werkInfo.HandleMessage = "任务执行中";
await _dbContext.UpdateAsync(werkInfo);
try
{
var personResp = await _jinkoSapService.GetPersonsByWerkAsync(werk);
var persons = personResp.Person.Items;
werkInfo.HandleMessage = "SAP人员数量" + persons.Count;
werkInfo.Total = persons.Count;
await _dbContext.UpdateAsync(werkInfo);
if (persons.Count > 0)
{
var modifiedPersons = await GetModifiedPersonAsync(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
werkInfo.HandleMessage = "SAP人员差异数量" + modifiedPersons.Count;
werkInfo.DiffNumber = modifiedPersons.Count;
await _dbContext.UpdateAsync(werkInfo);
if (modifiedPersons.Count > 0)
{
await SavePersonAsync(modifiedPersons);
}
}
werkInfo.HandleMessage = "同步结束";
werkInfo.LastSyncEndTime = DateTime.Now;
werkInfo.BackgroundJobKey = string.Empty;
await _dbContext.UpdateAsync(werkInfo);
}
catch (Exception ex)
{
_logger.LogError(ex, "{werk}同步处理异常:{message}", werk, ex.Message);
werkInfo.HandleMessage = ex.Message;
werkInfo.LastSyncEndTime = DateTime.Now;
werkInfo.BackgroundJobKey = string.Empty;
await _dbContext.UpdateAsync(werkInfo);
}
}
public async Task TodoByCodeAsync(string code)
{
_logger.LogInformation("SAP根据学工号同步开始:{code}", code);
var personResp = await _jinkoSapService.GetPersonsByCodeAsync(code);
var persons = personResp.Person.Items;
_logger.LogInformation("获取SAP人员数量为:{count}", persons.Count);
if (persons.Count > 0)
{
var modifiedPersons = await GetModifiedPersonAsync(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
_logger.LogInformation("SAP人员差异数量为:{count}", modifiedPersons.Count);
if (modifiedPersons.Count > 0)
{
await SavePersonAsync(modifiedPersons);
}
}
_logger.LogInformation("SAP根据学工号同步结束:{code}", code);
}
private async Task SavePersonAsync(List<SapPersonItem> persons)
{
_tenants = await _tenantApi.GetTenantsInternalAsync();
var workCodes = persons.Select(x => x.ZWORKCODE).ToList();
var chunks = workCodes.Chunk(4000).ToList();
foreach (var searchCodes in chunks)
{
_logger.LogWarning("SAP分批处理Chunk数量:{count}", searchCodes.Length);
var existsWorkCodes = await _dbContext.Queryable<GainfoSapEntity>()
.Where(x => searchCodes.Contains(x.ename))
.Select(x => x.ename)
.ToListAsync();
var originUpdates = persons.Where(x => existsWorkCodes.Contains(x.ZWORKCODE)).ToList();
var existsUpdateWorkCodes = originUpdates.Select(x => x.ZWORKCODE).ToList();
var originInserts = persons.Where(x => searchCodes.Contains(x.ZWORKCODE)).Where(x => !existsUpdateWorkCodes.Contains(x.ZWORKCODE)).ToList();
var updates = ToGainfoSap(originUpdates);
var inserts = ToGainfoSap(originInserts);
foreach (var item in inserts)
{
try
{
await InsertPersonAsync(item);
}
catch (Exception ex)
{
_logger.LogError(ex, "执行新增失败:{message}", ex.Message);
}
}
foreach (var item in updates)
{
try
{
var no = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).Select(x => x.No).SingleAsync();
if (no.IsEmpty())
{
await InsertPersonAsync(item);
}
else
{
await UpdatePersonAsync(item);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "执行更新失败:{message}", ex.Message);
}
}
}
}
private async Task InsertPersonAsync(GainfoSapEntity item)
{
await _dbContext.InsertAsync(item);
var info = GainfoSapToGainfo(item);
if (item.isowner == "T")
{
await _devicePermissionService.GenerateDeviceTasksAsync(async () =>
{
await _dbContext.InsertAsync(info);
await _identityUserSyncService.SyncAccountAsync(info.Code, info.Name, info.IdNo, info.Factory);
}, new List<string> { info.No });
}
else
{
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommandAsync();
}
}
}
private GainfoEntity GainfoSapToGainfo(GainfoSapEntity item)
{
var info = new GainfoEntity
{
No = Guid.NewGuid().ToString(),
InternalNo = item.PERNR,
Type = GainfoUserTypeEnumType.Normal,
Name = item.gname,
Code = item.ename,
CountryNo = item.country,
IdClass = item.idcls,
IdNo = item.idno,
Native = item.native,
Gender = item.sex == "F" ? GenderEnumType.Female : GenderEnumType.Male,
Birthday = item.birthday,
Address = item.address,
DepartmentNo = item.appellation,
Nation = item.nation,
Phone = item.phone,
Degree = item.email,
Grade = item.ZZ_ZD,
Title = item.Z_ZJ,
PositionNo = item.STELL,
Remark = item.remark,
Werks = item.WERKS,
CostId = item.KOSTL,
EntryDate = item.createdate,
ResignationDate = item.ZLZRQ,
CardType = SafeParseCardType(item.ZZ_KLX),
Workplace = _tenants.LastOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM,
Factory = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM,
};
return info;
}
private async Task UpdatePersonAsync(GainfoSapEntity item)
{
var info = GainfoSapToGainfo(item);
await _dbContext.Updateable<GainfoSapEntity>().SetColumns(g => new GainfoSapEntity
{
PERNR = item.PERNR,
gname = item.gname,
phone = item.phone,
appellation = item.appellation,
isowner = item.isowner,
remark = item.remark,
email = item.email,
WERKS = item.WERKS,
KOSTL = item.KOSTL,
STELL = item.STELL,
Z_ZJ = item.Z_ZJ,
ZZ_ZD = item.ZZ_ZD,
MNTXT = item.MNTXT,
MASSN = item.MASSN,
ZSTATUS = item.ZSTATUS,
ZLZRQ = item.ZLZRQ,
STELL_NM = item.STELL_NM,
ZZ_KLX = item.ZZ_KLX,
createdate = item.createdate,
ZZ_GZDJDNM = item.ZZ_GZDJDNM,
ZZ_GZDCQNM = item.ZZ_GZDCQNM,
}).Where(x => x.ename == item.ename).ExecuteCommandAsync();
//获取当前在职人员
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).SingleAsync();
var workplace = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM;
var factory = _tenants.LastOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM;
if (gainfo != null)
{
if (item.isowner == "T")
{
await _devicePermissionService.GenerateDeviceTasksAsync(async () =>
{
await _dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
{
InternalNo = item.PERNR,
Name = item.gname,
PositionNo = item.STELL,
Grade = item.ZZ_ZD,
Title = item.Z_ZJ,
Phone = item.phone,
DepartmentNo = item.appellation,
Remark = item.remark,
Degree = item.email,
Werks = item.WERKS,
CostId = item.KOSTL,
EntryDate = item.createdate,
ResignationDate = item.ZLZRQ,
Workplace = workplace,
Factory = factory,
CardType = SafeParseCardType(item.ZZ_KLX)
}).Where(x => x.Code == item.ename).ExecuteCommandAsync();
await _identityUserSyncService.SyncAccountAsync(gainfo.Code, gainfo.Name, gainfo.IdNo, factory);
}, new List<string> { gainfo.No });
}
else
{
await _devicePermissionService.GenerateDeviceTasksAsync(async () =>
{
await _dbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
{
InternalNo = item.PERNR,
Name = item.gname,
PositionNo = item.STELL,
Grade = item.ZZ_ZD,
Title = item.Z_ZJ,
Phone = item.phone,
DepartmentNo = item.appellation,
Remark = item.remark,
Degree = item.email,
Werks = item.WERKS,
CostId = item.KOSTL,
EntryDate = item.createdate,
ResignationDate = item.ZLZRQ,
Workplace = workplace,
Factory = factory,
CardType = SafeParseCardType(item.ZZ_KLX)
}).Where(x => x.Code == item.ename).ExecuteCommandAsync();
await _identityUserSyncService.SyncAccountAsync(gainfo.Code, gainfo.Name, gainfo.IdNo, factory);
}, new List<string> { gainfo.No });
try
{
//先写入离职表
gainfo.IdentityUserId = (int)gainfo.Id; //记录原始id
gainfo.Id = 0;
gainfo.ResignationDate = item.ZLZRQ;
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommandAsync();
}
gainfo.Id = gainfo.IdentityUserId;
await _dbContext.DeleteReallyAsync(gainfo);
}
catch (Exception ex)
{
_logger.LogError(ex, "离职任务生成失败:{message}", ex.Message);
}
}
}
else
{
if (item.isowner == "T")
{
await _dbContext.InsertAsync(info);
await _identityUserSyncService.SyncAccountAsync(info.Code, info.Name, info.IdNo, factory);
}
else
{
if (!await _dbContext.Queryable<GainfoLeaveEntity>().AnyAsync(x => x.Code == item.ename))
{
await _dbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommandAsync();
}
else
{
await _dbContext.Updateable<GainfoLeaveEntity>().SetColumns(g => new GainfoLeaveEntity
{
InternalNo = item.PERNR,
Name = item.gname,
PositionNo = item.STELL,
Grade = item.ZZ_ZD,
Title = item.Z_ZJ,
Phone = item.phone,
DepartmentNo = item.appellation,
Remark = item.remark,
Degree = item.email,
Werks = item.WERKS,
CostId = item.KOSTL,
EntryDate = item.createdate,
ResignationDate = item.ZLZRQ,
Workplace = workplace,
Factory = factory,
CardType = SafeParseCardType(item.ZZ_KLX)
}).Where(x => x.Code == item.ename).ExecuteCommandAsync();
}
}
}
}
private async Task<List<SapPersonItem>> GetModifiedPersonAsync(List<SapPersonItem> sapList)
{
var last = await LoadDataAsync();
if (last.Count <= 0)
{
return sapList;
}
var needRemove = sapList.Intersect(last, new SapPersonComparer()).ToList();
return sapList.Except(needRemove, new SapPersonComparer()).ToList();
}
private async Task<List<SapPersonItem>> LoadDataAsync()
{
//var pJson = "{\"id\":0,\"ano\":null,\"class\":\"C\",\"passwd\":null,\"question\":null,\"answer\":null,\"gname\":\"岳文超\",\"ename\":\"098250\",\"country\":null,\"idcls\":\"ID\",\"idno\":\"\\\"140105200112051318\n\",\"native\":\"14010\",\"sex\":\"M\",\"birthday\":\"2001-12-05T00:00:00\",\"address\":\"\",\"postcode\":null,\"occupation\":\"99\",\"appellation\":\"00210591\",\"nation\":\"01\",\"phone\":\"13773151205\",\"fax\":null,\"mobile\":null,\"email\":\"高中/中专【失效】\",\"web\":\"\",\"vip\":null,\"sec\":null,\"cropsno\":null,\"cropname\":null,\"fancy\":null,\"remark\":\"入职时间:2023-05-05 离职时间:2023-10-30 变更原因:自离【失效】\",\"amount\":0,\"days\":0,\"consume01\":0.0000,\"consume02\":0.0000,\"consume03\":0.0000,\"consume04\":0.0000,\"log_id\":\"XX\",\"log_shift\":\"1\",\"log_date\":null,\"log_ip\":\"127.0.0.1\",\"times\":0,\"logmark\":0,\"rmcode\":null,\"mkt\":null,\"src\":null,\"isowner\":\"F\",\"createdate\":\"2023-05-05T00:00:00\",\"PERNR\":\"00281800\",\"WERKS\":\"1560\",\"ZSTATUS\":\"5\",\"KOSTL\":\"156020336\",\"ZZ_ZD\":\"3\",\"Z_ZJ\":\"T0\",\"STELL\":null,\"STELL_NM\":null,\"ZLZRQ\":\"2023-10-30T00:00:00\",\"MASSN\":\"ZD\",\"MNTXT\":\"离职\",\"MASSG\":null,\"MGTXT\":null,\"logdate\":\"2024-03-14T00:02:34\",\"updatelogdate\":null,\"guestno\":null,\"ZZ_KLX\":\"3\",\"DAT01\":null,\"ZZ_COUNNM\":null,\"ZZ_GZDJDNM\":\"海宁基地\",\"ZZ_GZDCQNM\":\"海宁尖山\"}";
//var gainfos = new List<GainfoSapEntity>() { pJson.ToObject<GainfoSapEntity>() };
var gainfos = await _dbContext.Queryable<GainfoSapEntity>().ToListAsync();
return gainfos.Select(x => new SapPersonItem
{
NAME = x.gname,
ZWORKCODE = x.ename,
ZZ_SFZH = x.idno,
GBDAT = x.birthday,
ZZ_KLX = x.ZZ_KLX,
ZXUELI = x.email,
ORGEH = x.appellation,
ZMOBILE = x.phone,
ZSTATUS = x.ZSTATUS,
ZRZRQ = x.createdate,
PERNR = x.PERNR,
WERKS = x.WERKS,
KOSTL = x.KOSTL,
ZZ_ZD = x.ZZ_ZD,
Z_ZJ = x.Z_ZJ,
STELL = x.STELL,
STELL_NM = x.STELL_NM,
ZLZRQ = x.ZLZRQ,
MASSN = x.MASSN,
MNTXT = x.MNTXT,
ZZ_COUNNM = x.ZZ_COUNNM,
ZZ_GZDJDNM = x.ZZ_GZDJDNM,
ZZ_GZDCQNM = x.ZZ_GZDCQNM
}).ToList();
}
private static List<GainfoSapEntity> ToGainfoSap(List<SapPersonItem> data)
{
return data.Select(person =>
{
//var position = _positions.FirstOrDefault(x => x.No == person.PLANS);
var rzrq = person.ZRZRQ;
var lzrq = person.ZLZRQ;
var rmk = $"入职时间:{rzrq.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)} ";
if (lzrq != null && lzrq.Value.ToString("yyyy-MM-dd") != "1900-01-01")
rmk += $"离职时间:{lzrq.Value.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)} ";
if (!string.IsNullOrWhiteSpace(person.MGTXT))
rmk += $"变更原因:{person.MGTXT}";
var native = GetNative(person.ZZ_SFZH);
var sex = person.GESCH == "2" ? "F" : "M";
person.ZZ_SFZH = person.ZZ_SFZH?.TrimStart();
GainfoSapEntity o = new()
{
gname = person.NAME,
ename = person.ZWORKCODE,
idno = person.ZZ_SFZH,
birthday = person.GBDAT,
ZZ_KLX = person.ZZ_KLX,
email = person.ZXUELI,
appellation = person.ORGEH,
phone = person.ZMOBILE,
ZSTATUS = person.ZSTATUS,
createdate = person.ZRZRQ,
PERNR = person.PERNR,
WERKS = person.WERKS,
KOSTL = person.KOSTL,
ZZ_ZD = person.ZZ_ZD,
Z_ZJ = person.Z_ZJ,
STELL = person.STELL,
STELL_NM = person.STELL_NM,
ZLZRQ = person.ZLZRQ,
MASSN = person.MASSN,
MNTXT = person.MNTXT,
remark = rmk,
native = native,
sex = sex,
logdate = DateTime.Now,
isowner = int.Parse(person.ZSTATUS) < 5 ? "T" : "F",
@class = "C",
country = person.ZZ_COUNNM,
log_ip = "127.0.0.1",
log_shift = "1",
log_id = "XX",
address = "",
occupation = "99",
nation = "01",
idcls = "ID",
ZZ_COUNNM = person.ZZ_COUNNM,
ZZ_GZDJDNM = person.ZZ_GZDJDNM,
ZZ_GZDCQNM = person.ZZ_GZDCQNM,
};
return o;
}).ToList();
}
private static string GetNative(string idNo)
{
if (string.IsNullOrWhiteSpace(idNo) || idNo.Length < 6) return null;
idNo = idNo.TrimStart();
return idNo[..6];
}
private static int? SafeParseCardType(string ZZ_KLX)
{
if (int.TryParse(ZZ_KLX, out var cardType))
{
return cardType;
}
return null;
}
}

View File

@@ -1,4 +1,4 @@
namespace Dlhis.ScheduledTask.Common;
namespace Dlhis.Basic.Organization.Services.Implements;
internal static class GetHashCodeExtensions
{

View File

@@ -3,7 +3,7 @@ using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
using Microsoft.AspNetCore.Identity;
namespace Dlhis.ScheduledTask.Common.Services.Implements;
namespace Dlhis.Basic.Organization.Services.Implements;
public class IdentityUserSyncService : IIdentityUserSyncService
{

View File

@@ -1,12 +1,12 @@
using System.Net;
using System.Text;
using Dlhis.Entity.Basic.Entity;
using Dlhis.ScheduledTask.Common.Dto;
using Dlhis.ScheduledTask.Common.Response;
using Dlhis.Jip.Api.Dto;
using Dlhis.Jip.Api.Responses;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Newtonsoft.Json;
namespace Dlhis.ScheduledTask.Common.Services.Implements;
namespace Dlhis.Basic.Organization.Services.Implements;
public class JinkoSapService : IJinkoSapService
{

View File

@@ -1,139 +1,147 @@
// using Dlhis.Entity.Basic.Entity;
// using Dlhis.Entity.Device.Entities;
// using Dlhis.Entity.Device.Enums;
// using Dlhis.Entity.Sys.Entities;
// using Dlhis.Entity.Sys.Enums;
// using Dlhis.Entity.Visitor.Entity;
// using Dlhis.Entity.Visitor.Enums;
// using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
// using SqlSugar;
//
// namespace Dlhis.Basic.Organization.Services.Implements;
//
// public class SapBusinessTripService : ISapBusinessTripService
// {
// private readonly IJinkoJipService _jinkoJipService;
// private readonly IDbContext _dbContext;
// private readonly ILogger<SapBusinessTripService> _logger;
//
// public SapBusinessTripService(IJinkoJipService jinkoJipService, IDbContext dbContext , ILogger<SapBusinessTripService> logger)
// {
// _jinkoJipService = jinkoJipService;
// _dbContext = dbContext;
// _logger = logger;
// }
//
// /// <inheritdoc />
// public async Task HandlerBusinessTripsByFactoryAsync(string factory)
// {
// var today = DateTime.Today;
// var yesterday = today.AddDays(-1);
//
// try
// {
// var tripResponse = await _jinkoJipService.GetTravelInfosByFactoryAsync(today, today, factory);
// if (!tripResponse.Items.Any())
// {
// return;
// }
//
// foreach (var tripInfoItem in tripResponse.Items.Where(x => x.Destination.IsPresent()))
// {
// if (await _dbContext.Queryable<BusinessTripEntity>().Where(x => x.Code == tripInfoItem.Code
// && x.BeginDate == tripInfoItem.BeginDate
// && x.EndDate == tripInfoItem.EndDate
// && x.Destination == factory).AnyAsync())
// {
// continue;
// }
//
// var entity = tripInfoItem.Adapt<BusinessTripEntity>();
// entity.Status = BusinessTripStatusEnumType.Wait;
// await _dbContext.InsertAsync(entity);
// }
//
// //获取今天和昨天的出差数据
// var tripInfos = await _dbContext.Queryable<BusinessTripEntity>()
// .Where(x => (SqlFunc.DateIsSame(x.BeginDate, today) && SqlFunc.DateIsSame(x.BeginDate, today))
// || (SqlFunc.DateIsSame(x.BeginDate, yesterday) && SqlFunc.DateIsSame(x.BeginDate, yesterday)))
// .Where(x => !SqlFunc.IsNullOrEmpty(x.Destination))
// .Where(x => x.Destination == factory)
// .ToListAsync();
//
// //获取分组信息
// var tripGroup = await _dbContext.Queryable<DeviceGroupEntity>()
// .Where(x => x.Type == DeviceTypeEnumType.Door)
// .Where(x => x.TenantId == factory)
// .Where(x => x.IsBusinessTrip)
// .SingleAsync();
//
// var userCodes = tripInfos.Select(x => x.Code).Distinct().ToList();
// var gainfos = await _dbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).ToListAsync();
//
// foreach (var gainfo in gainfos)
// {
// try
// {
// var myTripInfos = tripInfos.Where(x => x.Code == gainfo.Code).ToList();
//
// var yesterdayTripInfo = myTripInfos.FirstOrDefault(x => x.BeginDate == yesterday && x.EndDate == yesterday); //昨天出差数据
// var todayTripInfo = myTripInfos.FirstOrDefault(x => x.BeginDate == today && x.EndDate == today); //今天出差数据
//
// //都为空不处理
// if (yesterdayTripInfo == null && todayTripInfo == null) continue;
//
// //都不为空则更新数据状态
// if (yesterdayTripInfo != null && todayTripInfo != null)
// {
// todayTripInfo.Status = BusinessTripStatusEnumType.Generated;
// await _dbContext.UpdateAsync(todayTripInfo);
// continue;
// }
//
// var beforeResult = await _devicePermissionApi.GetPermissionUsersInfoAsync(new List<string> { gainfo.Code });
//
// if (yesterdayTripInfo != null)
// {
// yesterdayTripInfo.Status = BusinessTripStatusEnumType.Deleted;
// await _dbContext.Updateable<DevicePermissionEntity>()
// .SetColumns(x => x.IsDeleted == true)
// .Where(x => x.AssignType == AssignTypeEnumType.User)
// .Where(x => x.AssignValue == gainfo.No)
// .Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Group)
// .Where(x => x.UniqueValue == tripGroup.Code)
// .Where(x => x.Type == tripGroup.Type)
// .Where(x => x.TenantId == factory)
// .ExecuteCommandAsync();
// await _dbContext.UpdateAsync(yesterdayTripInfo);
// }
//
// if (yesterdayTripInfo == null)
// {
// todayTripInfo.Status = BusinessTripStatusEnumType.Generated;
// await _dbContext.InsertAsync(new DevicePermissionEntity
// {
// AssignType = AssignTypeEnumType.User,
// AssignValue = gainfo.No,
// UniqueType = DeviceAssignmentTypeEnumType.Group,
// UniqueValue = tripGroup.Code,
// TenantId = factory,
// Type = tripGroup.Type,
// IsDeleted = false
// });
// await _dbContext.UpdateAsync(todayTripInfo);
// }
//
// await _devicePermissionApi.RePermissionUsersInfoAsync(beforeResult.Data);
// }
// catch (Exception e)
// {
// _logger.LogError(e, "出差自动下发任务失败:{message}", e.Message);
// }
// }
// }
// catch (Exception e)
// {
// _logger.LogError(e, "处理{factory}出差数据失败:{message}", factory, e.Message);
// }
// }
// }
using Dlhis.Basic.Device.Services;
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Sys.Entities;
using Dlhis.Entity.Sys.Enums;
using Dlhis.Entity.Visitor.Entity;
using Dlhis.Entity.Visitor.Enums;
using Dlhis.Jip.Api;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
using Mapster;
using SqlSugar;
namespace Dlhis.Basic.Organization.Services.Implements;
public class SapBusinessTripService : ISapBusinessTripService
{
private readonly IJinkoJipApi _jinkoJipApi;
private readonly IDbContext _dbContext;
private readonly IDevicePermissionService _devicePermissionService;
private readonly ILogger<SapBusinessTripService> _logger;
public SapBusinessTripService(IJinkoJipApi jinkoJipApi,
IDbContext dbContext,
IDevicePermissionService devicePermissionService,
ILogger<SapBusinessTripService> logger)
{
_jinkoJipApi = jinkoJipApi;
_dbContext = dbContext;
_devicePermissionService = devicePermissionService;
_logger = logger;
}
/// <inheritdoc />
public async Task HandlerBusinessTripsByFactoryAsync(string factory)
{
var today = DateTime.Today;
var yesterday = today.AddDays(-1);
try
{
var tripResponse = await _jinkoJipApi.GetBusinessTripInfosByFactoryAsync(factory, today, today);
if (!tripResponse.Items.Any())
{
return;
}
foreach (var tripInfoItem in tripResponse.Items.Where(x => x.Destination.IsPresent()))
{
if (await _dbContext.Queryable<BusinessTripEntity>().Where(x => x.Code == tripInfoItem.Code
&& x.BeginDate == tripInfoItem.BeginDate
&& x.EndDate == tripInfoItem.EndDate
&& x.Destination == factory).AnyAsync())
{
continue;
}
var entity = tripInfoItem.Adapt<BusinessTripEntity>();
entity.Status = BusinessTripStatusEnumType.Wait;
await _dbContext.InsertAsync(entity);
}
//获取今天和昨天的出差数据
var tripInfos = await _dbContext.Queryable<BusinessTripEntity>()
.Where(x => (SqlFunc.DateIsSame(x.BeginDate, today) && SqlFunc.DateIsSame(x.BeginDate, today))
|| (SqlFunc.DateIsSame(x.BeginDate, yesterday) && SqlFunc.DateIsSame(x.BeginDate, yesterday)))
.Where(x => !SqlFunc.IsNullOrEmpty(x.Destination))
.Where(x => x.Destination == factory)
.ToListAsync();
//获取分组信息
var tripGroup = await _dbContext.Queryable<DeviceGroupEntity>()
.Where(x => x.Type == DeviceTypeEnumType.Door)
.Where(x => x.TenantId == factory)
.Where(x => x.IsBusinessTrip)
.SingleAsync();
var userCodes = tripInfos.Select(x => x.Code).Distinct().ToList();
var gainfos = await _dbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.No, x.Code }).ToListAsync();
foreach (var gainfo in gainfos)
{
try
{
var myTripInfos = tripInfos.Where(x => x.Code == gainfo.Code).ToList();
var yesterdayTripInfo = myTripInfos.FirstOrDefault(x => x.BeginDate == yesterday && x.EndDate == yesterday); //昨天出差数据
var todayTripInfo = myTripInfos.FirstOrDefault(x => x.BeginDate == today && x.EndDate == today); //今天出差数据
//都为空不处理
if (yesterdayTripInfo == null && todayTripInfo == null) continue;
//都不为空则更新数据状态
if (yesterdayTripInfo != null && todayTripInfo != null)
{
todayTripInfo.Status = BusinessTripStatusEnumType.Generated;
await _dbContext.UpdateAsync(todayTripInfo);
continue;
}
await _devicePermissionService.GenerateDeviceTasksAsync(async () =>
{
if (yesterdayTripInfo != null)
{
yesterdayTripInfo.Status = BusinessTripStatusEnumType.Deleted;
await _dbContext.Updateable<DevicePermissionEntity>()
.SetColumns(x => x.IsDeleted == true)
.Where(x => x.AssignType == AssignTypeEnumType.User)
.Where(x => x.AssignValue == gainfo.No)
.Where(x => x.UniqueType == DeviceAssignmentTypeEnumType.Group)
.Where(x => x.UniqueValue == tripGroup.Code)
.Where(x => x.Type == tripGroup.Type)
.Where(x => x.TenantId == factory)
.ExecuteCommandAsync();
await _dbContext.UpdateAsync(yesterdayTripInfo);
}
if (yesterdayTripInfo == null)
{
todayTripInfo.Status = BusinessTripStatusEnumType.Generated;
await _dbContext.InsertAsync(new DevicePermissionEntity
{
AssignType = AssignTypeEnumType.User,
AssignValue = gainfo.No,
UniqueType = DeviceAssignmentTypeEnumType.Group,
UniqueValue = tripGroup.Code,
TenantId = factory,
Type = tripGroup.Type,
IsDeleted = false
});
await _dbContext.UpdateAsync(todayTripInfo);
}
}, new List<string> { gainfo.No });
}
catch (Exception e)
{
_logger.LogError(e, "出差自动下发任务失败:{message}", e.Message);
}
}
}
catch (Exception e)
{
_logger.LogError(e, "处理{factory}出差数据失败:{message}", factory, e.Message);
}
}
}

View File

@@ -35,8 +35,7 @@ public class BusinessPlacePermissionsService : IBusinessPlacePermissionsService
})
.ToPageListAsync(request);
var usersResult = await _userApi.GetUserByIdsAsync(page.Data.Select(x => x.UserId).Distinct().ToList());
var users = usersResult.Data;
var users = await _userApi.GetUserByIdsAsync(page.Data.Select(x => x.UserId).Distinct().ToList());
page.Data.ForEach(item => { item.UserName = users.FirstOrDefault(x => x.Id == item.UserId)?.UserName; });
@@ -98,9 +97,7 @@ public class BusinessPlacePermissionsService : IBusinessPlacePermissionsService
})
.ToListAsync();
var userResult = await _userApi.GetUserByIdAsync(id);
var user = userResult.Data;
var user = await _userApi.GetUserByIdAsync(id);
infos.ForEach(item => { item.UserName = user?.UserName; });
return infos;

View File

@@ -22,7 +22,7 @@
"Timeout": 30,
"SlowSqlTime": 1,
"EnableSqlLog": true,
"Generate": true
"Generate": false
},
"SwaggerOptions": {
"Enable": true,

View File

@@ -69,8 +69,7 @@ public class MealSupplementRecordService : IMealSupplementRecordService
var tenants = new List<TenantResponse>();
try
{
var tenantsResult = await _tenantApi.GetTenantsInternalAsync();
tenants = tenantsResult.Data;
tenants = await _tenantApi.GetTenantsInternalAsync();
}
catch (Exception)
{

View File

@@ -93,8 +93,7 @@ public class BalanceService : IBalanceService
try
{
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
page.Data.ForEach(item =>
{
@@ -233,7 +232,7 @@ public class BalanceService : IBalanceService
public async Task<BalanceRecordByBusinessPlaceResponse> RecordPageDetailsAsync(BalanceRecordPageDetailRequest request)
{
var myCodes = (await _businessPlacePermissionsApi.GetMyAsync()).Data.Select(x => (Guid?)x.Code).ToList();
var myCodes = (await _businessPlacePermissionsApi.GetMyAsync()).Select(x => (Guid?)x.Code).ToList();
if (request.BusinessplaceCodes.IsPresent())
{
myCodes = myCodes.Where(x => request.BusinessplaceCodes.Contains(x)).ToList();
@@ -272,9 +271,7 @@ public class BalanceService : IBalanceService
try
{
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
page.Data.ForEach(item => { item.Factory = tenants.FirstOrDefault(x => x.Code == item.Factory)?.Name; });
}
catch (Exception)
@@ -538,6 +535,8 @@ public class BalanceService : IBalanceService
Werks = gainfo.Werks,
IsDeleted = false
});
await _balanceRepository.CalculateBalanceAsync(gainfo.Code);
}
}

View File

@@ -132,14 +132,10 @@ public class OrderService : IOrderService
private async Task CheckPermissionAsync(string userCode, string deviceUniqueNo)
{
var r = await _gainfoPermissionApi.GetPermissionsDeviceCodesAsync(userCode);
if (r.Code != Kurisu.RemoteCall.Default.ApiStateCode.Success)
{
true.ThrowIfTrue(r.Msg);
}
var data = await _gainfoPermissionApi.GetPermissionsDeviceCodesAsync(userCode);
var code = await _dbContext.Queryable<DeviceEntity>().Where(x => x.UniqueNo == deviceUniqueNo).Select(x => x.Code).SingleAsync();
r.Data.Contains(code).ThrowIfFalse("无权消费");
data.Contains(code).ThrowIfFalse("无权消费");
}

View File

@@ -3,11 +3,11 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.2" />
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.5" />
</ItemGroup>
</Project>

View File

@@ -1,12 +1,12 @@
using Dlhis.InfoCheck.Api.Requests;
using Kurisu.RemoteCall.Attributes;
using Kurisu.RemoteCall.Default;
namespace Dlhis.InfoCheck.Api;
/// <summary>
/// 信息检查
/// </summary>
[RequestResultHandler]
[EnableRemoteClient(Name = "infocheck-service", BaseUrl = "${InternalRequest:InfoCheckRequestUrl}")]
public interface IInfoCheckApi
{
@@ -16,5 +16,5 @@ public interface IInfoCheckApi
/// <param name="request"></param>
/// <returns></returns>
[Post("/api/face/detection")]
Task<DefaultApiResult<List<string>>> FaceDetectAsync(FaceDetectRequest request);
Task<List<string>> FaceDetectAsync(FaceDetectRequest request);
}

View File

@@ -0,0 +1,13 @@
using Kurisu.RemoteCall.Abstractions;
using Microsoft.Extensions.DependencyInjection;
namespace Dlhis.Jip.Api.ClientHandlers;
public class JipClientHandler : IHttpRemoteCallPolicyHandler
{
/// <inheritdoc />
public IHttpClientBuilder ConfigureHttpClient(IHttpClientBuilder builder)
{
return builder;
}
}

View File

@@ -0,0 +1,47 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Kurisu.RemoteCall.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
namespace Dlhis.Jip.Api.ClientHandlers;
public class JipTokenHandler : IAsyncAuthTokenHandler
{
/// <inheritdoc />
public async Task<string> GetTokenAsync(IServiceProvider serviceProvider)
{
var configuration = serviceProvider.GetService<IConfiguration>()!;
var jwtKey = configuration.GetSection("JinkoOptions:Jip:Key").Value;
var jwtSecret = configuration.GetSection("JinkoOptions:Jip:Secret").Value;
const int min = 5;
var now = DateTime.Now.AddMinutes(-min);
var expires = DateTime.Now.AddMinutes(min);
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(now).ToUnixTimeSeconds()}"),
new(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(expires).ToUnixTimeSeconds()}"),
new(JwtRegisteredClaimNames.Iss, jwtKey),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret));
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Issuer = jwtKey,
IssuedAt = now,
NotBefore = now,
Expires = expires,
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
};
var jwtHandler = new JwtSecurityTokenHandler();
var securityToken = jwtHandler.CreateToken(descriptor);
return await Task.FromResult(jwtHandler.WriteToken(securityToken));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.5" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.10.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,15 @@
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.Dto;
/// <summary>
/// sap机构信息
/// </summary>
public class SapOrganization
{
/// <summary>
/// 机构项
/// </summary>
[JsonProperty("item")]
public List<SapOrganizationItem> Items { get; set; }
}

View File

@@ -0,0 +1,66 @@
namespace Dlhis.Jip.Api.Dto;
public class SapOrganizationItem
{
/// <summary>
/// 开始日期
/// </summary>
public string BEGDA { get; set; }
/// <summary>
/// 结束日期
/// </summary>
public string ENDDA { get; set; }
/// <summary>
/// 语言
/// </summary>
public string 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();
//}

View File

@@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.Dto;
public class SapPerson<T>
{
[JsonProperty("item")]
public List<T> Items { get; set; }
}

View File

@@ -0,0 +1,19 @@
// namespace Dlhis.ScheduledTask.Common.Dto
// {
// public class SapPersonDepartmentStatus
// {
// public string ZWORKCODE { get; set; }
//
// public DateTime BEGDA { get; set; }
//
// public DateTime ENDDA { get; set; }
//
// public string WERKS { get; set; }
//
// /// <summary>
// /// 部门号
// /// </summary>
// public string ORGEH { get; set; }
//
// }
// }

View File

@@ -0,0 +1,211 @@
namespace Dlhis.Jip.Api.Dto;
public class SapPersonItem
{
public string KOSTL { get; set; }
/// <summary>
/// 离职日期
/// </summary>
public DateTime? 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 DateTime 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 DateTime 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; }
/// <summary>
/// 国家
/// </summary>
public string ZZ_COUNNM { get; set; }
/// <summary>
/// 基地
/// </summary>
public string ZZ_GZDJDNM { get; set; }
/// <summary>
/// 厂区
/// </summary>
public string ZZ_GZDCQNM { get; set; }
}

View File

@@ -1,4 +1,4 @@
// namespace Dlhis.ScheduledTask.Common.Dto
// namespace Dlhis.ScheduledTask.Common.Dto
// {
// public class SapPersonJobStatus
// {

View File

@@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.Dto;
public class SapPosition
{
[JsonProperty("item")]
public List<SapPositionItem> Items { get; set; }
}

View File

@@ -0,0 +1,40 @@
namespace Dlhis.Jip.Api.Dto
{
public class SapPositionItem
{
/// <summary>
/// 开始日期
/// </summary>
public string BEGDA { get; set; }
/// <summary>
/// 结束日期
/// </summary>
public string ENDDA { get; set; }
/// <summary>
/// 语言代码
/// </summary>
public string LANGU { get; set; }
/// <summary>
/// 岗位编码
/// </summary>
public string ZJOBID { get; set; }
/// <summary>
/// 岗位名称
/// </summary>
public string ZJOBNAME { get; set; }
/// <summary>
///
/// </summary>
public string ZZWID { get; set; }
/// <summary>
/// 所属部门ID
/// </summary>
public string ZDEPID { get; set; }
}
}

View File

@@ -0,0 +1,86 @@
using Dlhis.Jip.Api.ClientHandlers;
using Dlhis.Jip.Api.Request;
using Dlhis.Jip.Api.RequestContentHandlers;
using Dlhis.Jip.Api.Requests;
using Dlhis.Jip.Api.Responses;
using Dlhis.Jip.Api.ResultHandlers;
using Kurisu.RemoteCall.Attributes;
namespace Dlhis.Jip.Api;
/// <summary>
/// jinko-jip api https://jip.jinkosolar.com
/// </summary>
[Auth(TokenHandler = typeof(JipTokenHandler))]
[EnableRemoteClient(Name = "jip-service", BaseUrl = "${JinkoOptions:Jip:BaseUrl}", PolicyHandler = typeof(JipClientHandler))]
public interface IJinkoJipApi
{
/// <summary>
/// 上传考勤记录
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[Post("/JIP/HCM/HCM_SWIPE_DATA_SAVE")]
Task<UploadAttendanceResponse> UploadAttendancesAsync(UploadAttendanceRequest request);
/// <summary>
/// 获取出差信息
/// </summary>
/// <param name="factory">厂区</param>
/// <param name="start">开始时间</param>
/// <param name="end">结束时间</param>
/// <code>
/// var obj = new
/// {
/// I_PAGE = 1,
/// I_LINE = 500,
/// IV_BEGDA = beginDay,
/// IV_ENDDA = endDay,
/// IT_CCMDD = new List{object}
/// {
/// new
/// {
/// IV_CCMDD = factory
/// }
/// }
/// }
/// </code>
/// <code>
///var obj = new
///{
/// IV_BEGDA = beginDay,
/// IV_ENDDA = endDay,
/// IT_2002GH = new List{object}
/// {
/// new
/// {
/// IV_GONGH = userCode
/// }
/// }
///};
/// </code>
/// <returns></returns>
[Post("/JIP/HCM/HCM_TRAVELINFO")]
[RequestContentHandler(typeof(BusinessTripContentHandler))]
Task<SapBusinessTripInfoResponse> GetBusinessTripInfosByFactoryAsync(string factory, DateTime start, DateTime end);
/// <summary>
/// 同步餐补状态
/// </summary>
/// <param name="requests"></param>
/// <returns></returns>
[Post("/JIP/DHR/DHR_DL_CALLBACK")]
[RequestResultHandler(typeof(DHRResultHandler))]
Task<string> SyncMealSupplementRecordsAsync(List<SyncMealSupplementRecordRequest> requests);
/// <summary>
/// 同步照片到sap
/// </summary>
/// <param name="userCode"></param>
/// <param name="base64"></param>
/// <returns></returns>
[Post("/JIP/HCM/HCM_I_PHOTO")]
[RequestContentHandler(typeof(SyncFaceContentHandler))]
Task<SapFaceSyncResponse> SyncFaceToSapAsync(string userCode, string base64);
}

View File

@@ -0,0 +1,36 @@
using System.Text;
using Kurisu.RemoteCall;
using Kurisu.RemoteCall.Abstractions;
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.RequestContentHandlers;
public class BusinessTripContentHandler : IContentHandler
{
/// <inheritdoc />
public HttpContent Create(List<ParameterValue> values)
{
var factory = values.First(x => x.Parameter.Name.Equals("factory", StringComparison.OrdinalIgnoreCase)).GetValue<string>();
var start = values.First(x => x.Parameter.Name.Equals("start", StringComparison.OrdinalIgnoreCase)).GetValue<DateTime>().ToString("yyyy-MM-dd");
var end = values.First(x => x.Parameter.Name.Equals("end", StringComparison.OrdinalIgnoreCase)).GetValue<DateTime>().ToString("yyyy-MM-dd");
var obj = new
{
I_PAGE = 1,
I_LINE = 500,
IV_BEGDA = start,
IV_ENDDA = end,
IT_CCMDD = new List<object>
{
new
{
IV_CCMDD = factory
}
}
};
var json = JsonConvert.SerializeObject(obj);
return new StringContent(json, Encoding.UTF8, "application/json");
}
}

View File

@@ -0,0 +1,26 @@
using System.Text;
using Kurisu.RemoteCall;
using Kurisu.RemoteCall.Abstractions;
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.RequestContentHandlers;
public class SyncFaceContentHandler : IContentHandler
{
/// <inheritdoc />
public HttpContent Create(List<ParameterValue> values)
{
var userCode = values.First(x => x.Parameter.Name.Equals("userCode", StringComparison.OrdinalIgnoreCase)).GetValue<string>();
var base64 = values.First(x => x.Parameter.Name.Equals("base64", StringComparison.OrdinalIgnoreCase)).GetValue<string>();
var obj = new
{
I_WORKCODE = userCode,
I_PHOTO_STR = base64
};
var json = JsonConvert.SerializeObject(obj);
return new StringContent(json, Encoding.UTF8, "application/json");
}
}

View File

@@ -0,0 +1,12 @@
namespace Dlhis.Jip.Api.Requests
{
public class GetBusinessTripInfosByFactoryRequest
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int PageIndex { get; set; }
public int PageSize { get; set; }
}
}

View File

@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
namespace Dlhis.ScheduledTask.Common.Request;
namespace Dlhis.Jip.Api.Request;
public class SapNoRequest
{

View File

@@ -1,4 +1,4 @@
namespace Dlhis.ScheduledTask.Common.Request;
namespace Dlhis.Jip.Api.Request;
public class SyncMealSupplementRecordRequest
{

View File

@@ -0,0 +1,41 @@
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.Requests;
public class UploadAttendanceRequest
{
/// <summary>
/// 考勤数据包
/// </summary>
[JsonProperty("T_DATA")]
public List<UploadAttendanceRequestItem> Data { get; set; }
}
public class UploadAttendanceRequestItem
{
[JsonIgnore]
public long Id { get; set; }
/// <summary>
/// item.CardNo.TrimEnd('\0')
/// </summary>
public string ZWORKCODE { get; set; }
[JsonIgnore]
public DateTime RaiseDateTime { get; set; }
/// <summary>
/// yyyy-MM-dd
/// </summary>
public string ZDATE => RaiseDateTime.ToString("yyyy-MM-dd");
/// <summary>
/// HH:mm:ss
/// </summary>
public string ZTIME => RaiseDateTime.ToString("HH:mm:ss");
/// <summary>
/// 设备位置
/// </summary>
public string ZNOTE { get; set; }
}

View File

@@ -0,0 +1,11 @@
namespace Dlhis.Jip.Api.Responses;
public class DHRResponse<T>
{
/// <summary>
/// 200:success
/// </summary>
public int Code { get; set; }
public string Message { get; set; }
public T Data { get; set; }
}

View File

@@ -1,6 +1,6 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
namespace Dlhis.ScheduledTask.Common.Response;
namespace Dlhis.Jip.Api.Responses;
public class SapBusinessTripInfoResponse
{

View File

@@ -0,0 +1,11 @@
namespace Dlhis.Jip.Api.Responses;
public class SapFaceSyncResponse
{
/// <summary>
/// S 成功
/// </summary>
public string OLX { get; set; }
public string OMS { get; set; }
}

View File

@@ -0,0 +1,10 @@
using Dlhis.Jip.Api.Dto;
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.Responses;
public class SapOrganizationResponse
{
[JsonProperty("T_ORG")]
public SapOrganization Org { get; set; }
}

View File

@@ -1,7 +1,7 @@
using Dlhis.ScheduledTask.Common.Dto;
using Dlhis.Jip.Api.Dto;
using Newtonsoft.Json;
namespace Dlhis.ScheduledTask.Common.Response;
namespace Dlhis.Jip.Api.Responses;
public class SapPersonResponse
{

View File

@@ -0,0 +1,10 @@
using Dlhis.Jip.Api.Dto;
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.Responses;
public class SapPositionResponse
{
[JsonProperty("T_POST")]
public SapPosition Position { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace Dlhis.ScheduledTask.Common.Response;
namespace Dlhis.Jip.Api.Responses;
public class UploadAttendanceResponse
{

View File

@@ -0,0 +1,22 @@
using System.Net;
using Dlhis.Jip.Api.Responses;
using Kurisu.RemoteCall.Abstractions;
using Mapster;
using Newtonsoft.Json;
namespace Dlhis.Jip.Api.ResultHandlers;
public class DHRResultHandler : IRemoteCallResultHandler
{
/// <inheritdoc />
public TResult Handle<TResult>(HttpStatusCode statusCode, string responseBody)
{
var apiResult = JsonConvert.DeserializeObject<DHRResponse<object>>(responseBody);
if (statusCode != HttpStatusCode.OK || apiResult.Code != 200)
{
throw new Exception(apiResult?.Message);
}
return responseBody.Adapt<TResult>();
}
}

View File

@@ -1,42 +0,0 @@
using Newtonsoft.Json;
namespace Dlhis.ScheduledTask.Common.Request
{
public class UploadAttendanceRequest
{
/// <summary>
/// 考勤数据包
/// </summary>
[JsonProperty("T_DATA")]
public List<UploadAttendanceRequestItem> Data { get; set; }
}
public class UploadAttendanceRequestItem
{
[JsonIgnore]
public long Id { get; set; }
/// <summary>
/// item.CardNo.TrimEnd('\0')
/// </summary>
public string ZWORKCODE { get; set; }
[JsonIgnore]
public DateTime RaiseDateTime { get; set; }
/// <summary>
/// yyyy-MM-dd
/// </summary>
public string ZDATE => RaiseDateTime.ToString("yyyy-MM-dd");
/// <summary>
/// HH:mm:ss
/// </summary>
public string ZTIME => RaiseDateTime.ToString("HH:mm:ss");
/// <summary>
/// 设备位置
/// </summary>
public string ZNOTE { get; set; }
}
}

View File

@@ -1,28 +1,25 @@
using Dlhis.Basic.Api.Request;
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.TaskAssignment.Request;
namespace Dlhis.ScheduledTask.Common.Services;
/// <summary>
/// hangfire调度服务
/// </summary>
public interface IHangfireService : IScopeDependency
{
/// <summary>
/// 创建sap人员同步后台任务
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task CreateSapPersonSyncBackgroundJobAsync(SapNoRequest request);
/// <summary>
/// 创建sap人事范围同步后台任务
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task CreateSapWerkSyncBackgroundJobAsync(SapNoRequest request);
Task FaceUploadToSapAsync(FaceUploadToSapRequest request);
}
// using Dlhis.Basic.Api.Request;
// using Dlhis.ScheduledTask.Common.Request;
// using Dlhis.ScheduledTask.TaskAssignment.Request;
//
// namespace Dlhis.ScheduledTask.Common.Services;
//
// /// <summary>
// /// hangfire调度服务
// /// </summary>
// public interface IHangfireService : IScopeDependency
// {
// /// <summary>
// /// 创建sap人员同步后台任务
// /// </summary>
// /// <param name="request"></param>
// /// <returns></returns>
// Task CreateSapPersonSyncBackgroundJobAsync(SapNoRequest request);
//
// /// <summary>
// /// 创建sap人事范围同步后台任务
// /// </summary>
// /// <param name="request"></param>
// /// <returns></returns>
// Task CreateSapWerkSyncBackgroundJobAsync(SapNoRequest request);
// }

View File

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

View File

@@ -1,63 +1,50 @@
using Dlhis.Entity.Basic.Entity;
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.TaskAssignment.Request;
using Hangfire;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.ScheduledTask.Common.Services.Implements;
public class HangfireService : IHangfireService
{
private readonly RedisCache _redisCache;
private readonly IDbContext _dbContext;
private readonly IJinkoJipService _jinkoJipService;
public HangfireService(RedisCache redisCache, IDbContext dbContext, IJinkoJipService jinkoJipService)
{
_redisCache = redisCache;
_dbContext = dbContext;
_jinkoJipService = jinkoJipService;
}
public async Task CreateSapPersonSyncBackgroundJobAsync(SapNoRequest request)
{
// var jobKey = $"hangfire:background:person:{request.Code}";
//
// using var handler = await _redisCache.LockAsync(jobKey);
// if (handler.Acquired)
// {
// BackgroundJob.Enqueue<IGainfoUpdateService>(x => x.TodoByCodeAsync(request.Code));
// }
}
public async Task CreateSapWerkSyncBackgroundJobAsync(SapNoRequest request)
{
// var jobKey = $"hangfire:background:werk:{request.Code}";
//
// await using var handler = await _redisCache.LockAsync(jobKey);
// if (handler.Acquired)
// {
// var werkInfo = await _dbContext.Queryable<WerkEntity>().Where(x => x.Werk == request.Code).SingleAsync();
// werkInfo.ThrowIfNull("人事范围不存在");
//
// werkInfo.BackgroundJobKey.IsPresent().ThrowIfTrue("任务进行中,无法再次发起同步");
//
// BackgroundJob.Enqueue<IGainfoUpdateService>(x => x.TodoByWerkAsync(request.Code));
// }
}
public async Task FaceUploadToSapAsync(FaceUploadToSapRequest request)
{
// var response = await _jinkoJipService.SyncFaceToSapAsync(request.UserCode, request.Base64);
// if (response.OLX == "S")
// {
// var faceDbContext = _dbContext.ChangeDb("face");
// await faceDbContext.Updateable<GainfoFaceEntity>()
// .SetColumns(x => x.IsSync == true)
// .Where(x => x.UserCode == request.UserCode)
// .ExecuteCommandAsync();
// }
}
}
// using Dlhis.Entity.Basic.Entity;
// using Dlhis.ScheduledTask.Common.Request;
// using Dlhis.ScheduledTask.TaskAssignment.Request;
// using Hangfire;
// using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
// using Kurisu.AspNetCore.Utils;
// using Kurisu.AspNetCore.Utils.Extensions;
//
// namespace Dlhis.ScheduledTask.Common.Services.Implements;
//
// public class HangfireService : IHangfireService
// {
// private readonly RedisCache _redisCache;
// private readonly IDbContext _dbContext;
// private readonly IJinkoJipService _jinkoJipService;
//
// public HangfireService(RedisCache redisCache, IDbContext dbContext, IJinkoJipService jinkoJipService)
// {
// _redisCache = redisCache;
// _dbContext = dbContext;
// _jinkoJipService = jinkoJipService;
// }
//
// public async Task CreateSapPersonSyncBackgroundJobAsync(SapNoRequest request)
// {
// // var jobKey = $"hangfire:background:person:{request.Code}";
// //
// // using var handler = await _redisCache.LockAsync(jobKey);
// // if (handler.Acquired)
// // {
// // BackgroundJob.Enqueue<IGainfoUpdateService>(x => x.TodoByCodeAsync(request.Code));
// // }
// }
//
// public async Task CreateSapWerkSyncBackgroundJobAsync(SapNoRequest request)
// {
// // var jobKey = $"hangfire:background:werk:{request.Code}";
// //
// // await using var handler = await _redisCache.LockAsync(jobKey);
// // if (handler.Acquired)
// // {
// // var werkInfo = await _dbContext.Queryable<WerkEntity>().Where(x => x.Werk == request.Code).SingleAsync();
// // werkInfo.ThrowIfNull("人事范围不存在");
// //
// // werkInfo.BackgroundJobKey.IsPresent().ThrowIfTrue("任务进行中,无法再次发起同步");
// //
// // BackgroundJob.Enqueue<IGainfoUpdateService>(x => x.TodoByWerkAsync(request.Code));
// // }
// }
// }

View File

@@ -1,208 +0,0 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.Common.Response;
using Kurisu.AspNetCore.Utils.Extensions;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
namespace Dlhis.ScheduledTask.Common.Services.Implements;
public class JinkoJipService : IJinkoJipService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<JinkoJipService> _logger;
private readonly IConfiguration _configuration;
public JinkoJipService(IHttpClientFactory httpClientFactory, ILogger<JinkoJipService> logger, IConfiguration configuration)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
_configuration = configuration;
}
private HttpClient GetHttpClient()
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_configuration.GetSection("JinkoOptions:Jip:BaseUrl").Value);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", IssueToken());
return httpClient;
}
public async Task<UploadAttendanceResponse> UploadAttendancesAsync(UploadAttendanceRequest request)
{
var requestUrl = "/JIP/HCM/HCM_SWIPE_DATA_SAVE";
var json = request.ToJson();
//_logger.LogInformation("上传考勤记录请求:{json}", json);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(requestUrl, content);
var responseJson = await response.Content.ReadAsStringAsync();
_logger.LogInformation("上传考勤记录响应:{json}", responseJson);
try
{
return responseJson.ToObject<UploadAttendanceResponse>();
}
catch (Exception)
{
return new UploadAttendanceResponse
{
OLX = "99",
OMS = "接口响应数据异常,无法反序列化"
};
}
}
public async Task<string> SyncMealSupplementRecordsAsync(List<SyncMealSupplementRecordRequest> requests)
{
var requestUrl = "/JIP/DHR/DHR_DL_CALLBACK";
var json = requests.ToJson(Kurisu.AspNetCore.Utils.Extensions.JsonExtensions.DefaultSetting);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(requestUrl, content);
var responseJson = await response.Content.ReadAsStringAsync();
_logger.LogInformation("餐补状态同步响应:{json}", responseJson);
var jobj = JObject.Parse(responseJson);
if (jobj.TryGetValue("exp", out var exp))
{
true.ThrowIfTrue(exp.Value<string>());
}
if (jobj.TryGetValue("message", out var message) && !jobj.ContainsKey("code"))
{
true.ThrowIfTrue(message.Value<string>());
}
(jobj.GetValue("code").Value<int>() != 200).ThrowIfTrue(jobj.GetValue("message").Value<string>());
return responseJson;
}
public async Task<SapBusinessTripInfoResponse> GetTravelInfosByFactoryAsync(DateTime begin, DateTime end, string factory)
{
const string apiUrl = "/JIP/HCM/HCM_TRAVELINFO";
var beginDay = begin.ToString("yyyyMMdd");
var endDay = end.ToString("yyyyMMdd");
var obj = new
{
I_PAGE = 1,
I_LINE = 500,
IV_BEGDA = beginDay,
IV_ENDDA = endDay,
IT_CCMDD = new List<object>
{
new
{
IV_CCMDD = factory
}
}
};
var body = obj.ToJson();
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(apiUrl, content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse.ToObject<SapBusinessTripInfoResponse>();
}
public async Task<SapBusinessTripInfoResponse> GetTravelInfosByUserCodeAsync(DateTime begin, DateTime end, string userCode)
{
const string apiUrl = "/JIP/HCM/HCM_TRAVELINFO";
var beginDay = begin.ToString("yyyyMMdd");
var endDay = end.ToString("yyyyMMdd");
//IV_GONGH IV_ORGID
//IT_2002GH
var obj = new
{
IV_BEGDA = beginDay,
IV_ENDDA = endDay,
IT_2002GH = new List<object>
{
new
{
IV_GONGH = userCode
}
}
};
var body = obj.ToJson();
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(apiUrl, content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse.ToObject<SapBusinessTripInfoResponse>();
}
public async Task<SapFaceSyncResponse> SyncFaceToSapAsync(string userCode, string base64)
{
const string apiUrl = "/JIP/HCM/HCM_I_PHOTO";
var obj = new
{
I_WORKCODE = userCode,
I_PHOTO_STR = base64
};
var body = obj.ToJson();
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(apiUrl, content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse.ToObject<SapFaceSyncResponse>();
}
public string IssueToken()
{
var jwtKey = _configuration.GetSection("JinkoOptions:Jip:Key").Value;
var jwtSecret = _configuration.GetSection("JinkoOptions:Jip:Secret").Value;
const int min = 5;
var now = DateTime.Now.AddMinutes(-min);
var expires = DateTime.Now.AddMinutes(min);
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(now).ToUnixTimeSeconds()}"),
new(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(expires).ToUnixTimeSeconds()}"),
new(JwtRegisteredClaimNames.Iss, jwtKey),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret));
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Issuer = jwtKey,
IssuedAt = now,
NotBefore = now,
Expires = expires,
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
};
var jwtHandler = new JwtSecurityTokenHandler();
var securityToken = jwtHandler.CreateToken(descriptor);
return jwtHandler.WriteToken(securityToken);
}
}

View File

@@ -1,208 +0,0 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.Common.Response;
using Kurisu.AspNetCore.Utils.Extensions;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
namespace Dlhis.ScheduledTask.Common.Services.Implements;
public class JinkoJipService : IJinkoJipService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<JinkoJipService> _logger;
private readonly IConfiguration _configuration;
public JinkoJipService(IHttpClientFactory httpClientFactory, ILogger<JinkoJipService> logger, IConfiguration configuration)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
_configuration = configuration;
}
private HttpClient GetHttpClient()
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_configuration.GetSection("JinkoOptions:Jip:BaseUrl").Value);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", IssueToken());
return httpClient;
}
public async Task<UploadAttendanceResponse> UploadAttendancesAsync(UploadAttendanceRequest request)
{
var requestUrl = "/JIP/HCM/HCM_SWIPE_DATA_SAVE";
var json = request.ToJson();
//_logger.LogInformation("上传考勤记录请求:{json}", json);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(requestUrl, content);
var responseJson = await response.Content.ReadAsStringAsync();
_logger.LogInformation("上传考勤记录响应:{json}", responseJson);
try
{
return responseJson.ToObject<UploadAttendanceResponse>();
}
catch (Exception)
{
return new UploadAttendanceResponse
{
OLX = "99",
OMS = "接口响应数据异常,无法反序列化"
};
}
}
public async Task<string> SyncMealSupplementRecordsAsync(List<SyncMealSupplementRecordRequest> requests)
{
var requestUrl = "/JIP/DHR/DHR_DL_CALLBACK";
var json = requests.ToJson(Kurisu.AspNetCore.Utils.Extensions.JsonExtensions.DefaultSetting);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(requestUrl, content);
var responseJson = await response.Content.ReadAsStringAsync();
_logger.LogInformation("餐补状态同步响应:{json}", responseJson);
var jobj = JObject.Parse(responseJson);
if (jobj.TryGetValue("exp", out var exp))
{
true.ThrowIfTrue(exp.Value<string>());
}
if (jobj.TryGetValue("message", out var message) && !jobj.ContainsKey("code"))
{
true.ThrowIfTrue(message.Value<string>());
}
(jobj.GetValue("code").Value<int>() != 200).ThrowIfTrue(jobj.GetValue("message").Value<string>());
return responseJson;
}
public async Task<SapBusinessTripInfoResponse> GetTravelInfosByFactoryAsync(DateTime begin, DateTime end, string factory)
{
const string apiUrl = "/JIP/HCM/HCM_TRAVELINFO";
var beginDay = begin.ToString("yyyyMMdd");
var endDay = end.ToString("yyyyMMdd");
var obj = new
{
I_PAGE = 1,
I_LINE = 500,
IV_BEGDA = beginDay,
IV_ENDDA = endDay,
IT_CCMDD = new List<object>
{
new
{
IV_CCMDD = factory
}
}
};
var body = obj.ToJson();
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(apiUrl, content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse.ToObject<SapBusinessTripInfoResponse>();
}
public async Task<SapBusinessTripInfoResponse> GetTravelInfosByUserCodeAsync(DateTime begin, DateTime end, string userCode)
{
const string apiUrl = "/JIP/HCM/HCM_TRAVELINFO";
var beginDay = begin.ToString("yyyyMMdd");
var endDay = end.ToString("yyyyMMdd");
//IV_GONGH IV_ORGID
//IT_2002GH
var obj = new
{
IV_BEGDA = beginDay,
IV_ENDDA = endDay,
IT_2002GH = new List<object>
{
new
{
IV_GONGH = userCode
}
}
};
var body = obj.ToJson();
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(apiUrl, content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse.ToObject<SapBusinessTripInfoResponse>();
}
public async Task<SapFaceSyncResponse> SyncFaceToSapAsync(string userCode, string base64)
{
const string apiUrl = "/JIP/HCM/HCM_I_PHOTO";
var obj = new
{
I_WORKCODE = userCode,
I_PHOTO_STR = base64
};
var body = obj.ToJson();
var content = new StringContent(body, Encoding.UTF8, "application/json");
var response = await GetHttpClient().PostAsync(apiUrl, content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse.ToObject<SapFaceSyncResponse>();
}
public string IssueToken()
{
var jwtKey = _configuration.GetSection("JinkoOptions:Jip:Key").Value;
var jwtSecret = _configuration.GetSection("JinkoOptions:Jip:Secret").Value;
const int min = 5;
var now = DateTime.Now.AddMinutes(-min);
var expires = DateTime.Now.AddMinutes(min);
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(now).ToUnixTimeSeconds()}"),
new(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(expires).ToUnixTimeSeconds()}"),
new(JwtRegisteredClaimNames.Iss, jwtKey),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret));
var descriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Issuer = jwtKey,
IssuedAt = now,
NotBefore = now,
Expires = expires,
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
};
var jwtHandler = new JwtSecurityTokenHandler();
var securityToken = jwtHandler.CreateToken(descriptor);
return jwtHandler.WriteToken(securityToken);
}
}

View File

@@ -25,6 +25,7 @@
<ItemGroup>
<ProjectReference Include="..\Dlhis.Basic.Api\Dlhis.Basic.Api.csproj" />
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
<ProjectReference Include="..\Dlhis.Jip.Api\Dlhis.Jip.Api.csproj" />
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
</ItemGroup>

View File

@@ -29,8 +29,7 @@ public class CreateDefinitelyGroupJob : BaseJob
protected override async Task RunAsync(IServiceProvider serviceProvider)
{
//获取所有基地信息
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
Logger.LogInformation("获取基地信息:{json}", JsonConvert.SerializeObject(tenants));

View File

@@ -2,10 +2,9 @@
using Dlhis.Entity.Basic.Enums;
using Dlhis.Entity.Canteen.Entities;
using Dlhis.Entity.Canteen.Enums;
using Dlhis.Jip.Api;
using Dlhis.Jip.Api.Request;
using Dlhis.ScheduledTask.Attributes;
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.Common.Services;
using Hangfire;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
using Kurisu.AspNetCore.Utils;
@@ -17,12 +16,12 @@ namespace Dlhis.ScheduledTask.Jobs;
[RecurringJob(nameof(MealSupplementHandlerJob), "0 0/30 * * * ?", Name = "餐补核算")]
public class MealSupplementHandlerJob : BaseJob
{
private readonly IJinkoJipService _jinkoJIPService;
private readonly IJinkoJipApi _jinkoJipApi;
public MealSupplementHandlerJob(IServiceProvider serviceProvider,
IJinkoJipService jinkoJIPService) : base(serviceProvider)
IJinkoJipApi jinkoJipApi) : base(serviceProvider)
{
_jinkoJIPService = jinkoJIPService;
_jinkoJipApi = jinkoJipApi;
}
protected override async Task RunAsync(IServiceProvider serviceProvider)
@@ -59,7 +58,7 @@ public class MealSupplementHandlerJob : BaseJob
{
try
{
var r = await _jinkoJIPService.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
var r = await _jinkoJipApi.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
{
new()
{
@@ -79,6 +78,7 @@ public class MealSupplementHandlerJob : BaseJob
}
catch
{
//ignore
}
continue;
@@ -121,8 +121,8 @@ public class MealSupplementHandlerJob : BaseJob
IsDeleted = false,
});
if (!await DbContext.Queryable<UserBalanceEntity>().Where(x => x.UserCode == gainfo.Code).AnyAsync())
{
await DbContext.InsertAsync(new UserBalanceEntity
@@ -153,8 +153,8 @@ public class MealSupplementHandlerJob : BaseJob
.Where(x => x.UserCode == gainfo.Code && x.Version == version)
.ExecuteCommandThrowVersionAsync();
}, 5);
var r = await _jinkoJIPService.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
var r = await _jinkoJipApi.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
{
new()
{

View File

@@ -1,6 +1,6 @@
using Dlhis.Basic.Api;
using Dlhis.Entity.Sys.Entities;
using Dlhis.ScheduledTask.Attributes;
using Dlhis.ScheduledTask.Common.Services;
using SqlSugar;
namespace Dlhis.ScheduledTask.Jobs;
@@ -8,23 +8,23 @@ namespace Dlhis.ScheduledTask.Jobs;
[RecurringJob(nameof(SyncBusinessTripJob), "0 0 1 1/1 * ? ", Name = "SAP同步出差信息")]
public class SyncBusinessTripJob : BaseJob
{
private readonly ISyncApi _syncApi;
/// <inheritdoc />
public SyncBusinessTripJob(IServiceProvider serviceProvider) : base(serviceProvider)
public SyncBusinessTripJob(IServiceProvider serviceProvider, ISyncApi syncApi) : base(serviceProvider)
{
_syncApi = syncApi;
}
/// <inheritdoc />
protected override async Task RunAsync(IServiceProvider serviceProvider)
{
// var sapBusinessTripService = serviceProvider.GetService<ISapBusinessTripService>();
//
// var identityDbContext = DbContext.ChangeDb("identity");
// var factories = await identityDbContext.Queryable<TenantEntity>().Where(x => !SqlFunc.IsNullOrEmpty(x.PCode)).ToListAsync();
//
// foreach (var factory in factories)
// {
// await sapBusinessTripService.HandlerBusinessTripsByFactoryAsync(factory.Code);
// }
var identityDbContext = DbContext.ChangeDb("identity");
var factories = await identityDbContext.Queryable<TenantEntity>().Where(x => !SqlFunc.IsNullOrEmpty(x.PCode)).ToListAsync();
foreach (var factory in factories)
{
await _syncApi.HandlerBusinessTripsAsync(factory.Code);
}
}
}

View File

@@ -1,7 +1,7 @@
using Dlhis.Entity.Basic.Entity;
using Dlhis.Basic.Api;
using Dlhis.Basic.Api.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.ScheduledTask.Attributes;
using Dlhis.ScheduledTask.Common.Dto;
using Dlhis.ScheduledTask.Common.Services;
namespace Dlhis.ScheduledTask.Jobs;
@@ -11,16 +11,16 @@ namespace Dlhis.ScheduledTask.Jobs;
[RecurringJob(nameof(SyncOrganizationJob), "0 0 0 * * ?", Name = "SAP组织架构数据同步")]
public class SyncOrganizationJob : BaseJob
{
private readonly IJinkoSapService _jinkoSapService;
private readonly ISyncApi _syncApi;
public SyncOrganizationJob(IServiceProvider serviceProvider, IJinkoSapService jinkoSapService) : base(serviceProvider)
public SyncOrganizationJob(IServiceProvider serviceProvider, ISyncApi syncApi) : base(serviceProvider)
{
_jinkoSapService = jinkoSapService;
_syncApi = syncApi;
}
protected override async Task RunAsync(IServiceProvider serviceProvider)
{
var orgResult = await _jinkoSapService.GetSapOrganizationsAsync();
var orgResult = await _syncApi.SyncOrganizationsAsync();
if (orgResult.Org != null && orgResult.Org.Items.Count > 0)
{
@@ -53,4 +53,4 @@ public class SyncOrganizationJob : BaseJob
}
}
}
}
}

View File

@@ -1,9 +1,9 @@
using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Jip.Api;
using Dlhis.Jip.Api.Requests;
using Dlhis.ScheduledTask.Attributes;
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.Common.Services;
using SqlSugar;
namespace Dlhis.ScheduledTask.Jobs;
@@ -14,11 +14,11 @@ namespace Dlhis.ScheduledTask.Jobs;
[RecurringJob(nameof(SyncOriginCardInfoJob), "0 0/1 * * * ?", Name = "上传考勤记录")]
public class SyncOriginCardInfoJob : BaseJob
{
private readonly IJinkoJipService _jinkoJipService;
private readonly IJinkoJipApi _jinkoJipApi;
public SyncOriginCardInfoJob(IJinkoJipService jinkoJipService, IServiceProvider serviceProvider) : base(serviceProvider)
public SyncOriginCardInfoJob(IJinkoJipApi jinkoJipApi, IServiceProvider serviceProvider) : base(serviceProvider)
{
_jinkoJipService = jinkoJipService;
_jinkoJipApi = jinkoJipApi;
}
protected override async Task RunAsync(IServiceProvider serviceProvider)
@@ -52,7 +52,7 @@ public class SyncOriginCardInfoJob : BaseJob
try
{
var ids = items.Select(x => x.Id).ToList();
var r = await _jinkoJipService.UploadAttendancesAsync(new UploadAttendanceRequest { Data = items.ToList() });
var r = await _jinkoJipApi.UploadAttendancesAsync(new UploadAttendanceRequest { Data = items.ToList() });
if (r.OLX == "0")
{
await DbContext.Updateable<DeviceUploadLogEntity>()

View File

@@ -1,7 +1,5 @@
using Dlhis.Entity.Basic.Entity;
using Dlhis.ScheduledTask.Attributes;
using Dlhis.ScheduledTask.Common.Services;
using Hangfire;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.ScheduledTask.Jobs;

View File

@@ -1,7 +1,7 @@
using Dlhis.Entity.Basic.Entity;
using Dlhis.Basic.Api;
using Dlhis.Basic.Api.Response;
using Dlhis.Entity.Basic.Entity;
using Dlhis.ScheduledTask.Attributes;
using Dlhis.ScheduledTask.Common.Dto;
using Dlhis.ScheduledTask.Common.Services;
namespace Dlhis.ScheduledTask.Jobs;
@@ -11,16 +11,16 @@ namespace Dlhis.ScheduledTask.Jobs;
[RecurringJob(nameof(SyncPositionJob), "0 0 0 * * ?", Name = "SAP岗位信息同步")]
public class SyncPositionJob : BaseJob
{
private readonly IJinkoSapService _jinkoSapService;
private readonly ISyncApi _syncApi;
public SyncPositionJob(IServiceProvider serviceProvider, IJinkoSapService jinkoSapService) : base(serviceProvider)
public SyncPositionJob(IServiceProvider serviceProvider, ISyncApi syncApi) : base(serviceProvider)
{
_jinkoSapService = jinkoSapService;
_syncApi = syncApi;
}
protected override async Task RunAsync(IServiceProvider serviceProvider)
{
var positionResult = await _jinkoSapService.GetPositionsAsync();
var positionResult = await _syncApi.GetPositionsAsync();
if (positionResult.Position != null && positionResult.Position.Items.Count > 0)
{

View File

@@ -1,3 +1,5 @@
using Dlhis.Jip.Api;
using Dlhis.Jip.Api.Request;
using Kurisu.AspNetCore.Startup;
using Kurisu.AspNetCore.Utils.Extensions;
@@ -20,4 +22,20 @@ public class Startup : DefaultStartup
base.ConfigureServices(services);
services.AddRedis();
}
/// <inheritdoc />
public override void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
base.Configure(app, env);
// var a = app.ApplicationServices.GetService<IJinkoJipApi>().SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>()
// {
// new SyncMealSupplementRecordRequest
// {
// UniqueId = null,
// Status = null,
// Msg = null
// }
// }).GetAwaiter().GetResult();
}
}

View File

@@ -1,7 +1,5 @@
using Dlhis.ScheduledTask.Common.Request;
using Dlhis.ScheduledTask.Common.Services;
using Dlhis.ScheduledTask.TaskAssignment.Request;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Dlhis.Basic.Api;
using Dlhis.Jip.Api.Request;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -10,18 +8,16 @@ namespace Dlhis.ScheduledTask.TaskAssignment.Controllers;
/// <summary>
/// 调度任务
/// </summary>
[Authorize(Roles = "admin")]
[AllowAnonymous]
[Route("api/[controller]")]
[ApiController]
public class HangfireController : ControllerBase
{
private readonly IHangfireService _hangfireService;
private readonly IDbContext _dbContext;
private readonly ISyncApi _gainfoSyncApi;
public HangfireController(IHangfireService hangfireService, IDbContext dbContext)
public HangfireController(ISyncApi gainfoSyncApi)
{
_hangfireService = hangfireService;
_dbContext = dbContext;
_gainfoSyncApi = gainfoSyncApi;
}
/// <summary>
@@ -29,11 +25,10 @@ public class HangfireController : ControllerBase
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost("sap/person/no")]
public async Task PersonManuallySync(SapNoRequest request)
{
await _hangfireService.CreateSapPersonSyncBackgroundJobAsync(request);
await _gainfoSyncApi.SyncGainfoByUserCodeAsync(request.Code);
}
/// <summary>
@@ -44,13 +39,6 @@ public class HangfireController : ControllerBase
[HttpPost("sap/werk/no")]
public async Task WerkManuallySync(SapNoRequest request)
{
await _hangfireService.CreateSapWerkSyncBackgroundJobAsync(request);
}
[AllowAnonymous]
[HttpPost("sap/face")]
public async Task FaceUploadToSapAsync(FaceUploadToSapRequest request)
{
await _hangfireService.FaceUploadToSapAsync(request);
await _gainfoSyncApi.SyncGainfoByWerkAsync(request.Code);
}
}

View File

@@ -1,7 +0,0 @@
namespace Dlhis.ScheduledTask.TaskAssignment.Request;
public class FaceUploadToSapRequest
{
public string UserCode { get; set; }
public string Base64 { get; set; }
}

View File

@@ -71,9 +71,7 @@ public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService
try
{
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
var tenants = tenantResult.Data;
var tenants = await _tenantApi.GetTenantsInternalAsync();
page.Data.ForEach(item => { item.TenantName = tenants.FirstOrDefault(x => x.Code == item.TenantId)?.Name; });
}
catch (Exception)

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.2" />
<PackageReference Include="Kurisu.RemoteCall" Version="0.4.5" />
</ItemGroup>
</Project>

View File

@@ -7,6 +7,7 @@ namespace Dlhis.Sys.Api;
/// <summary>
/// 租户Api
/// </summary>
[RequestResultHandler]
[EnableRemoteClient(Name = "sys-service", BaseUrl = "${InternalRequest:SysRequestUrl}")]
public interface ITenantApi
{
@@ -16,19 +17,18 @@ public interface ITenantApi
/// <returns></returns>
[Auth]
[Get("/api/tenants/list")]
Task<DefaultApiResult<List<TenantResponse>>> GetTenantsAsync();
Task<List<TenantResponse>> GetTenantsAsync();
[Auth]
[Get("/api/tenants/tree")]
Task<DefaultApiResult<List<TenantTreeResponse>>> GetTenantTreeAsync();
Task<List<TenantTreeResponse>> GetTenantTreeAsync();
/// <summary>
/// 获取所有租户(内部使用)
/// </summary>
/// <returns></returns>
[Get("/api/tenants/list-internal")]
Task<DefaultApiResult<List<TenantResponse>>> GetTenantsInternalAsync();
Task<List<TenantResponse>> GetTenantsInternalAsync();
/// <summary>
@@ -38,7 +38,7 @@ public interface ITenantApi
/// <returns></returns>
[Auth]
[Get("/api/tenants/single")]
Task<DefaultApiResult<TenantResponse>> GetTenantByCodeAsync(string code);
Task<TenantResponse> GetTenantByCodeAsync(string code);
/// <summary>
/// 获取我的管理的基地/租户
@@ -46,5 +46,5 @@ public interface ITenantApi
/// <returns></returns>
[Auth]
[Get("/api/tenants/my")]
Task<DefaultApiResult<List<TenantResponse>>> GetMyTenantsAsync();
}
Task<List<TenantResponse>> GetMyTenantsAsync();
}

View File

@@ -1,6 +1,5 @@
using Dlhis.Sys.Api.Response;
using Kurisu.RemoteCall.Attributes;
using Kurisu.RemoteCall.Default;
namespace Dlhis.Sys.Api;
@@ -9,9 +8,9 @@ public interface IUserApi
{
[Auth]
[Get("/api/users")]
Task<DefaultApiResult<UserResponse>> GetUserByIdAsync(int id);
Task<UserResponse> GetUserByIdAsync(int id);
[Auth]
[Post("/api/users/by-ids")]
Task<DefaultApiResult<List<UserResponse>>> GetUserByIdsAsync(List<int> ids);
Task<List<UserResponse>> GetUserByIdsAsync(List<int> ids);
}