using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities;
using Dlhis.Entity.Device.Enums;
using Dlhis.Entity.Visitor.Entity;
using Dlhis.Entity.Visitor.Enums;
using Dlhis.ScheduledTask.Attributes;
namespace Dlhis.ScheduledTask.Jobs.Visitor;
///
/// 定时任务:每5分钟执行一次,自动处理访客预约车间相关逻辑。
///
[RecurringJob(nameof(AutoConfirmAppointmentJob), "0 0/5 * * * ?", Name = "访客预约自动处理车间")]
public class AutoConfirmAppointmentJob : BaseJob
{
// 构造函数,注入服务提供者
public AutoConfirmAppointmentJob(IServiceProvider serviceProvider) : base(serviceProvider)
{
}
// 定时任务主逻辑
protected override async Task RunAsync(IServiceProvider serviceProvider)
{
// 查询所有需要自动处理的访客预约明细
var details = await DbContext.Queryable()
.Where(x => x.IsEnterDoorArea == false || (x.IsEnterDoorArea && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived))
.Where(x => x.IsEnterWorkplace && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Wait && DateTime.Now >= x.WorkplaceStart)
.ToListAsync();
// 获取所有相关证件号
var idNos = details.Select(x => x.IdNo).Distinct().ToList();
// 查询访客信息
var gainfos = await DbContext.Queryable()
.Where(x => idNos.Contains(x.IdNo) || idNos.Contains(x.Code))
.ToListAsync();
// 批量获取所有有效区域编码,避免循环中多次查库
var allValidAreaCodes = details.SelectMany(GetValidAreaCodes).Distinct().ToList();
// 查询所有有效区域编码
var allAreaCodes = await DbContext.Queryable()
.Where(x => allValidAreaCodes.Contains(x.CustomCode))
.Select(x => x.CustomCode)
.ToListAsync();
// 预先缓存每个detail的有效区域编码,减少循环内重复计算
var detailsWithValidAreaCodesDict = details.ToDictionary(
x => x.Id,
x => GetValidAreaCodes(x).Intersect(allAreaCodes).ToList()
);
var deviceTaskList = new List(); // 设备任务列表
var updateDetails = new List(); // 需要更新的预约明细
foreach (var detail in details)
{
// 查找对应访客信息
var gainfo = gainfos.FirstOrDefault(x => x.IdNo == detail.IdNo || x.Code == detail.IdNo);
if (gainfo == null) continue;
// 获取当前明细的有效区域编码
var existsAreaCodes = detailsWithValidAreaCodesDict[detail.Id];
if (!existsAreaCodes.Any()) continue;
// 查询区域下的设备信息
var deviceInfos = await GetDeviceUniqueNoAndTenantIdAsync(existsAreaCodes);
if (deviceInfos?.Any() != true)
{
continue;
}
// 生成设备任务
deviceTaskList.AddRange(deviceInfos.Select(x => new DeviceTaskEntity
{
DeviceType = DeviceTypeEnumType.Door,
DeviceUniqueNo = x.UniqueNo,
Status = DeviceTaskStatusEnumType.Wait,
UserNo = gainfo.No,
Type = DeviceTaskEnumType.Add,
Priority = 100,
TenantId = x.TenantId,
Source = "定时任务判断触发车间下发任务",
Version = 0
}));
// 更新预约明细状态
if (detail.WorkplaceStatus != VisitorAppointmentDetailStatusEnumType.Wait) continue;
detail.WorkplaceStatus = VisitorAppointmentDetailStatusEnumType.Arrived;
updateDetails.Add(detail);
}
// 事务提交设备任务和明细状态更新
var r = await DbContext.Client.Ado.UseTranAsync(async () =>
{
if (deviceTaskList.Any())
await DbContext.InsertAsync(deviceTaskList);
if (updateDetails.Any())
await DbContext.UpdateAsync(updateDetails);
});
// 记录失败日志
if (!r.IsSuccess)
{
Logger.LogError(r.ErrorException, "执行访客预约自动处理车间任务失败:{error}", r.ErrorMessage);
}
}
///
/// 获取预约明细的有效区域编码
///
///
///
private static List GetValidAreaCodes(VisitorAppointmentDetailEntity detail)
{
return detail.ApplyWorkplaceAreas ?? new List();
}
///
/// 根据区域编码获取设备唯一编号和租户ID
///
///
///
private async Task> GetDeviceUniqueNoAndTenantIdAsync(List existsAreaCodes)
{
// 当前分配的设备组code
var deviceGroupCodes = await DbContext.Queryable()
.Where(x => existsAreaCodes.Contains(x.CustomCode))
.Select(x => x.DeviceGroupCode)
.ToListAsync();
if (!deviceGroupCodes.Any()) return null;
// 查询设备组下的设备编码
var deviceCodes = await DbContext.Queryable()
.Where(x => deviceGroupCodes.Contains(x.GroupCode))
.Select(x => x.DeviceCode)
.ToListAsync();
if (!deviceCodes.Any()) return null;
// 查询设备唯一编号和租户ID
var deviceUniqueNos = await DbContext.Queryable()
.Where(x => deviceCodes.Contains(x.Code))
.Select(x => new { x.UniqueNo, x.TenantId })
.ToListAsync();
return !deviceUniqueNos.Any()
? null
: deviceUniqueNos.Select(x => (x.UniqueNo, x.TenantId)).ToList();
}
}