refactor 封装任务,调整人员获取
This commit is contained in:
6
Src/Dlhis.ScheduledTask/Abstractions/IJob.cs
Normal file
6
Src/Dlhis.ScheduledTask/Abstractions/IJob.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Kurisu.Scheduled.Abstractions;
|
||||||
|
|
||||||
|
public interface IJob
|
||||||
|
{
|
||||||
|
Task TodoAsync();
|
||||||
|
}
|
||||||
18
Src/Dlhis.ScheduledTask/Attributes/RecurringJobAttribute.cs
Normal file
18
Src/Dlhis.ScheduledTask/Attributes/RecurringJobAttribute.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class RecurringJobAttribute : Attribute
|
||||||
|
{
|
||||||
|
public RecurringJobAttribute(string uniqueJobKey, string cron)
|
||||||
|
{
|
||||||
|
UniqueJobKey = uniqueJobKey;
|
||||||
|
Cron = cron;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string UniqueJobKey { get; }
|
||||||
|
public string Cron { get; }
|
||||||
|
|
||||||
|
public string Queue { get; set; } = "default";
|
||||||
|
}
|
||||||
53
Src/Dlhis.ScheduledTask/BaseJob.cs
Normal file
53
Src/Dlhis.ScheduledTask/BaseJob.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Kurisu.Core.DataAccess.Entity;
|
||||||
|
using Kurisu.Scheduled.Abstractions;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using Kurisu.SqlSugar.Services;
|
||||||
|
|
||||||
|
namespace Kurisu.Scheduled;
|
||||||
|
|
||||||
|
public abstract class BaseJob : IJob
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public BaseJob(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ILogger Logger { get; set; }
|
||||||
|
protected IDbContext DbContext { get; set; }
|
||||||
|
|
||||||
|
public async Task TodoAsync()
|
||||||
|
{
|
||||||
|
using (var scope = _serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
Logger = scope.ServiceProvider.GetService<ILogger<BaseJob>>();
|
||||||
|
DbContext = scope.ServiceProvider.GetService<IDbContext>();
|
||||||
|
var sqlSugarOptionsService = scope.ServiceProvider.GetService<ISqlSugarOptionsService>();
|
||||||
|
|
||||||
|
DbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
||||||
|
sqlSugarOptionsService.IgnoreTenant = true;
|
||||||
|
|
||||||
|
var name = this.GetType().GetCustomAttribute<RecurringJobAttribute>()!.Name;
|
||||||
|
Logger.LogDebug("[{name}]开始执行...", name);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await RunAsync(scope.ServiceProvider);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "[{name}]执行失败:{message} {stacktrace}", name, ex.Message, ex.StackTrace);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Logger.LogDebug("[{name}]执行结束...", name);
|
||||||
|
DbContext.Client.QueryFilter.Restore();
|
||||||
|
sqlSugarOptionsService.IgnoreTenant = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task RunAsync(IServiceProvider serviceProvider);
|
||||||
|
}
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
using Dlhis.Entity.Device.Entities;
|
|
||||||
using Dlhis.Entity.Device.Enums;
|
|
||||||
using Kurisu.AspNetCore.Utils.Extensions;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using SqlSugar;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.CommonJobs;
|
|
||||||
|
|
||||||
public class CancelDuplicationTaskJob
|
|
||||||
{
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
|
||||||
private readonly ILogger<CancelDuplicationTaskJob> _logger;
|
|
||||||
|
|
||||||
public CancelDuplicationTaskJob(IServiceProvider serviceProvider, ILogger<CancelDuplicationTaskJob> logger)
|
|
||||||
{
|
|
||||||
_serviceProvider = serviceProvider;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_logger.LogInformation("抵消任务开始处理");
|
|
||||||
|
|
||||||
using (var scope = _serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
var optionService = scope.ServiceProvider.GetService<ISqlSugarOptionsService>();
|
|
||||||
var db = scope.ServiceProvider.GetService<IDbContext>();
|
|
||||||
|
|
||||||
db.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
optionService.IgnoreTenant = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//人员下发任务相关
|
|
||||||
var taskTypes = new List<DeviceTaskEnumType>() { DeviceTaskEnumType.Add, DeviceTaskEnumType.Delete, DeviceTaskEnumType.Update };
|
|
||||||
|
|
||||||
var deviceTasks = await db.Queryable<DeviceTaskEntity>()
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)//没有被获取
|
|
||||||
.Where(x => taskTypes.Contains(x.Type))
|
|
||||||
.OrderBy(x => x.CreateTime, OrderByType.Desc)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var groupData = deviceTasks.GroupBy(x => new { x.TenantId, x.UserNo, x.DeviceUniqueNo });
|
|
||||||
foreach (var deviceTaskPack in groupData)
|
|
||||||
{
|
|
||||||
var uniqueInfo = deviceTaskPack.Key;
|
|
||||||
var data = deviceTaskPack.ToList();
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var item in data)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Expression<Func<DeviceTaskEntity, bool>> where = LinqExpressionExtension.False<DeviceTaskEntity>();
|
|
||||||
var ignoreData = new List<IdVersion>();
|
|
||||||
//最新一条更新人员信息
|
|
||||||
if (item.Type == DeviceTaskEnumType.Update && item.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
{
|
|
||||||
//获取过往的更新人员任务
|
|
||||||
ignoreData = data.Where(x => x.Type == DeviceTaskEnumType.Update)
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
.Where(x => x.Id != item.Id)
|
|
||||||
.Where(x => item.CreateTime > x.CreateTime)
|
|
||||||
.Select(x => new IdVersion { Id = x.Id, Version = x.Version }).ToList();
|
|
||||||
}
|
|
||||||
//最新一条删除人员信息
|
|
||||||
else if (item.Type == DeviceTaskEnumType.Delete && item.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
{
|
|
||||||
//存在成功下发的任务,此处可以直接把其他任务取消
|
|
||||||
if (await db.Queryable<DeviceTaskEntity>().Where(x => x.UserNo == item.UserNo)
|
|
||||||
.Where(x => x.DeviceUniqueNo == item.DeviceUniqueNo)
|
|
||||||
.Where(x => x.TenantId == item.TenantId).Where(x => x.Status == DeviceTaskStatusEnumType.Success).AnyAsync())
|
|
||||||
{
|
|
||||||
ignoreData.AddRange(data.Where(x => x.Type == DeviceTaskEnumType.Add
|
|
||||||
|| x.Type == DeviceTaskEnumType.Delete
|
|
||||||
|| x.Type == DeviceTaskEnumType.Update)
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
.Where(x => x.Id != item.Id)
|
|
||||||
.Where(x => item.CreateTime > x.CreateTime)
|
|
||||||
.Select(x => new IdVersion { Id = x.Id, Version = x.Version })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var currentIds = new List<long> { item.Id };
|
|
||||||
var beforeTask = data.Where(x => x.Type == DeviceTaskEnumType.Add || x.Type == DeviceTaskEnumType.Update)
|
|
||||||
.Where(x => !currentIds.Contains(x.Id))
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
.Where(x => item.CreateTime > x.CreateTime)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
//逻辑正确,最终beforeTask.type == DeviceTaskEnumType.Add
|
|
||||||
while (beforeTask != null && beforeTask.Type == DeviceTaskEnumType.Update)
|
|
||||||
{
|
|
||||||
ignoreData.Add(new IdVersion() { Id = beforeTask.Id, Version = beforeTask.Version });
|
|
||||||
currentIds.Add(beforeTask.Id);
|
|
||||||
|
|
||||||
beforeTask = data.Where(x => x.Type == DeviceTaskEnumType.Add || x.Type == DeviceTaskEnumType.Update)
|
|
||||||
.Where(x => !currentIds.Contains(x.Id))
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
.Where(x => item.CreateTime > x.CreateTime)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (beforeTask != null)
|
|
||||||
{
|
|
||||||
ignoreData.Add(new IdVersion() { Id = beforeTask.Id, Version = beforeTask.Version });
|
|
||||||
ignoreData.Add(new IdVersion() { Id = item.Id, Version = item.Version });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ignoreData.Any())
|
|
||||||
{
|
|
||||||
ignoreData.ForEach(p =>
|
|
||||||
{
|
|
||||||
where = where.Or(x => x.Id == p.Id && x.Version == p.Version && x.Status == DeviceTaskStatusEnumType.Wait);
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.Updateable<DeviceTaskEntity>()
|
|
||||||
.SetColumns(x => x.Version == x.Version + 1)
|
|
||||||
.SetColumns(x => x.Status == DeviceTaskStatusEnumType.Cancel)
|
|
||||||
.SetColumns(x => x.CancellationId == item.Id)
|
|
||||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
|
||||||
.Where(where)
|
|
||||||
.ExecuteCommandAsync();
|
|
||||||
|
|
||||||
data.ForEach(x =>
|
|
||||||
{
|
|
||||||
if (ignoreData.Any(p => p.Id == x.Id))
|
|
||||||
x.Status = DeviceTaskStatusEnumType.Cancel;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "抵消处理异常:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "抵消处理异常:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
db.Client.QueryFilter.Restore();
|
|
||||||
optionService.IgnoreTenant = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_logger.LogInformation("抵消任务处理完成");
|
|
||||||
}
|
|
||||||
|
|
||||||
class IdVersion
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
public int Version { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Dlhis.Entity.Common;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.CommonJobs;
|
|
||||||
|
|
||||||
public class DelApiLogTaskJob
|
|
||||||
{
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly ILogger<DelApiLogTaskJob> _logger;
|
|
||||||
|
|
||||||
public DelApiLogTaskJob(IDbContext dbContext, ILogger<DelApiLogTaskJob> logger)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DateTime before = DateTime.Now.Date.AddDays(-7);
|
|
||||||
await _dbContext.ChangeDb("log").Client.Deleteable<ApiLogEntity>().Where(x => x._ts <= before).ExecuteCommandAsync();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "删除日志异常:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Device.Entities;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.CommonJobs;
|
|
||||||
|
|
||||||
public class HeartbeatJob
|
|
||||||
{
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
|
|
||||||
public HeartbeatJob(IDbContext dbContext)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var devices = await _dbContext.Queryable<DeviceEntity>().Where(x => x.Enable).Where(x => x.HeartbeatInterval > 0).ToListAsync();
|
|
||||||
foreach (var device in devices)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ipInfo = JsonConvert.DeserializeObject<IPPortDto>(device.ConnectionInfo);
|
|
||||||
|
|
||||||
//超时时间
|
|
||||||
var CancellationTokenSource = new CancellationTokenSource(300);
|
|
||||||
await new TcpClient().ConnectAsync(IPAddress.Parse(ipInfo.IP), ipInfo.Port, CancellationTokenSource.Token);
|
|
||||||
|
|
||||||
await _dbContext.Updateable<DeviceRegistryEntity>().SetColumns(x => x.LastHeartbeatTime == DateTime.Now)
|
|
||||||
.Where(x => x.DeviceUniqueNo == device.UniqueNo).ExecuteCommandAsync();
|
|
||||||
|
|
||||||
// _logger.LogInformation("心跳设备成功:{no}", device.UniqueNo);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
//_logger.LogError(ex, "心跳设备失败:{no}. {message}", device.UniqueNo, ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Basic.Enums;
|
|
||||||
using Dlhis.Entity.Canteen.Entities;
|
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo;
|
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
|
||||||
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using SqlSugar;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.CommonJobs;
|
|
||||||
|
|
||||||
public class MealSupplementHandlerJob
|
|
||||||
{
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly ILogger<MealSupplementHandlerJob> _logger;
|
|
||||||
private readonly IJinkoJIPService _jinkoJIPService;
|
|
||||||
|
|
||||||
public MealSupplementHandlerJob(IDbContext dbContext, ILogger<MealSupplementHandlerJob> logger, IJinkoJIPService jinkoJIPService)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
_logger = logger;
|
|
||||||
_jinkoJIPService = jinkoJIPService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//查询待处理餐补
|
|
||||||
var mealSupplements = await _dbContext.Queryable<MealSupplementRecordEntity>()
|
|
||||||
.Where(x => (x.Status == MealSupplementStatusEnumtype.Wait || x.Status == MealSupplementStatusEnumtype.Error) && !x.Sync)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
foreach (var item in mealSupplements)
|
|
||||||
{
|
|
||||||
GainfoMealEntity mealUser = null;
|
|
||||||
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.Code).SingleAsync();
|
|
||||||
//档案不存在
|
|
||||||
if (gainfo == null)
|
|
||||||
{
|
|
||||||
//todo
|
|
||||||
//_logger.LogWarning("档案code:{code}不存在.flowno:{flowno}", item.Code, item.UniqueId);
|
|
||||||
//continue;
|
|
||||||
|
|
||||||
gainfo = new GainfoEntity() { No = Guid.NewGuid().ToString() };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
mealUser = await _dbContext.Queryable<GainfoMealEntity>().Where(x => x.UserNo == gainfo.No).SingleAsync();
|
|
||||||
if (mealUser == null)
|
|
||||||
{
|
|
||||||
mealUser = new GainfoMealEntity
|
|
||||||
{
|
|
||||||
Balance = 0,
|
|
||||||
BalanceOfRecharge = 0,
|
|
||||||
BalanceOfSubsidies = 0,
|
|
||||||
UserNo = gainfo.No,
|
|
||||||
UserCode = gainfo.Code,
|
|
||||||
Version = 0,
|
|
||||||
TenantId = gainfo.Factory,
|
|
||||||
};
|
|
||||||
|
|
||||||
await _dbContext.InsertAsync(mealUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
await SetMealSupplementAsync(mealUser, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetMealSupplementAsync(GainfoMealEntity mealUser, MealSupplementRecordEntity mealSupplement)
|
|
||||||
{
|
|
||||||
await _dbContext.Client.Ado.BeginTranAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await ContinueUpdateAsync(async () =>
|
|
||||||
{
|
|
||||||
mealUser = await _dbContext.Queryable<GainfoMealEntity>().Where(x => x.UserCode == mealUser.UserCode).FirstAsync();
|
|
||||||
var b = mealUser.Balance += mealSupplement.Amount;
|
|
||||||
|
|
||||||
var effect = await _dbContext.Updateable<GainfoMealEntity>()
|
|
||||||
.SetColumns(x => x.Balance == b)
|
|
||||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
|
||||||
.Where(x => x.UserCode == mealUser.UserCode && x.Version == mealUser.Version)
|
|
||||||
.ExecuteCommandAsync();
|
|
||||||
|
|
||||||
if (effect <= 0)
|
|
||||||
{
|
|
||||||
throw new VersionExceptions("餐补写入错误");
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 5);
|
|
||||||
|
|
||||||
await _dbContext.Updateable<MealSupplementRecordEntity>()
|
|
||||||
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Sucess)
|
|
||||||
.SetColumns(x => x.Sync == true)
|
|
||||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
|
||||||
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
|
||||||
.ExecuteCommandAsync();
|
|
||||||
|
|
||||||
var r = await _jinkoJIPService.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
UniqueId = mealSupplement.UniqueId,
|
|
||||||
Status = "SUCCESS",
|
|
||||||
Msg = "操作成功"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await _dbContext.Updateable<MealSupplementRecordEntity>()
|
|
||||||
.SetColumns(x => x.Result == r)
|
|
||||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
|
||||||
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
|
||||||
.ExecuteCommandAsync();
|
|
||||||
|
|
||||||
await _dbContext.Client.Ado.CommitTranAsync();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await _dbContext.Client.Ado.RollbackTranAsync();
|
|
||||||
|
|
||||||
await _dbContext.Updateable<MealSupplementRecordEntity>()
|
|
||||||
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Error)
|
|
||||||
.SetColumns(x => x.Result == ex.Message)
|
|
||||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
|
||||||
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
|
||||||
.ExecuteCommandAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ContinueUpdateAsync(Func<Task> func, int retry, string errorMessage = null)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < retry; i++)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await func();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Exception ex) when (ex is VersionExceptions)
|
|
||||||
{
|
|
||||||
_logger.LogWarning(ex, ex.Message);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UserFriendlyException(errorMessage ?? "操作失败,请重试");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Sys.Entities;
|
|
||||||
using Kurisu.AspNetCore.Utils.Extensions;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.CommonJobs;
|
|
||||||
|
|
||||||
public class UpdateUserPasswordJob
|
|
||||||
{
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly ILogger<UpdateUserPasswordJob> _logger;
|
|
||||||
|
|
||||||
public UpdateUserPasswordJob(
|
|
||||||
IDbContext dbContext,
|
|
||||||
ILogger<UpdateUserPasswordJob> logger)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
var identityDbContext = _dbContext.ChangeDb("identity");
|
|
||||||
|
|
||||||
var whitelist = new List<string>() { "admin", "WB-0741", "WB-1091", "0123456" };
|
|
||||||
|
|
||||||
var users = await identityDbContext.Queryable<UserEntity>()
|
|
||||||
.Where(x => !whitelist.Contains(x.UserName))
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var gainfos = await _dbContext.Queryable<GainfoEntity>().Where(x => !whitelist.Contains(x.Code)).ToListAsync();
|
|
||||||
|
|
||||||
var hasher = new PasswordHasher<UserEntity>();
|
|
||||||
foreach (var gainfo in gainfos)
|
|
||||||
{
|
|
||||||
if (gainfo.IdNo.IsPresent())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var password = gainfo.IdNo.TakeLast(6).Join("");
|
|
||||||
|
|
||||||
var user = users.FirstOrDefault(x => x.UserName == gainfo.Code);
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
user = new UserEntity
|
|
||||||
{
|
|
||||||
UserName = gainfo.Code,
|
|
||||||
NormalizedUserName = gainfo.Code.ToUpper(),
|
|
||||||
ConcurrencyStamp = Guid.NewGuid().ToString(),
|
|
||||||
SecurityStamp = Guid.NewGuid().ToString(),
|
|
||||||
};
|
|
||||||
password = hasher.HashPassword(user, password);
|
|
||||||
user.PasswordHash = password;
|
|
||||||
|
|
||||||
var id = (int)await identityDbContext.InsertReturnIdentityAsync(user);
|
|
||||||
await AddUserClaim(identityDbContext, id, "jinko-code", gainfo.Code);
|
|
||||||
await AddUserClaim(identityDbContext, id, "name", gainfo.Name);
|
|
||||||
if (!string.IsNullOrEmpty(gainfo.Factory))
|
|
||||||
{
|
|
||||||
var userTenant = await identityDbContext.Queryable<UserTenantEntity>().Where(x => x.UserId == user.Id).FirstAsync();
|
|
||||||
if (userTenant == null)
|
|
||||||
{
|
|
||||||
userTenant = new UserTenantEntity
|
|
||||||
{
|
|
||||||
UserId = user.Id,
|
|
||||||
TenantCode = gainfo.Factory
|
|
||||||
};
|
|
||||||
await identityDbContext.InsertAsync(userTenant);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
userTenant.TenantCode = gainfo.Factory;
|
|
||||||
await identityDbContext.UpdateAsync(userTenant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
password = hasher.HashPassword(user, password);
|
|
||||||
user.PasswordHash = password;
|
|
||||||
await identityDbContext.UpdateAsync(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "密码修改失败:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task AddUserClaim(IDbContext dbContext, int userId, string type, string value)
|
|
||||||
{
|
|
||||||
var claim = await dbContext.Queryable<UserClaimEntity>().Where(x => x.UserId == userId).FirstAsync(x => x.ClaimType == type);
|
|
||||||
if (claim == null)
|
|
||||||
{
|
|
||||||
claim = new UserClaimEntity()
|
|
||||||
{
|
|
||||||
UserId = userId,
|
|
||||||
ClaimType = type,
|
|
||||||
ClaimValue = value
|
|
||||||
};
|
|
||||||
await dbContext.InsertAsync(claim);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
claim.ClaimValue = value;
|
|
||||||
await dbContext.UpdateAsync(claim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,11 +21,11 @@
|
|||||||
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
|
||||||
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.3" />
|
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.3" />
|
||||||
<PackageReference Include="Kurisu.AspNetCore" Version="0.7.0" />
|
<PackageReference Include="Kurisu.AspNetCore" Version="0.7.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.4" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Dlhis.Basic.Api\Dlhis.Basic.Api.csproj" />
|
<ProjectReference Include="..\Dlhis.Basic.Api\Dlhis.Basic.Api.csproj" />
|
||||||
|
<ProjectReference Include="..\Dlhis.Canteen.Api\Dlhis.Canteen.Api.csproj" />
|
||||||
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
|
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
|
||||||
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
|
<ProjectReference Include="..\Dlhis.Sys.Api\Dlhis.Sys.Api.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
138
Src/Dlhis.ScheduledTask/Jobs/CancelDuplicationTaskJob.cs
Normal file
138
Src/Dlhis.ScheduledTask/Jobs/CancelDuplicationTaskJob.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
using Dlhis.Entity.Device.Entities;
|
||||||
|
using Dlhis.Entity.Device.Enums;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using SqlSugar;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理重复下发任务
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(CancelDuplicationTaskJob), "0/15 * * * * ?", Name = "处理重复下发任务")]
|
||||||
|
public class CancelDuplicationTaskJob : BaseJob
|
||||||
|
{
|
||||||
|
public CancelDuplicationTaskJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
//人员下发任务相关
|
||||||
|
var taskTypes = new List<DeviceTaskEnumType>() { DeviceTaskEnumType.Add, DeviceTaskEnumType.Delete, DeviceTaskEnumType.Update };
|
||||||
|
|
||||||
|
var deviceTasks = await DbContext.Queryable<DeviceTaskEntity>()
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)//没有被获取
|
||||||
|
.Where(x => taskTypes.Contains(x.Type))
|
||||||
|
.OrderBy(x => x.CreateTime, OrderByType.Desc)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var groupData = deviceTasks.GroupBy(x => new { x.TenantId, x.UserNo, x.DeviceUniqueNo });
|
||||||
|
foreach (var deviceTaskPack in groupData)
|
||||||
|
{
|
||||||
|
var uniqueInfo = deviceTaskPack.Key;
|
||||||
|
var data = deviceTaskPack.ToList();
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var item in data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Expression<Func<DeviceTaskEntity, bool>> where = LinqExpressionExtension.False<DeviceTaskEntity>();
|
||||||
|
var ignoreData = new List<IdVersion>();
|
||||||
|
//最新一条更新人员信息
|
||||||
|
if (item.Type == DeviceTaskEnumType.Update && item.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
{
|
||||||
|
//获取过往的更新人员任务
|
||||||
|
ignoreData = data.Where(x => x.Type == DeviceTaskEnumType.Update)
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
.Where(x => x.Id != item.Id)
|
||||||
|
.Where(x => item.CreateTime > x.CreateTime)
|
||||||
|
.Select(x => new IdVersion { Id = x.Id, Version = x.Version }).ToList();
|
||||||
|
}
|
||||||
|
//最新一条删除人员信息
|
||||||
|
else if (item.Type == DeviceTaskEnumType.Delete && item.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
{
|
||||||
|
//存在成功下发的任务,此处可以直接把其他任务取消
|
||||||
|
if (await DbContext.Queryable<DeviceTaskEntity>().Where(x => x.UserNo == item.UserNo)
|
||||||
|
.Where(x => x.DeviceUniqueNo == item.DeviceUniqueNo)
|
||||||
|
.Where(x => x.TenantId == item.TenantId).Where(x => x.Status == DeviceTaskStatusEnumType.Success).AnyAsync())
|
||||||
|
{
|
||||||
|
ignoreData.AddRange(data.Where(x => x.Type == DeviceTaskEnumType.Add
|
||||||
|
|| x.Type == DeviceTaskEnumType.Delete
|
||||||
|
|| x.Type == DeviceTaskEnumType.Update)
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
.Where(x => x.Id != item.Id)
|
||||||
|
.Where(x => item.CreateTime > x.CreateTime)
|
||||||
|
.Select(x => new IdVersion { Id = x.Id, Version = x.Version })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var currentIds = new List<long> { item.Id };
|
||||||
|
var beforeTask = data.Where(x => x.Type == DeviceTaskEnumType.Add || x.Type == DeviceTaskEnumType.Update)
|
||||||
|
.Where(x => !currentIds.Contains(x.Id))
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
.Where(x => item.CreateTime > x.CreateTime)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
//逻辑正确,最终beforeTask.type == DeviceTaskEnumType.Add
|
||||||
|
while (beforeTask != null && beforeTask.Type == DeviceTaskEnumType.Update)
|
||||||
|
{
|
||||||
|
ignoreData.Add(new IdVersion() { Id = beforeTask.Id, Version = beforeTask.Version });
|
||||||
|
currentIds.Add(beforeTask.Id);
|
||||||
|
|
||||||
|
beforeTask = data.Where(x => x.Type == DeviceTaskEnumType.Add || x.Type == DeviceTaskEnumType.Update)
|
||||||
|
.Where(x => !currentIds.Contains(x.Id))
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
.Where(x => item.CreateTime > x.CreateTime)
|
||||||
|
.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (beforeTask != null)
|
||||||
|
{
|
||||||
|
ignoreData.Add(new IdVersion() { Id = beforeTask.Id, Version = beforeTask.Version });
|
||||||
|
ignoreData.Add(new IdVersion() { Id = item.Id, Version = item.Version });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoreData.Any())
|
||||||
|
{
|
||||||
|
ignoreData.ForEach(p =>
|
||||||
|
{
|
||||||
|
where = where.Or(x => x.Id == p.Id && x.Version == p.Version && x.Status == DeviceTaskStatusEnumType.Wait);
|
||||||
|
});
|
||||||
|
|
||||||
|
await DbContext.Updateable<DeviceTaskEntity>()
|
||||||
|
.SetColumns(x => x.Version == x.Version + 1)
|
||||||
|
.SetColumns(x => x.Status == DeviceTaskStatusEnumType.Cancel)
|
||||||
|
.SetColumns(x => x.CancellationId == item.Id)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(where)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
|
data.ForEach(x =>
|
||||||
|
{
|
||||||
|
if (ignoreData.Any(p => p.Id == x.Id))
|
||||||
|
x.Status = DeviceTaskStatusEnumType.Cancel;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "抵消处理异常:{message}", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IdVersion
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
public int Version { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -5,74 +5,62 @@ using Dlhis.Sys.Api;
|
|||||||
using Dlhis.Sys.Api.Response;
|
using Dlhis.Sys.Api.Response;
|
||||||
using Kurisu.AspNetCore.Utils.Extensions;
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
using Kurisu.Core.DataAccess.Entity;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
using Kurisu.SqlSugar.Services;
|
using Kurisu.SqlSugar.Services;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.CommonJobs;
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
public class CreateDefinitelyGroupJob
|
/// <summary>
|
||||||
|
/// 创建系统默认分组
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(CreateDefinitelyGroupJob), "0 0 5 * * ?", Name = "创建系统默认分组")]
|
||||||
|
public class CreateDefinitelyGroupJob : BaseJob
|
||||||
{
|
{
|
||||||
private readonly ILogger<CreateDefinitelyGroupJob> _logger;
|
|
||||||
private readonly ITenantApi _tenantApi;
|
private readonly ITenantApi _tenantApi;
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
|
|
||||||
public CreateDefinitelyGroupJob(ILogger<CreateDefinitelyGroupJob> logger,
|
public CreateDefinitelyGroupJob(
|
||||||
ITenantApi tenantApi,
|
ITenantApi tenantApi,
|
||||||
IDbContext dbContext,
|
IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
ISqlSugarOptionsService sqlSugarOptionsService)
|
|
||||||
{
|
{
|
||||||
_logger = logger;
|
|
||||||
_tenantApi = tenantApi;
|
_tenantApi = tenantApi;
|
||||||
_dbContext = dbContext;
|
|
||||||
|
|
||||||
sqlSugarOptionsService.IgnoreTenant = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string _remark = "系统自动生成";
|
private static readonly string _remark = "系统自动生成";
|
||||||
|
|
||||||
public async Task RunAsync()
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
//获取所有基地信息
|
||||||
try
|
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
|
||||||
{
|
var tenants = tenantResult.Data;
|
||||||
//获取所有基地信息
|
|
||||||
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
|
|
||||||
var tenants = tenantResult.Data;
|
|
||||||
|
|
||||||
_logger.LogInformation("获取基地信息:{json}", JsonConvert.SerializeObject(tenants));
|
Logger.LogInformation("获取基地信息:{json}", JsonConvert.SerializeObject(tenants));
|
||||||
|
|
||||||
//****************************************************系统人员分组**********************************************************/
|
//****************************************************系统人员分组**********************************************************/
|
||||||
|
|
||||||
await CreateGainfoGroupsAsync(tenants);
|
await CreateGainfoGroupsAsync(tenants);
|
||||||
|
|
||||||
//*****************************************************考勤设备组*********************************************************/
|
//*****************************************************考勤设备组*********************************************************/
|
||||||
|
|
||||||
await CreateDeviceGroupAsync(DeviceTypeEnumType.Attendance, new List<string> { "*通用考勤设备组", "*专用考勤设备组" }, tenants);
|
await CreateDeviceGroupAsync(DeviceTypeEnumType.Attendance, new List<string> { "*通用考勤设备组", "*专用考勤设备组" }, tenants);
|
||||||
|
|
||||||
//*****************************************************门禁设备组********************************************************/
|
//*****************************************************门禁设备组********************************************************/
|
||||||
|
|
||||||
|
await CreateDeviceGroupAsync(DeviceTypeEnumType.Door, new List<string> { "*共用区域", "*非共用区域" }, tenants);
|
||||||
|
|
||||||
await CreateDeviceGroupAsync(DeviceTypeEnumType.Door, new List<string> { "*共用区域", "*非共用区域" }, tenants);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "自动创建系统分组失败:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CreateGainfoGroupsAsync(List<TenantResponse> tenants)
|
private async Task CreateGainfoGroupsAsync(List<TenantResponse> tenants)
|
||||||
{
|
{
|
||||||
var grps = new List<string> { "*自定义人员分组", "*督查组", "*X3及以上领导组" };
|
var grps = new List<string> { "*自定义人员分组", "*督查组", "*X3及以上领导组" };
|
||||||
var searchGrps = await _dbContext.Queryable<GainfoGroupEntity>().Where(x => grps.Contains(x.Name)).ToListAsync();
|
var searchGrps = await DbContext.Queryable<GainfoGroupEntity>().Where(x => grps.Contains(x.Name)).ToListAsync();
|
||||||
foreach (var grp in grps)
|
foreach (var grp in grps)
|
||||||
{
|
{
|
||||||
if (!searchGrps.Any(x => x.Name == grp))
|
if (!searchGrps.Any(x => x.Name == grp))
|
||||||
{
|
{
|
||||||
await _dbContext.InsertAsync(new GainfoGroupEntity
|
await DbContext.InsertAsync(new GainfoGroupEntity
|
||||||
{
|
{
|
||||||
PCode = null,
|
PCode = null,
|
||||||
Code = Guid.NewGuid(),
|
Code = Guid.NewGuid(),
|
||||||
@@ -96,7 +84,7 @@ public class CreateDefinitelyGroupJob
|
|||||||
{
|
{
|
||||||
foreach (var grp in topGroups)
|
foreach (var grp in topGroups)
|
||||||
{
|
{
|
||||||
var topGrp = await _dbContext.Queryable<DeviceGroupEntity>().FirstAsync(x => x.Name == grp);
|
var topGrp = await DbContext.Queryable<DeviceGroupEntity>().FirstAsync(x => x.Name == grp);
|
||||||
if (topGrp == null)
|
if (topGrp == null)
|
||||||
{
|
{
|
||||||
topGrp = new DeviceGroupEntity
|
topGrp = new DeviceGroupEntity
|
||||||
@@ -115,13 +103,13 @@ public class CreateDefinitelyGroupJob
|
|||||||
ModifiedTime = DateTime.Now,
|
ModifiedTime = DateTime.Now,
|
||||||
TenantId = null,
|
TenantId = null,
|
||||||
};
|
};
|
||||||
await _dbContext.InsertAsync(topGrp);
|
await DbContext.InsertAsync(topGrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var workplace in tenants.Where(x => x.PCode.IsEmpty()))
|
foreach (var workplace in tenants.Where(x => x.PCode.IsEmpty()))
|
||||||
{
|
{
|
||||||
var workplaceName = $"*{type.GetDescription()}工作地系统组({workplace.Name})";
|
var workplaceName = $"*{type.GetDescription()}工作地系统组({workplace.Name})";
|
||||||
var workplaceGrp = await _dbContext.Queryable<DeviceGroupEntity>().Where(x => x.PCode == topGrp.Code).FirstAsync(x => x.Name == workplaceName);
|
var workplaceGrp = await DbContext.Queryable<DeviceGroupEntity>().Where(x => x.PCode == topGrp.Code).FirstAsync(x => x.Name == workplaceName);
|
||||||
if (workplaceGrp == null)
|
if (workplaceGrp == null)
|
||||||
{
|
{
|
||||||
workplaceGrp = new DeviceGroupEntity
|
workplaceGrp = new DeviceGroupEntity
|
||||||
@@ -140,15 +128,15 @@ public class CreateDefinitelyGroupJob
|
|||||||
ModifiedTime = DateTime.Now,
|
ModifiedTime = DateTime.Now,
|
||||||
TenantId = null,
|
TenantId = null,
|
||||||
};
|
};
|
||||||
await _dbContext.InsertAsync(workplaceGrp);
|
await DbContext.InsertAsync(workplaceGrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var factory in tenants.Where(x => x.PCode == workplace.Code))
|
foreach (var factory in tenants.Where(x => x.PCode == workplace.Code))
|
||||||
{
|
{
|
||||||
var factoryName = $"*{type.GetDescription()}厂区系统组({factory.Name})";
|
var factoryName = $"*{type.GetDescription()}厂区系统组({factory.Name})";
|
||||||
if (!await _dbContext.Queryable<DeviceGroupEntity>().Where(x => x.PCode == workplaceGrp.Code).AnyAsync(x => x.Name == factoryName))
|
if (!await DbContext.Queryable<DeviceGroupEntity>().Where(x => x.PCode == workplaceGrp.Code).AnyAsync(x => x.Name == factoryName))
|
||||||
{
|
{
|
||||||
await _dbContext.InsertAsync(new DeviceGroupEntity
|
await DbContext.InsertAsync(new DeviceGroupEntity
|
||||||
{
|
{
|
||||||
PCode = workplaceGrp.Code,
|
PCode = workplaceGrp.Code,
|
||||||
Code = Guid.NewGuid(),
|
Code = Guid.NewGuid(),
|
||||||
53
Src/Dlhis.ScheduledTask/Jobs/CreateGetUploadRecordJob.cs
Normal file
53
Src/Dlhis.ScheduledTask/Jobs/CreateGetUploadRecordJob.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Device.Entities;
|
||||||
|
using Dlhis.Entity.Device.Enums;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建上传设备数据任务
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(CreateGetUploadRecordJob), "0 0/1 * * * ?", Name = "创建上传设备数据任务")]
|
||||||
|
public class CreateGetUploadRecordJob : BaseJob
|
||||||
|
{
|
||||||
|
|
||||||
|
public CreateGetUploadRecordJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
var devices = await DbContext.Queryable<DeviceEntity>()
|
||||||
|
.Where(x => x.Enable)
|
||||||
|
.Where(x => x.Type == DeviceTypeEnumType.Attendance || x.Type == DeviceTypeEnumType.Door)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
//过滤处理中的任务
|
||||||
|
var currentUniqueNos = await DbContext.Queryable<DeviceTaskEntity>()
|
||||||
|
.Where(x => x.Type == DeviceTaskEnumType.UploadRecord)
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Process || x.Status == DeviceTaskStatusEnumType.Wait)
|
||||||
|
.Select(x => x.DeviceUniqueNo)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var tasks = devices.Where(x => !currentUniqueNos.Contains(x.UniqueNo)).Select(x => new DeviceTaskEntity
|
||||||
|
{
|
||||||
|
DeviceUniqueNo = x.UniqueNo,
|
||||||
|
Status = DeviceTaskStatusEnumType.Wait,
|
||||||
|
|
||||||
|
TenantId = x.TenantId,
|
||||||
|
Version = 0,
|
||||||
|
Type = DeviceTaskEnumType.UploadRecord,
|
||||||
|
|
||||||
|
CreatedBy = 1,
|
||||||
|
CreateTime = DateTime.Now,
|
||||||
|
ModifiedBy = 1,
|
||||||
|
ModifiedTime = DateTime.Now,
|
||||||
|
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
await DbContext.InsertAsync(tasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
Src/Dlhis.ScheduledTask/Jobs/CreateSyncServerDateTimeJob.cs
Normal file
54
Src/Dlhis.ScheduledTask/Jobs/CreateSyncServerDateTimeJob.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Device.Entities;
|
||||||
|
using Dlhis.Entity.Device.Enums;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备时间同步
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(CreateSyncServerDateTimeJob), "0 0 0/1 * * ?", Name = "设备时间同步")]
|
||||||
|
public class CreateSyncServerDateTimeJob : BaseJob
|
||||||
|
{
|
||||||
|
|
||||||
|
public CreateSyncServerDateTimeJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
var deviceUniqueNos = await DbContext.Queryable<DeviceTaskEntity>()
|
||||||
|
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait || x.Status == DeviceTaskStatusEnumType.Process)
|
||||||
|
.Where(x => x.Type == DeviceTaskEnumType.SyncDateTime)
|
||||||
|
.Select(x => x.DeviceUniqueNo)
|
||||||
|
.Distinct()
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var devices = await DbContext.Queryable<DeviceEntity>()
|
||||||
|
.Where(x => !deviceUniqueNos.Contains(x.UniqueNo))
|
||||||
|
.Where(x => x.Enable)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var tasks = devices.Select(x => new DeviceTaskEntity
|
||||||
|
{
|
||||||
|
DeviceUniqueNo = x.UniqueNo,
|
||||||
|
Status = DeviceTaskStatusEnumType.Wait,
|
||||||
|
|
||||||
|
TenantId = x.TenantId,
|
||||||
|
Version = 0,
|
||||||
|
UserNo = string.Empty,
|
||||||
|
Type = DeviceTaskEnumType.SyncDateTime,
|
||||||
|
|
||||||
|
CreatedBy = 1,
|
||||||
|
CreateTime = DateTime.Now,
|
||||||
|
ModifiedBy = 1,
|
||||||
|
ModifiedTime = DateTime.Now,
|
||||||
|
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
await DbContext.InsertAsync(tasks);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Src/Dlhis.ScheduledTask/Jobs/DeleteApiLogTaskJob.cs
Normal file
25
Src/Dlhis.ScheduledTask/Jobs/DeleteApiLogTaskJob.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Dlhis.Entity.Common;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除过期日志
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(DeleteApiLogTaskJob), "0 0 0 */6 * ?", Name = "删除过期日志")]
|
||||||
|
public class DeleteApiLogTaskJob : BaseJob
|
||||||
|
{
|
||||||
|
|
||||||
|
public DeleteApiLogTaskJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
var before = DateTime.Now.Date.AddDays(-7);
|
||||||
|
await DbContext.ChangeDb("log").Client.Deleteable<ApiLogEntity>().Where(x => x._ts <= before).ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
42
Src/Dlhis.ScheduledTask/Jobs/HeartbeatJob.cs
Normal file
42
Src/Dlhis.ScheduledTask/Jobs/HeartbeatJob.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Device.Entities;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设备心跳
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(HeartbeatJob), "0/10 * * * * ?", Name = "设备心跳")]
|
||||||
|
public class HeartbeatJob : BaseJob
|
||||||
|
{
|
||||||
|
public HeartbeatJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
var devices = await DbContext.Queryable<DeviceEntity>().Where(x => x.Enable).Where(x => x.HeartbeatInterval > 0).ToListAsync();
|
||||||
|
foreach (var device in devices)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var ipInfo = JsonConvert.DeserializeObject<IPPortDto>(device.ConnectionInfo);
|
||||||
|
|
||||||
|
//超时时间
|
||||||
|
var CancellationTokenSource = new CancellationTokenSource(300);
|
||||||
|
await new TcpClient().ConnectAsync(IPAddress.Parse(ipInfo.IP), ipInfo.Port, CancellationTokenSource.Token);
|
||||||
|
|
||||||
|
await DbContext.Updateable<DeviceRegistryEntity>().SetColumns(x => x.LastHeartbeatTime == DateTime.Now)
|
||||||
|
.Where(x => x.DeviceUniqueNo == device.UniqueNo).ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
224
Src/Dlhis.ScheduledTask/Jobs/MealSupplementHandlerJob.cs
Normal file
224
Src/Dlhis.ScheduledTask/Jobs/MealSupplementHandlerJob.cs
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
using Dlhis.Canteen.Api;
|
||||||
|
using Dlhis.Canteen.Api.Request;
|
||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Basic.Enums;
|
||||||
|
using Dlhis.Entity.Canteen.Entities;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
|
using Kurisu.AspNetCore.UnifyResultAndValidation;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 餐补核算
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(MealSupplementHandlerJob), "0 0/30 * * * ?", Name = "餐补核算")]
|
||||||
|
public class MealSupplementHandlerJob : BaseJob
|
||||||
|
{
|
||||||
|
private readonly IHainingMealSupplementApi _hainingMealSupplementApi;
|
||||||
|
private readonly IJinkoJIPService _jinkoJIPService;
|
||||||
|
|
||||||
|
public MealSupplementHandlerJob(IServiceProvider serviceProvider, IHainingMealSupplementApi hainingMealSupplementApi, IJinkoJIPService jinkoJIPService) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
_hainingMealSupplementApi = hainingMealSupplementApi;
|
||||||
|
_jinkoJIPService = jinkoJIPService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
//查询待处理餐补
|
||||||
|
var mealSupplements = await DbContext.Queryable<MealSupplementRecordEntity>()
|
||||||
|
.Where(x => (x.Status == MealSupplementStatusEnumtype.Wait || x.Status == MealSupplementStatusEnumtype.Error) && !x.Sync)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
foreach (var item in mealSupplements)
|
||||||
|
{
|
||||||
|
GainfoMealEntity mealUser = null;
|
||||||
|
var gainfo = await DbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.Code).SingleAsync();
|
||||||
|
//档案不存在
|
||||||
|
if (gainfo == null)
|
||||||
|
{
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Error)
|
||||||
|
.SetColumns(x => x.Result == "人员档案不存在")
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == item.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//创建余额数据
|
||||||
|
mealUser = await DbContext.Queryable<GainfoMealEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync();
|
||||||
|
if (mealUser == null)
|
||||||
|
{
|
||||||
|
mealUser = new GainfoMealEntity
|
||||||
|
{
|
||||||
|
Balance = 0,
|
||||||
|
BalanceOfRecharge = 0,
|
||||||
|
BalanceOfSubsidies = 0,
|
||||||
|
UserNo = gainfo.No,
|
||||||
|
UserCode = gainfo.Code,
|
||||||
|
Version = 0,
|
||||||
|
TenantId = gainfo.Factory,
|
||||||
|
};
|
||||||
|
|
||||||
|
await DbContext.InsertAsync(mealUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.Workplace == "5")
|
||||||
|
{
|
||||||
|
await SetHainingMealSupplementAsync(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await SetMealSupplementAsync(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SetMealSupplementAsync(MealSupplementRecordEntity mealSupplement)
|
||||||
|
{
|
||||||
|
await DbContext.Client.Ado.BeginTranAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ContinueUpdateAsync(async () =>
|
||||||
|
{
|
||||||
|
var mealUser = await DbContext.Queryable<GainfoMealEntity>().Where(x => x.UserCode == mealSupplement.Code).FirstAsync();
|
||||||
|
var b = mealUser.Balance += mealSupplement.Amount;
|
||||||
|
|
||||||
|
var effect = await DbContext.Updateable<GainfoMealEntity>()
|
||||||
|
.SetColumns(x => x.Balance == b)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UserCode == mealUser.UserCode && x.Version == mealUser.Version)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
|
if (effect <= 0)
|
||||||
|
{
|
||||||
|
throw new VersionExceptions("餐补写入错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 5);
|
||||||
|
|
||||||
|
//更新餐补信息为成功(同步成功)
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Sucess)
|
||||||
|
.SetColumns(x => x.Sync == true)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
|
var r = await _jinkoJIPService.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
UniqueId = mealSupplement.UniqueId,
|
||||||
|
Status = "SUCCESS",
|
||||||
|
Msg = "操作成功"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Result == r)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
|
await DbContext.Client.Ado.CommitTranAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await DbContext.Client.Ado.RollbackTranAsync();
|
||||||
|
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Error)
|
||||||
|
.SetColumns(x => x.Result == ex.Message)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task SetHainingMealSupplementAsync(MealSupplementRecordEntity mealSupplement)
|
||||||
|
{
|
||||||
|
await DbContext.Client.Ado.BeginTranAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var hnResponse = await _hainingMealSupplementApi.AddMealSupplementAsync(new AddHainingMealSupplementRequest
|
||||||
|
{
|
||||||
|
Code = mealSupplement.Code,
|
||||||
|
Amount = mealSupplement.Amount,
|
||||||
|
Date = mealSupplement.Date,
|
||||||
|
Remark = mealSupplement.Remark,
|
||||||
|
UniqueId = mealSupplement.UniqueId,
|
||||||
|
});
|
||||||
|
|
||||||
|
(hnResponse == null || hnResponse.Code != 200).ThrowIfTrue("海宁餐补写入失败:" + hnResponse?.Message);
|
||||||
|
|
||||||
|
//更新餐补信息为成功(同步成功)
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Sucess)
|
||||||
|
.SetColumns(x => x.Sync == true)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
|
var r = await _jinkoJIPService.SyncMealSupplementRecordsAsync(new List<SyncMealSupplementRecordRequest>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
UniqueId = mealSupplement.UniqueId,
|
||||||
|
Status = "SUCCESS",
|
||||||
|
Msg = "操作成功"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Result == r)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
|
||||||
|
await DbContext.Client.Ado.CommitTranAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await DbContext.Client.Ado.RollbackTranAsync();
|
||||||
|
|
||||||
|
await DbContext.Updateable<MealSupplementRecordEntity>()
|
||||||
|
.SetColumns(x => x.Status == MealSupplementStatusEnumtype.Error)
|
||||||
|
.SetColumns(x => x.Result == ex.Message)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => x.UniqueId == mealSupplement.UniqueId)
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ContinueUpdateAsync(Func<Task> func, int retry, string errorMessage = null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < retry; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await func();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is VersionExceptions)
|
||||||
|
{
|
||||||
|
Logger.LogWarning(ex, ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UserFriendlyException(errorMessage ?? "操作失败,请重试");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,25 +2,25 @@
|
|||||||
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
using Kurisu.SqlSugar.Services;
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 部门同步定时任务
|
/// SAP组织架构数据同步
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SyncOrganizationJob
|
[RecurringJob(nameof(SyncOrganizationJob), "0 0 0 * * ?", Name = "SAP组织架构数据同步", Queue = "SAP")]
|
||||||
|
public class SyncOrganizationJob : BaseJob
|
||||||
{
|
{
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly IJinkoSapService _jinkoSapService;
|
private readonly IJinkoSapService _jinkoSapService;
|
||||||
|
|
||||||
public SyncOrganizationJob(IDbContext dbContext, IJinkoSapService jinkoSapService)
|
public SyncOrganizationJob(IServiceProvider serviceProvider, IJinkoSapService jinkoSapService) : base(serviceProvider)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
|
||||||
_jinkoSapService = jinkoSapService;
|
_jinkoSapService = jinkoSapService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunAsync()
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
var orgResult = await _jinkoSapService.GetSapOrganizationsAsync();
|
var orgResult = await _jinkoSapService.GetSapOrganizationsAsync();
|
||||||
|
|
||||||
@@ -28,16 +28,13 @@ public class SyncOrganizationJob
|
|||||||
{
|
{
|
||||||
await SaveOrg(orgResult.Org.Items);
|
await SaveOrg(orgResult.Org.Items);
|
||||||
}
|
}
|
||||||
|
|
||||||
var syncPositionJob = BackgroundJob.Enqueue<SyncPositionJob>(job => job.RunAsync());
|
|
||||||
BackgroundJob.ContinueJobWith<SyncPersonJob>(syncPositionJob, job => job.RunAsync(), JobContinuationOptions.OnlyOnSucceededState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveOrg(List<SapOrganizationItem> modifiedOrgList)
|
private async Task SaveOrg(List<SapOrganizationItem> modifiedOrgList)
|
||||||
{
|
{
|
||||||
foreach (SapOrganizationItem item in modifiedOrgList)
|
foreach (SapOrganizationItem item in modifiedOrgList)
|
||||||
{
|
{
|
||||||
var department = await _dbContext.Queryable<DepartmentEntity>().Where(x => x.No == item.OBJID).FirstAsync();
|
var department = await DbContext.Queryable<DepartmentEntity>().Where(x => x.No == item.OBJID).FirstAsync();
|
||||||
if (department == null)
|
if (department == null)
|
||||||
{
|
{
|
||||||
department = new DepartmentEntity
|
department = new DepartmentEntity
|
||||||
@@ -47,14 +44,14 @@ public class SyncOrganizationJob
|
|||||||
PNo = item.SOBID,
|
PNo = item.SOBID,
|
||||||
};
|
};
|
||||||
|
|
||||||
await _dbContext.InsertAsync(department);
|
await DbContext.InsertAsync(department);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
department.PNo = item.SOBID;
|
department.PNo = item.SOBID;
|
||||||
department.Name = item.STEXT;
|
department.Name = item.STEXT;
|
||||||
|
|
||||||
await _dbContext.UpdateAsync(department);
|
await DbContext.UpdateAsync(department);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
74
Src/Dlhis.ScheduledTask/Jobs/SyncOriginCardInfoJob.cs
Normal file
74
Src/Dlhis.ScheduledTask/Jobs/SyncOriginCardInfoJob.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Device.Entities;
|
||||||
|
using Dlhis.Entity.Device.Enums;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo;
|
||||||
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using Kurisu.SqlSugar.Services;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传考勤记录
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(SyncOriginCardInfoJob), "0/20 * * * * ?", Name = "上传考勤记录", Queue = "SAP")]
|
||||||
|
public class SyncOriginCardInfoJob : BaseJob
|
||||||
|
{
|
||||||
|
private readonly IJinkoJIPService _jinkoJIPService;
|
||||||
|
private readonly ISqlSugarOptionsService _sqlSugarOptionsService;
|
||||||
|
|
||||||
|
public SyncOriginCardInfoJob(IJinkoJIPService jinkoJIPService, IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
_jinkoJIPService = jinkoJIPService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
//考勤设备(不需要Enable参数)
|
||||||
|
var devices = await DbContext.Queryable<DeviceEntity>()
|
||||||
|
.Where(x => x.Type == DeviceTypeEnumType.Attendance || x.Type == DeviceTypeEnumType.Door && x.AsAttendance)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
//获取上传日志(有效的)
|
||||||
|
var deviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
|
||||||
|
var logs = await DbContext.Queryable<DeviceUploadLogEntity>()
|
||||||
|
.Where(x => deviceUniqueNos.Contains(x.DeviceUniqueNo))
|
||||||
|
.Where(x => !string.IsNullOrEmpty(x.UserUniqueNo))
|
||||||
|
.Where(x => x.Sync == false)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
//获取人员信息
|
||||||
|
var userCodes = logs.Select(x => x.UserUniqueNo).ToList();
|
||||||
|
var gainfoCodes = await DbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => x.Code).ToListAsync();
|
||||||
|
|
||||||
|
var requests = logs.Select(x => new UploadAttendanceRequest
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
RaiseDateTime = x.RaiseDateTime,
|
||||||
|
ZNOTE = devices.First(item => item.UniqueNo == x.DeviceUniqueNo).DeployPlace,
|
||||||
|
ZWORKCODE = gainfoCodes.Contains(x.UserUniqueNo) ? x.UserUniqueNo?.TrimEnd('\0') : string.Empty,
|
||||||
|
|
||||||
|
}).Where(x => x.ZWORKCODE.IsPresent()).ToList();
|
||||||
|
|
||||||
|
var ids = requests.Select(x => x.Id).ToList();
|
||||||
|
if (ids.Any())
|
||||||
|
{
|
||||||
|
var r = await _jinkoJIPService.UploadAttendancesAsync(requests);
|
||||||
|
if (r.OLX == "0")
|
||||||
|
{
|
||||||
|
await DbContext.Updateable<DeviceUploadLogEntity>()
|
||||||
|
.SetColumns(x => x.Sync == true)
|
||||||
|
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
||||||
|
.Where(x => ids.Contains(x.Id))
|
||||||
|
.ExecuteCommandAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception(r.OMS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,156 +1,147 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using Dlhis.Entity.Basic.Entity;
|
using Dlhis.Entity.Basic.Entity;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
using Dlhis.ScheduledTask.SyncSapInfo.Comparers;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
using Kurisu.AspNetCore.Scope;
|
|
||||||
using Dlhis.Entity.Basic.Enums;
|
using Dlhis.Entity.Basic.Enums;
|
||||||
using Dlhis.Sys.Api;
|
using Dlhis.Sys.Api;
|
||||||
using Dlhis.Sys.Api.Response;
|
using Dlhis.Sys.Api.Response;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using Dlhis.Basic.Api;
|
using Dlhis.Basic.Api;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
public class SyncPersonJob
|
/// <summary>
|
||||||
|
/// SAP人员信息同步
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(SyncPersonJob), "0 0 1-4 * * ?", Name = "SAP人员信息同步", Queue = "SAP")]
|
||||||
|
public class SyncPersonJob : BaseJob
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
|
||||||
private readonly IJinkoSapService _jinkoSapService;
|
private readonly IJinkoSapService _jinkoSapService;
|
||||||
private readonly ITenantApi _tenantApi;
|
private readonly ITenantApi _tenantApi;
|
||||||
private readonly IDevicePermissionApi _devicePermissionApi;
|
private readonly IDevicePermissionApi _devicePermissionApi;
|
||||||
private List<PositionEntity> _positions;
|
|
||||||
private List<TenantResponse> _tenants;
|
private List<TenantResponse> _tenants;
|
||||||
private List<SapPersonDepartmentStatus> _departmentChanges;
|
private List<SapPersonDepartmentStatus> _departmentChanges;
|
||||||
private List<SapPersonJobStatus> _jobChanges;
|
private List<SapPersonJobStatus> _jobChanges;
|
||||||
|
|
||||||
public SyncPersonJob(ILogger<SyncPersonJob> logger, IJinkoSapService jinkoSapService,
|
public SyncPersonJob(
|
||||||
ITenantApi tenantApi, IDevicePermissionApi devicePermissionApi)
|
IJinkoSapService jinkoSapService,
|
||||||
|
ITenantApi tenantApi,
|
||||||
|
IServiceProvider serviceProvider,
|
||||||
|
IDevicePermissionApi devicePermissionApi) : base(serviceProvider)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
|
||||||
_jinkoSapService = jinkoSapService;
|
_jinkoSapService = jinkoSapService;
|
||||||
_tenantApi = tenantApi;
|
_tenantApi = tenantApi;
|
||||||
_devicePermissionApi = devicePermissionApi;
|
_devicePermissionApi = devicePermissionApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunAsync()
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("开始获取SAP人员");
|
Logger.LogWarning("开始获取SAP人员");
|
||||||
|
DbContext.Client.QueryFilter.ClearAndBackup();
|
||||||
|
|
||||||
var personResp = await _jinkoSapService.GetPersonsAsync();
|
var personResp = await _jinkoSapService.GetPersonsAsync();
|
||||||
var persons = personResp.Person.Items;
|
var persons = personResp.Person.Items;
|
||||||
_departmentChanges = personResp.DepartmentInfo.Items;
|
_departmentChanges = personResp.DepartmentInfo.Items;
|
||||||
_jobChanges = personResp.JobStatusInfo.Items;
|
_jobChanges = personResp.JobStatusInfo.Items;
|
||||||
|
|
||||||
_logger.LogInformation("获取SAP人员数量为:{count}", persons.Count);
|
Logger.LogWarning("获取SAP人员数量为:{count}", persons.Count);
|
||||||
if (persons.Count > 0)
|
if (persons.Count > 0)
|
||||||
{
|
{
|
||||||
Scoped.Temp.Value.Create(sp =>
|
var modifiedPersons = GetModifiedPerson(persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
|
||||||
|
Logger.LogWarning("SAP人员差异数量为:{count}", modifiedPersons.Count);
|
||||||
|
if (modifiedPersons.Count > 0)
|
||||||
{
|
{
|
||||||
var dbContext = sp.GetService<IDbContext>();
|
await SavePersonAsync(modifiedPersons);
|
||||||
_positions = dbContext.Queryable<PositionEntity>().ToList();
|
}
|
||||||
var modifiedPersons = GetModifiedPerson(dbContext, persons.OrderByDescending(x => x.ZSTATUS).ThenBy(x => x.ZRZRQ).ToList());
|
|
||||||
_logger.LogInformation("SAP人员差异数量为:{count}", modifiedPersons.Count);
|
|
||||||
if (modifiedPersons.Count > 0)
|
|
||||||
{
|
|
||||||
var failedRecords = SavePerson(modifiedPersons);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("同步SAP人员数据结束");
|
Logger.LogWarning("同步SAP人员数据结束");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<int> SavePerson(List<SapPersonItem> persons)
|
private async Task SavePersonAsync(List<SapPersonItem> persons)
|
||||||
{
|
{
|
||||||
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
|
var tenantResult = await _tenantApi.GetTenantsInternalAsync();
|
||||||
_tenants = tenantResult.Data;
|
_tenants = tenantResult.Data;
|
||||||
|
|
||||||
var failure = 0;
|
|
||||||
var workCodes = persons.Select(x => x.ZWORKCODE).ToList();
|
var workCodes = persons.Select(x => x.ZWORKCODE).ToList();
|
||||||
var chunks = workCodes.Chunk(4000).ToList();
|
var chunks = workCodes.Chunk(4000).ToList();
|
||||||
|
|
||||||
var dtoResult = await _devicePermissionApi.GetPermissionUsersInfoAsync();
|
var dtoResult = await _devicePermissionApi.GetPermissionUsersInfoAsync();
|
||||||
var dto = dtoResult.Data;
|
var dto = dtoResult.Data;
|
||||||
|
|
||||||
Scoped.Temp.Value.Create(sp =>
|
foreach (var searchCodes in chunks)
|
||||||
{
|
{
|
||||||
var dbContext = sp.GetService<IDbContext>();
|
Logger.LogWarning("SAP分批处理Chunk数量:{count}", searchCodes.Length);
|
||||||
|
var existsWorkCodes = DbContext.Queryable<GainfoSapEntity>()
|
||||||
|
.Where(x => searchCodes.Contains(x.ename))
|
||||||
|
.Select(x => x.ename)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var searchCodes in chunks)
|
var originUpdates = persons.Where(x => existsWorkCodes.Contains(x.ZWORKCODE)).ToList();
|
||||||
|
var existsUpdateWorkCodes = originUpdates.Select(x => x.ZWORKCODE).ToList();
|
||||||
|
var originInserts = persons.Where(x => searchCodes.Contains(x.ZWORKCODE)).Where(x => !existsUpdateWorkCodes.Contains(x.ZWORKCODE)).ToList();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
var updates = ToGainfoSap(originUpdates);
|
||||||
|
Logger.LogWarning("SAP分批更新数:{count}", updates.Count);
|
||||||
|
var inserts = ToGainfoSap(originInserts);
|
||||||
|
Logger.LogWarning("SAP分批新增数:{count}", inserts.Count);
|
||||||
|
|
||||||
|
foreach (var item in inserts)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("SAP分批处理Chunk数量:{count}", searchCodes.Length);
|
i++;
|
||||||
var existsWorkCodes = dbContext.Queryable<GainfoSapEntity>()
|
try
|
||||||
.Where(x => searchCodes.Contains(x.ename))
|
|
||||||
.Select(x => x.ename)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var originUpdates = persons.Where(x => existsWorkCodes.Contains(x.ZWORKCODE)).ToList();
|
|
||||||
var existsUpdateWorkCodes = originUpdates.Select(x => x.ZWORKCODE).ToList();
|
|
||||||
var originInserts = persons.Where(x => searchCodes.Contains(x.ZWORKCODE)).Where(x => !existsUpdateWorkCodes.Contains(x.ZWORKCODE)).ToList();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
var currentTotal = originUpdates.Count + originInserts.Count;
|
|
||||||
|
|
||||||
var updates = ToGainfoSap(originUpdates);
|
|
||||||
_logger.LogInformation("SAP分批更新数:{count}", updates.Count);
|
|
||||||
var inserts = ToGainfoSap(originInserts);
|
|
||||||
_logger.LogInformation("SAP分批新增数:{count}", inserts.Count);
|
|
||||||
|
|
||||||
foreach (var item in inserts)
|
|
||||||
{
|
{
|
||||||
i++;
|
InsertPerson(item);
|
||||||
try
|
Logger.LogWarning("执行新增成功 工号:{code},姓名:{name}", item.ename, item.gname);
|
||||||
{
|
|
||||||
InsertPerson(dbContext, item);
|
|
||||||
_logger.LogInformation("执行新增成功 工号:{code},姓名:{name}", item.ename, item.gname);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
failure++;
|
|
||||||
_logger.LogError(ex, "执行新增失败:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
foreach (var item in updates)
|
|
||||||
{
|
{
|
||||||
i++;
|
Logger.LogError(ex, "执行新增失败:{message}", ex.Message);
|
||||||
try
|
|
||||||
{
|
|
||||||
UpdatePerson(dbContext, item);
|
|
||||||
_logger.LogInformation("执行更新成功 工号:{code},姓名:{name}", item.ename, item.gname);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
failure++;
|
|
||||||
_logger.LogError(ex, "执行更新失败:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
foreach (var item in updates)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdatePerson(item);
|
||||||
|
Logger.LogWarning("执行更新成功 工号:{code},姓名:{name}", item.ename, item.gname);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "执行更新失败:{message}", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var rResult = await _devicePermissionApi.RePermissionUsersInfoAsync(dto);
|
var rResult = await _devicePermissionApi.RePermissionUsersInfoAsync(dto);
|
||||||
var r = rResult.Data;
|
var r = rResult.Data;
|
||||||
_logger.LogInformation("生成下发任务数量:{count}", r);
|
|
||||||
|
|
||||||
return 0;
|
Logger.LogWarning("生成下发任务数量:{count}", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InsertPerson(IDbContext db, GainfoSapEntity item)
|
private void InsertPerson(GainfoSapEntity item)
|
||||||
{
|
{
|
||||||
db.Client.Insertable(item).ExecuteCommand();
|
DbContext.Client.Insertable(item).ExecuteCommand();
|
||||||
|
|
||||||
var info = GainfoSapToGainfo(item);
|
var info = GainfoSapToGainfo(item);
|
||||||
|
|
||||||
if (item.isowner == "T")
|
if (item.isowner == "T")
|
||||||
{
|
{
|
||||||
db.Client.Insertable(info).ExecuteCommand();
|
DbContext.Client.Insertable(info).ExecuteCommand();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
db.Client.Insertable(info).AS("GainfoLeave").ExecuteCommand();
|
DbContext.Client.Insertable(info).AS("GainfoLeave").ExecuteCommand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,10 +178,10 @@ public class SyncPersonJob
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePerson(IDbContext db, GainfoSapEntity item)
|
private void UpdatePerson(GainfoSapEntity item)
|
||||||
{
|
{
|
||||||
var gainfoSap = db.Queryable<GainfoSapEntity>().Where(x => x.ename == item.ename).First();
|
var gainfoSap = DbContext.Queryable<GainfoSapEntity>().Where(x => x.ename == item.ename).First();
|
||||||
db.Updateable<GainfoSapEntity>().SetColumns(g => new GainfoSapEntity
|
DbContext.Updateable<GainfoSapEntity>().SetColumns(g => new GainfoSapEntity
|
||||||
{
|
{
|
||||||
PERNR = item.PERNR,
|
PERNR = item.PERNR,
|
||||||
gname = item.gname,
|
gname = item.gname,
|
||||||
@@ -211,14 +202,14 @@ public class SyncPersonJob
|
|||||||
.Where(x => x.ename == item.ename)
|
.Where(x => x.ename == item.ename)
|
||||||
.ExecuteCommand();
|
.ExecuteCommand();
|
||||||
|
|
||||||
var gainfo = db.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).First();
|
var gainfo = DbContext.Queryable<GainfoEntity>().Where(x => x.Code == item.ename).First();
|
||||||
if (item.isowner == "T")
|
if (item.isowner == "T")
|
||||||
{
|
{
|
||||||
if (gainfo != null)
|
if (gainfo != null)
|
||||||
{
|
{
|
||||||
var workplace = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM;
|
var workplace = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDJDNM)?.Code ?? item.ZZ_GZDJDNM;
|
||||||
var factory = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM;
|
var factory = _tenants.FirstOrDefault(x => x.Name == item.ZZ_GZDCQNM)?.Code ?? item.ZZ_GZDCQNM;
|
||||||
db.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
DbContext.Updateable<GainfoEntity>().SetColumns(g => new GainfoEntity
|
||||||
{
|
{
|
||||||
SapNo = item.PERNR,
|
SapNo = item.PERNR,
|
||||||
Name = item.gname,
|
Name = item.gname,
|
||||||
@@ -240,23 +231,23 @@ public class SyncPersonJob
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var info = GainfoSapToGainfo(item);
|
var info = GainfoSapToGainfo(item);
|
||||||
db.Client.Insertable(info).ExecuteCommand();
|
DbContext.Client.Insertable(info).ExecuteCommand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (gainfo != null)
|
if (gainfo != null)
|
||||||
{
|
{
|
||||||
db.Client.Deleteable(gainfo).ExecuteCommand();
|
DbContext.Client.Deleteable(gainfo).ExecuteCommand();
|
||||||
gainfo.Id = 0;
|
gainfo.Id = 0;
|
||||||
db.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommand();
|
DbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SapPersonItem> GetModifiedPerson(IDbContext db, List<SapPersonItem> sapList)
|
private List<SapPersonItem> GetModifiedPerson(List<SapPersonItem> sapList)
|
||||||
{
|
{
|
||||||
var last = LoadData(db);
|
var last = LoadData();
|
||||||
if (last.Count <= 0)
|
if (last.Count <= 0)
|
||||||
{
|
{
|
||||||
return sapList;
|
return sapList;
|
||||||
@@ -294,9 +285,9 @@ public class SyncPersonJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static List<SapPersonItem> LoadData(IDbContext db)
|
private List<SapPersonItem> LoadData()
|
||||||
{
|
{
|
||||||
var gainfo = db.Queryable<GainfoSapEntity>().ToList();
|
var gainfo = DbContext.Queryable<GainfoSapEntity>().ToList();
|
||||||
|
|
||||||
return gainfo.Select(x => new SapPersonItem
|
return gainfo.Select(x => new SapPersonItem
|
||||||
{
|
{
|
||||||
@@ -335,7 +326,7 @@ public class SyncPersonJob
|
|||||||
GainfoSapEntity o = null;
|
GainfoSapEntity o = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var position = _positions.FirstOrDefault(x => x.No == person.PLANS);
|
//var position = _positions.FirstOrDefault(x => x.No == person.PLANS);
|
||||||
|
|
||||||
var rzrq = SafeParseDate(person.ZRZRQ);
|
var rzrq = SafeParseDate(person.ZRZRQ);
|
||||||
var lzrq = SafeParseDate(person.ZLZRQ);
|
var lzrq = SafeParseDate(person.ZLZRQ);
|
||||||
@@ -378,7 +369,7 @@ public class SyncPersonJob
|
|||||||
remark = rmk,
|
remark = rmk,
|
||||||
native = native,
|
native = native,
|
||||||
sex = sex,
|
sex = sex,
|
||||||
web = SubString(position?.Name ?? "", 30),
|
//web = SubString(position?.Name ?? "", 30),
|
||||||
logdate = DateTime.Now,
|
logdate = DateTime.Now,
|
||||||
isowner = int.Parse(person.ZSTATUS) < 5 ? "T" : "F",
|
isowner = int.Parse(person.ZSTATUS) < 5 ? "T" : "F",
|
||||||
@class = "C",
|
@class = "C",
|
||||||
@@ -409,7 +400,7 @@ public class SyncPersonJob
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(idno) || idno.Length < 6) return null;
|
if (string.IsNullOrWhiteSpace(idno) || idno.Length < 6) return null;
|
||||||
idno = idno.TrimStart();
|
idno = idno.TrimStart();
|
||||||
return idno.Substring(0, 6);
|
return idno[..6];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DateTime? SafeParseDate(string str)
|
private static DateTime? SafeParseDate(string str)
|
||||||
@@ -1,33 +1,31 @@
|
|||||||
using Dlhis.Entity.Basic.Entity;
|
using Dlhis.Entity.Basic.Entity;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
using Dlhis.ScheduledTask.SyncSapInfo.Dto;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
||||||
using Kurisu.SqlSugar.Services;
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 职位同步定时任务
|
/// SAP岗位信息同步
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SyncPositionJob
|
[RecurringJob(nameof(SyncPositionJob), "0 0 0 * * ?", Name = "SAP岗位信息同步", Queue = "SAP")]
|
||||||
|
public class SyncPositionJob : BaseJob
|
||||||
{
|
{
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly IJinkoSapService _jinkoSapService;
|
private readonly IJinkoSapService _jinkoSapService;
|
||||||
private readonly ILogger<SyncPositionJob> _logger;
|
|
||||||
|
|
||||||
public SyncPositionJob(IDbContext dbContext, IJinkoSapService jinkoSapService, ILogger<SyncPositionJob> logger)
|
public SyncPositionJob(IServiceProvider serviceProvider, IJinkoSapService jinkoSapService) : base(serviceProvider)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
|
||||||
_jinkoSapService = jinkoSapService;
|
_jinkoSapService = jinkoSapService;
|
||||||
_logger = logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunAsync()
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
var positionResult = await _jinkoSapService.GetPositionsAsync();
|
var positionResult = await _jinkoSapService.GetPositionsAsync();
|
||||||
|
|
||||||
if (positionResult.Position != null && positionResult.Position.Items.Count > 0)
|
if (positionResult.Position != null && positionResult.Position.Items.Count > 0)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("SAP岗位数量:{count}", positionResult.Position.Items.Count);
|
Logger.LogWarning("SAP岗位数量:{count}", positionResult.Position.Items.Count);
|
||||||
await SaveOrg(positionResult.Position.Items);
|
await SaveOrg(positionResult.Position.Items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +34,7 @@ public class SyncPositionJob
|
|||||||
{
|
{
|
||||||
foreach (var item in modifiedPostList)
|
foreach (var item in modifiedPostList)
|
||||||
{
|
{
|
||||||
var position = await _dbContext.Queryable<PositionEntity>().Where(x => x.No == item.ZJOBID).FirstAsync();
|
var position = await DbContext.Queryable<PositionEntity>().Where(x => x.No == item.ZJOBID).FirstAsync();
|
||||||
if (position == null)
|
if (position == null)
|
||||||
{
|
{
|
||||||
position = new PositionEntity
|
position = new PositionEntity
|
||||||
@@ -47,7 +45,7 @@ public class SyncPositionJob
|
|||||||
Grade = item.ZZWID
|
Grade = item.ZZWID
|
||||||
};
|
};
|
||||||
|
|
||||||
await _dbContext.InsertAsync(position);
|
await DbContext.InsertAsync(position);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -55,7 +53,7 @@ public class SyncPositionJob
|
|||||||
position.DepartmentNo = item.ZDEPID;
|
position.DepartmentNo = item.ZDEPID;
|
||||||
position.Grade = item.ZZWID;
|
position.Grade = item.ZZWID;
|
||||||
|
|
||||||
await _dbContext.UpdateAsync(position);
|
await DbContext.UpdateAsync(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
111
Src/Dlhis.ScheduledTask/Jobs/UpdateUserPasswordJob.cs
Normal file
111
Src/Dlhis.ScheduledTask/Jobs/UpdateUserPasswordJob.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
using Dlhis.Entity.Basic.Entity;
|
||||||
|
using Dlhis.Entity.Sys.Entities;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using Kurisu.SqlSugar.Services;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace Dlhis.ScheduledTask.Jobs;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户创建
|
||||||
|
/// </summary>
|
||||||
|
[RecurringJob(nameof(UpdateUserPasswordJob), "0 0 6 * * ?", Name = "用户创建")]
|
||||||
|
public class UpdateUserPasswordJob : BaseJob
|
||||||
|
{
|
||||||
|
public UpdateUserPasswordJob(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RunAsync(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
|
||||||
|
var identityDbContext = DbContext.ChangeDb("identity");
|
||||||
|
|
||||||
|
var whitelist = new List<string>() { "admin", "WB-0741", "WB-1091", "0123456" };
|
||||||
|
|
||||||
|
var users = await identityDbContext.Queryable<UserEntity>()
|
||||||
|
.Where(x => !whitelist.Contains(x.UserName))
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var gainfos = await DbContext.Queryable<GainfoEntity>().Where(x => !whitelist.Contains(x.Code)).ToListAsync();
|
||||||
|
|
||||||
|
var hasher = new PasswordHasher<UserEntity>();
|
||||||
|
foreach (var gainfo in gainfos)
|
||||||
|
{
|
||||||
|
if (gainfo.IdNo.IsPresent())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var password = gainfo.IdNo.TakeLast(6).Join("");
|
||||||
|
|
||||||
|
var user = users.FirstOrDefault(x => x.UserName == gainfo.Code);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = new UserEntity
|
||||||
|
{
|
||||||
|
UserName = gainfo.Code,
|
||||||
|
NormalizedUserName = gainfo.Code.ToUpper(),
|
||||||
|
ConcurrencyStamp = Guid.NewGuid().ToString(),
|
||||||
|
SecurityStamp = Guid.NewGuid().ToString(),
|
||||||
|
};
|
||||||
|
password = hasher.HashPassword(user, password);
|
||||||
|
user.PasswordHash = password;
|
||||||
|
|
||||||
|
var id = (int)await identityDbContext.InsertReturnIdentityAsync(user);
|
||||||
|
await AddUserClaim(identityDbContext, id, "jinko-code", gainfo.Code);
|
||||||
|
await AddUserClaim(identityDbContext, id, "name", gainfo.Name);
|
||||||
|
if (!string.IsNullOrEmpty(gainfo.Factory))
|
||||||
|
{
|
||||||
|
var userTenant = await identityDbContext.Queryable<UserTenantEntity>().Where(x => x.UserId == user.Id).FirstAsync();
|
||||||
|
if (userTenant == null)
|
||||||
|
{
|
||||||
|
userTenant = new UserTenantEntity
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
TenantCode = gainfo.Factory
|
||||||
|
};
|
||||||
|
await identityDbContext.InsertAsync(userTenant);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
userTenant.TenantCode = gainfo.Factory;
|
||||||
|
await identityDbContext.UpdateAsync(userTenant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
password = hasher.HashPassword(user, password);
|
||||||
|
user.PasswordHash = password;
|
||||||
|
await identityDbContext.UpdateAsync(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AddUserClaim(IDbContext dbContext, int userId, string type, string value)
|
||||||
|
{
|
||||||
|
var claim = await dbContext.Queryable<UserClaimEntity>().Where(x => x.UserId == userId).FirstAsync(x => x.ClaimType == type);
|
||||||
|
if (claim == null)
|
||||||
|
{
|
||||||
|
claim = new UserClaimEntity()
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
ClaimType = type,
|
||||||
|
ClaimValue = value
|
||||||
|
};
|
||||||
|
await dbContext.InsertAsync(claim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
claim.ClaimValue = value;
|
||||||
|
await dbContext.UpdateAsync(claim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,8 @@ public class HangfirePack : BaseAppPack
|
|||||||
{
|
{
|
||||||
Db = 5,
|
Db = 5,
|
||||||
Prefix = "hangfire"
|
Prefix = "hangfire"
|
||||||
});
|
})
|
||||||
|
.UseSerilogLogProvider();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
using Dlhis.ScheduledTask.CommonJobs;
|
using System.Linq.Expressions;
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Job;
|
using System.Reflection;
|
||||||
using Dlhis.ScheduledTask.TaskAssignment.Job;
|
|
||||||
using Hangfire;
|
using Hangfire;
|
||||||
|
using Hangfire.Common;
|
||||||
using Kurisu.AspNetCore.Startup;
|
using Kurisu.AspNetCore.Startup;
|
||||||
|
using Kurisu.AspNetCore.Utils.Extensions;
|
||||||
|
using Kurisu.Scheduled;
|
||||||
|
using Kurisu.Scheduled.Attributes;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.Packs;
|
namespace Dlhis.ScheduledTask.Packs;
|
||||||
|
|
||||||
@@ -13,68 +17,34 @@ public class JobPack : BaseAppPack
|
|||||||
|
|
||||||
public override void Invoke(IServiceProvider serviceProvider)
|
public override void Invoke(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
RecurringJob.AddOrUpdate<SyncOrganizationJob>("SyncSap", s => s.RunAsync(), "0 0 2 * * ?", new RecurringJobOptions
|
var logger = serviceProvider.GetService<ILogger<JobPack>>();
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
RecurringJob.AddOrUpdate<SyncPersonJob>("SyncPerson", s => s.RunAsync(), "0 0 3 * * ?", new RecurringJobOptions
|
var jobs = Assembly.GetEntryAssembly().GetTypes()
|
||||||
{
|
.Where(x => x.IsAssignableTo(typeof(BaseJob)) && x != typeof(BaseJob))
|
||||||
TimeZone = TimeZoneInfo.Local
|
.Where(x => x.IsDefined(typeof(RecurringJobAttribute)))
|
||||||
});
|
.ToList();
|
||||||
|
|
||||||
//创建设备同步时间任务
|
var setJob = typeof(Job).GetMethod(nameof(Job.FromExpression), BindingFlags.NonPublic | BindingFlags.Static, new[] { typeof(LambdaExpression), typeof(Type), typeof(string) });
|
||||||
RecurringJob.AddOrUpdate<CreateSyncServerDateTimeJob>("SyncServerDateTime", s => s.RunAsync(), "0 0 0/1 * * ?", new RecurringJobOptions
|
var m = (Lazy<RecurringJobManager>)typeof(RecurringJob).GetField("Instance", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
//创建设备获取的任务
|
(jobs.Select(job => job.GetCustomAttribute<RecurringJobAttribute>().UniqueJobKey).Distinct().Count() != jobs.Count).ThrowIfTrue("任务key重复");
|
||||||
RecurringJob.AddOrUpdate<CreateGetUploadRecordJob>("CreateGetUploadRecord", s => s.RunAsync(), "0 0/1 * * * ?", new RecurringJobOptions
|
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
//创建系统默认分组
|
logger.LogDebug("一共获取{count}个调度任务", jobs.Count);
|
||||||
RecurringJob.AddOrUpdate<CreateDefinitelyGroupJob>("CreateDefinitelyGroup", s => s.RunAsync(), "0 0 5 * * ?", new RecurringJobOptions
|
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
//心跳
|
foreach (var job in jobs)
|
||||||
RecurringJob.AddOrUpdate<HeartbeatJob>("Heartbeat", s => s.RunAsync(), "0/10 * * * * ?", new RecurringJobOptions
|
|
||||||
{
|
{
|
||||||
TimeZone = TimeZoneInfo.Local
|
var recurringSetting = job.GetCustomAttribute<RecurringJobAttribute>()!;
|
||||||
});
|
recurringSetting.Cron.IsEmpty().ThrowIfTrue(job.Name + "尚未定义Cron");
|
||||||
|
|
||||||
//上传考勤记录
|
var parameterExpression = Expression.Parameter(job);
|
||||||
RecurringJob.AddOrUpdate<SyncOriginCardInfoJob>("SyncOriginCardInfo", s => s.RunAsync(), "0/20 * * * * ?", new RecurringJobOptions
|
var todo = job.GetMethod(nameof(BaseJob.TodoAsync));
|
||||||
{
|
var todoExp = Expression.Call(parameterExpression, todo);
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
//处理重复下发任务
|
var nJob = (Job)setJob.Invoke(null, new object[] { Expression.Lambda(todoExp), job, "default" });
|
||||||
RecurringJob.AddOrUpdate<CancelDuplicationTaskJob>("CancelDuplicationTask", s => s.RunAsync(), "0/15 * * * * ?", new RecurringJobOptions
|
m.Value.AddOrUpdate(recurringSetting.UniqueJobKey, nJob, recurringSetting.Cron, new RecurringJobOptions
|
||||||
{
|
{
|
||||||
TimeZone = TimeZoneInfo.Local
|
TimeZone = TimeZoneInfo.Local
|
||||||
});
|
});
|
||||||
|
}
|
||||||
//更新用户密码
|
|
||||||
RecurringJob.AddOrUpdate<UpdateUserPasswordJob>("UpdateUserPassword", s => s.RunAsync(), "0 0 5 * * ?", new RecurringJobOptions
|
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
//删除前三天前的日志
|
|
||||||
RecurringJob.AddOrUpdate<DelApiLogTaskJob>("DelApiLogTask", s => s.RunAsync(), "0 0 */7 * *", new RecurringJobOptions
|
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
|
|
||||||
//处理餐补
|
|
||||||
RecurringJob.AddOrUpdate<MealSupplementHandlerJob>("MealSupplementHandler", s => s.RunAsync(), "0 0 0/1 * * ?", new RecurringJobOptions
|
|
||||||
{
|
|
||||||
TimeZone = TimeZoneInfo.Local
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Device.Entities;
|
|
||||||
using Dlhis.Entity.Device.Enums;
|
|
||||||
using Dlhis.ScheduledTask.SyncSapInfo.Services;
|
|
||||||
using Kurisu.AspNetCore.Utils.Extensions;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
using SqlSugar;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.SyncSapInfo.Job;
|
|
||||||
|
|
||||||
public class SyncOriginCardInfoJob
|
|
||||||
{
|
|
||||||
private readonly IJinkoJIPService _jinkoJIPService;
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly ISqlSugarOptionsService _sqlSugarOptionsService;
|
|
||||||
private readonly ILogger<SyncOriginCardInfoJob> _logger;
|
|
||||||
|
|
||||||
public SyncOriginCardInfoJob(IJinkoJIPService jinkoJIPService,
|
|
||||||
IDbContext dbContext,
|
|
||||||
ISqlSugarOptionsService sqlSugarOptionsService,
|
|
||||||
ILogger<SyncOriginCardInfoJob> logger
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_jinkoJIPService = jinkoJIPService;
|
|
||||||
_dbContext = dbContext;
|
|
||||||
_sqlSugarOptionsService = sqlSugarOptionsService;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_logger.LogInformation("调度任务:{job}.开始执行", nameof(SyncOriginCardInfoJob));
|
|
||||||
|
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
_sqlSugarOptionsService.IgnoreTenant = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//考勤设备(不需要Enable参数)
|
|
||||||
var devices = await _dbContext.Queryable<DeviceEntity>()
|
|
||||||
.Where(x => x.Type == DeviceTypeEnumType.Attendance || (x.Type == DeviceTypeEnumType.Door && x.AsAttendance))
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
//获取上传日志(有效的)
|
|
||||||
var deviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
|
|
||||||
var logs = await _dbContext.Queryable<DeviceUploadLogEntity>()
|
|
||||||
.Where(x => deviceUniqueNos.Contains(x.DeviceUniqueNo))
|
|
||||||
.Where(x => !string.IsNullOrEmpty(x.UserUniqueNo))
|
|
||||||
.Where(x => x.Sync == false)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
//获取人员信息
|
|
||||||
var userCodes = logs.Select(x => x.UserUniqueNo).ToList();
|
|
||||||
var gainfoCodes = await _dbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => x.Code).ToListAsync();
|
|
||||||
|
|
||||||
var requests = logs.Select(x => new UploadAttendanceRequest
|
|
||||||
{
|
|
||||||
Id = x.Id,
|
|
||||||
RaiseDateTime = x.RaiseDateTime,
|
|
||||||
ZNOTE = devices.First(item => item.UniqueNo == x.DeviceUniqueNo).DeployPlace,
|
|
||||||
ZWORKCODE = gainfoCodes.Contains(x.UserUniqueNo) ? x.UserUniqueNo?.TrimEnd('\0') : string.Empty,
|
|
||||||
|
|
||||||
}).Where(x => x.ZWORKCODE.IsPresent()).ToList();
|
|
||||||
|
|
||||||
var ids = requests.Select(x => x.Id).ToList();
|
|
||||||
if (ids.Any())
|
|
||||||
{
|
|
||||||
var r = await _jinkoJIPService.UploadAttendancesAsync(requests);
|
|
||||||
if (r.OLX == "0")
|
|
||||||
{
|
|
||||||
await _dbContext.Updateable<DeviceUploadLogEntity>()
|
|
||||||
.SetColumns(x => x.Sync == true)
|
|
||||||
.SetColumns(x => x.ModifiedTime == DateTime.Now)
|
|
||||||
.Where(x => ids.Contains(x.Id))
|
|
||||||
.ExecuteCommandAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception(r.OMS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError("上传考勤记录失败:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_sqlSugarOptionsService.IgnoreTenant = false;
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
|
|
||||||
_logger.LogInformation("调度任务:{job}.结束", nameof(SyncOriginCardInfoJob));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -60,7 +60,7 @@ public class JinkoJIPService : IJinkoJIPService
|
|||||||
{
|
{
|
||||||
var requestUrl = "/JIP/DHR/DHR_DL_CALLBACK_UAT";
|
var requestUrl = "/JIP/DHR/DHR_DL_CALLBACK_UAT";
|
||||||
|
|
||||||
var json = requests.ToJson();
|
var json = requests.ToJson(Kurisu.AspNetCore.Utils.Extensions.JsonExtensions.DefaultSetting);
|
||||||
|
|
||||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
var response = await GetHttpClient().PostAsync(requestUrl, content);
|
var response = await GetHttpClient().PostAsync(requestUrl, content);
|
||||||
|
|||||||
@@ -112,10 +112,12 @@ public class JinkoSapService : IJinkoSapService
|
|||||||
{
|
{
|
||||||
departmentInfos.AddRange(personResp.DepartmentInfo.Items);
|
departmentInfos.AddRange(personResp.DepartmentInfo.Items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("获取人事范围{werk}完成", item.Werk);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "获取人事范围{werk}失败:{message}", ex.Message, item.Werk);
|
_logger.LogError(ex, "获取人事范围{werk}失败:{message}", item.Werk, ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Device.Entities;
|
|
||||||
using Dlhis.Entity.Device.Enums;
|
|
||||||
using Kurisu.AspNetCore.Utils.Extensions;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.TaskAssignment.Job;
|
|
||||||
|
|
||||||
public class CreateGetUploadRecordJob
|
|
||||||
{
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly ILogger<CreateGetUploadRecordJob> _logger;
|
|
||||||
private readonly ISqlSugarOptionsService _sqlSugarOptionsService;
|
|
||||||
|
|
||||||
public CreateGetUploadRecordJob(IDbContext dbContext, ILogger<CreateGetUploadRecordJob> logger, ISqlSugarOptionsService sqlSugarOptionsService)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
_sqlSugarOptionsService = sqlSugarOptionsService;
|
|
||||||
_dbContext = dbContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
_sqlSugarOptionsService.IgnoreTenant = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var devices = await _dbContext.Queryable<DeviceEntity>()
|
|
||||||
.Where(x => x.Enable)
|
|
||||||
.Where(x => x.Type == DeviceTypeEnumType.Attendance || x.Type == DeviceTypeEnumType.Door)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
//过滤处理中的任务
|
|
||||||
var currentUniqueNos = await _dbContext.Queryable<DeviceTaskEntity>()
|
|
||||||
.Where(x => x.Type == DeviceTaskEnumType.UploadRecord)
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Process || x.Status == DeviceTaskStatusEnumType.Wait)
|
|
||||||
.Select(x => x.DeviceUniqueNo)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var tasks = devices.Where(x => !currentUniqueNos.Contains(x.UniqueNo)).Select(x => new DeviceTaskEntity
|
|
||||||
{
|
|
||||||
DeviceUniqueNo = x.UniqueNo,
|
|
||||||
Status = DeviceTaskStatusEnumType.Wait,
|
|
||||||
|
|
||||||
TenantId = x.TenantId,
|
|
||||||
Version = 0,
|
|
||||||
Type = DeviceTaskEnumType.UploadRecord,
|
|
||||||
|
|
||||||
CreatedBy = 1,
|
|
||||||
CreateTime = DateTime.Now,
|
|
||||||
ModifiedBy = 1,
|
|
||||||
ModifiedTime = DateTime.Now,
|
|
||||||
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
await _dbContext.InsertAsync(tasks);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "生成{type}任务失败:{message}", DeviceTaskEnumType.UploadRecord.GetDescription(), ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_sqlSugarOptionsService.IgnoreTenant = false;
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using Dlhis.Entity.Basic.Entity;
|
|
||||||
using Dlhis.Entity.Device.Entities;
|
|
||||||
using Dlhis.Entity.Device.Enums;
|
|
||||||
using Kurisu.Core.DataAccess.Entity;
|
|
||||||
using Kurisu.SqlSugar.Services;
|
|
||||||
|
|
||||||
namespace Dlhis.ScheduledTask.TaskAssignment.Job
|
|
||||||
{
|
|
||||||
public class CreateSyncServerDateTimeJob
|
|
||||||
{
|
|
||||||
private readonly IDbContext _dbContext;
|
|
||||||
private readonly ILogger<CreateSyncServerDateTimeJob> _logger;
|
|
||||||
private readonly ISqlSugarOptionsService _sqlSugarOptionsService;
|
|
||||||
|
|
||||||
public CreateSyncServerDateTimeJob(IDbContext dbContext, ILogger<CreateSyncServerDateTimeJob> logger, ISqlSugarOptionsService sqlSugarOptionsService)
|
|
||||||
{
|
|
||||||
_dbContext = dbContext;
|
|
||||||
_logger = logger;
|
|
||||||
_sqlSugarOptionsService = sqlSugarOptionsService;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task RunAsync()
|
|
||||||
{
|
|
||||||
_dbContext.Client.QueryFilter.ClearAndBackup<ITenantId>();
|
|
||||||
_sqlSugarOptionsService.IgnoreTenant = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var deviceUniqueNos = await _dbContext.Queryable<DeviceTaskEntity>()
|
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Wait || x.Status == DeviceTaskStatusEnumType.Process)
|
|
||||||
.Where(x => x.Type == DeviceTaskEnumType.SyncDateTime)
|
|
||||||
.Select(x => x.DeviceUniqueNo)
|
|
||||||
.Distinct()
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var devices = await _dbContext.Queryable<DeviceEntity>()
|
|
||||||
.Where(x => !deviceUniqueNos.Contains(x.UniqueNo))
|
|
||||||
.Where(x => x.Enable)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
var tasks = devices.Select(x => new DeviceTaskEntity
|
|
||||||
{
|
|
||||||
DeviceUniqueNo = x.UniqueNo,
|
|
||||||
Status = DeviceTaskStatusEnumType.Wait,
|
|
||||||
|
|
||||||
TenantId = x.TenantId,
|
|
||||||
Version = 0,
|
|
||||||
UserNo = string.Empty,
|
|
||||||
Type = DeviceTaskEnumType.SyncDateTime,
|
|
||||||
|
|
||||||
CreatedBy = 1,
|
|
||||||
CreateTime = DateTime.Now,
|
|
||||||
ModifiedBy = 1,
|
|
||||||
ModifiedTime = DateTime.Now,
|
|
||||||
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
await _dbContext.InsertAsync(tasks);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "生成同步时间任务失败:{message}", ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_sqlSugarOptionsService.IgnoreTenant = false;
|
|
||||||
_dbContext.Client.QueryFilter.Restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -80,7 +80,6 @@ public class DeviceTaskAssignmentService : IDeviceTaskAssignmentService
|
|||||||
{
|
{
|
||||||
var tasks = await _dbContext.Queryable<DeviceTaskEntity>()
|
var tasks = await _dbContext.Queryable<DeviceTaskEntity>()
|
||||||
.Where(x => request.Ids.Contains(x.Id))
|
.Where(x => request.Ids.Contains(x.Id))
|
||||||
.Where(x => x.Status == DeviceTaskStatusEnumType.Process || x.Status == DeviceTaskStatusEnumType.Error)
|
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
//判断process任务时间
|
//判断process任务时间
|
||||||
|
|||||||
@@ -52,9 +52,9 @@
|
|||||||
},
|
},
|
||||||
"JinkoOptions": {
|
"JinkoOptions": {
|
||||||
"Jip": {
|
"Jip": {
|
||||||
"BaseUrl": "http://172.16.202.34:8000",
|
"BaseUrl": "http://jip.jinkosolar.com",
|
||||||
"Key": "FACE-7409WIBX",
|
"Key": "FACE-CUOJG9N7",
|
||||||
"Secret": "be0a4b88-cd80-4509-b9b9-865205d0d3d8"
|
"Secret": "130c2f2d-03a0-4720-8e25-538ffac7a7cb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RedisOptions": {
|
"RedisOptions": {
|
||||||
@@ -63,12 +63,12 @@
|
|||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"Serilog": {
|
"Serilog": {
|
||||||
"MinimumLevel": {
|
"MinimumLevel": {
|
||||||
"Default": "Information",
|
"Default": "Warning",
|
||||||
"Override": {
|
"Override": {
|
||||||
"System": "Warning",
|
"System": "Warning",
|
||||||
"Microsoft": "Warning",
|
"Microsoft": "Warning",
|
||||||
"Microsoft.Hosting.Lifetime": "Information",
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
"Hangfire": "Information"
|
"Hangfire": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"WriteTo": [
|
"WriteTo": [
|
||||||
|
|||||||
Reference in New Issue
Block a user