feat 访客强制离场通知,自动离场增加节假日判断

This commit is contained in:
2025-12-09 11:16:09 +08:00
parent 59557ab617
commit 726e62d032
7 changed files with 107 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
using Dlhis.Entity.Visitor.Enums; using Dlhis.Basic.Utils;
using Kurisu.AspNetCore.Utils.Extensions; using Dlhis.Entity.Visitor.Enums;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Dlhis.Basic.Appointment.Response; namespace Dlhis.Basic.Appointment.Response;

View File

@@ -1,5 +1,7 @@
using Dlhis.Basic.Appointment.Request; using Dlhis.Basic.Appointment.Request;
using Dlhis.Basic.Appointment.Response; using Dlhis.Basic.Appointment.Response;
using Dlhis.Basic.Common.Message.Requests;
using Dlhis.Basic.Common.Message.Services;
using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Request;
using Dlhis.Basic.Organization.Services; using Dlhis.Basic.Organization.Services;
using Dlhis.Dh.Api; using Dlhis.Dh.Api;
@@ -27,6 +29,7 @@ public class AppointmentService : IAppointmentService
private readonly IDataProtectionProvider _dataProtectionProvider; private readonly IDataProtectionProvider _dataProtectionProvider;
private readonly ICurrentUser _currentUser; private readonly ICurrentUser _currentUser;
private readonly IDhApi _dhApi; private readonly IDhApi _dhApi;
private readonly IJinkoApiService _jinkoApiService;
private readonly IFactorySettingService _factorySettingService; private readonly IFactorySettingService _factorySettingService;
private readonly ILogger<AppointmentService> _logger; private readonly ILogger<AppointmentService> _logger;
private readonly IGainfoFaceService _gainfoFaceService; private readonly IGainfoFaceService _gainfoFaceService;
@@ -36,15 +39,18 @@ public class AppointmentService : IAppointmentService
IDataProtectionProvider dataProtectionProvider, IDataProtectionProvider dataProtectionProvider,
ICurrentUser currentUser, ICurrentUser currentUser,
IDhApi dhApi, IDhApi dhApi,
IJinkoApiService jinkoApiService,
IFactorySettingService factorySettingService, IFactorySettingService factorySettingService,
IGainfoFaceService gainfoFaceService, IGainfoFaceService gainfoFaceService,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
ILogger<AppointmentService> logger) ILogger<AppointmentService> logger)
{ {
_dbContext = dbContext; _dbContext = dbContext;
_dataProtectionProvider = dataProtectionProvider; _dataProtectionProvider = dataProtectionProvider;
_currentUser = currentUser; _currentUser = currentUser;
_dhApi = dhApi; _dhApi = dhApi;
_jinkoApiService = jinkoApiService;
_factorySettingService = factorySettingService; _factorySettingService = factorySettingService;
_logger = logger; _logger = logger;
_gainfoFaceService = gainfoFaceService; _gainfoFaceService = gainfoFaceService;
@@ -196,6 +202,13 @@ public class AppointmentService : IAppointmentService
// 生成设备任务并更新数据库 // 生成设备任务并更新数据库
await GenerateDeviceTasksAsync(detail, true, DeviceTaskEnumType.Delete, $"强制离场:{reason}"); await GenerateDeviceTasksAsync(detail, true, DeviceTaskEnumType.Delete, $"强制离场:{reason}");
await _dbContext.UpdateAsync(detail); await _dbContext.UpdateAsync(detail);
var appointment = await _dbContext.Queryable<VisitorAppointmentEntity>().Where(x => x.No == detail.No).SingleAsync();
await _jinkoApiService.SendWorkMessageAsync(new DingTalkWorkMessageRequest
{
WorkCodes = new List<string> { appointment.Code },
Content = $"您的访客预约《{appointment.Title}》中的访客{detail.Name}已被强制离场,原因:{reason}。"
});
} }
public async Task<Pagination<AppointmentDetailResponse>> GetRecordPageByIdNoAsync(AppointmentIdNoPageRequest request) public async Task<Pagination<AppointmentDetailResponse>> GetRecordPageByIdNoAsync(AppointmentIdNoPageRequest request)
@@ -355,6 +368,21 @@ public class AppointmentService : IAppointmentService
//todo 临时处理循环依赖 //todo 临时处理循环依赖
var gainfoService = _serviceProvider.GetService<IGainfoService>(); var gainfoService = _serviceProvider.GetService<IGainfoService>();
var holidaies = await _dbContext
.Queryable<HolidayEntity>()
.Select(x => new
{
x.Type,
Period = new DatePeriod
{
Start = x.Start,
End = x.End
}
})
.ToListAsync();
var weekends = new List<DayOfWeek>() { DayOfWeek.Saturday, DayOfWeek.Sunday };
//人员分组,key为factory //人员分组,key为factory
foreach (var exts in externals.GroupBy(x => x.Factory)) foreach (var exts in externals.GroupBy(x => x.Factory))
{ {
@@ -375,29 +403,73 @@ public class AppointmentService : IAppointmentService
.SingleAsync(); .SingleAsync();
// 如果最近通行时间存在且超出未通行天数阈值,则自动归档该外部人员 // 如果最近通行时间存在且超出未通行天数阈值,则自动归档该外部人员
if (raiseDateTime.HasValue && raiseDateTime.Value.AddDays(setting.NoRecordAutoResignExternalDays) < DateTime.Now) if (raiseDateTime.HasValue)
{ {
try var checkDates = GetDaysUntilToday(raiseDateTime.Value);
var days = checkDates.Count;
foreach (var date in checkDates)
{ {
await gainfoService.ResignAsync(new GainfoResignRequest //date.DayOfWeek
foreach (var holiday in holidaies)
{ {
Id = ext.Id, var isPresent = date >= holiday.Period.Start && date <= holiday.Period.Start;
Reason = $"{setting.NoRecordAutoResignExternalDays}天无通行记录", if (isPresent)
Date = DateTime.Now {
}); if (holiday.Type == HolidayEnumType.Rest)
{
days--;
}
}
else
{
if (weekends.Contains(date.DayOfWeek))
{
days--;
}
}
}
} }
catch (Exception e)
if (days >= setting.NoRecordAutoResignExternalDays)
{ {
// 记录自动归档异常日志 try
_logger.LogError(e, "自动归档外部人员异常:{msg}", e.Message); {
await gainfoService.ResignAsync(new GainfoResignRequest
{
Id = ext.Id,
Reason = $"{setting.NoRecordAutoResignExternalDays}天无通行记录",
Date = DateTime.Now
});
}
catch (Exception e)
{
// 记录自动归档异常日志
_logger.LogError(e, "自动归档外部人员异常:{msg}", e.Message);
}
} }
} }
} }
} }
} }
//********************************************************************************************************************* //*********************************************************************************************************************
private List<DateOnly> GetDaysUntilToday(DateTime begin)
{
var start = DateOnly.FromDateTime(begin.Date);
var today = DateOnly.FromDateTime(DateTime.Today);
if (start > today) return new List<DateOnly>();
var days = new List<DateOnly>();
for (var d = start; d <= today; d = d.AddDays(1))
{
days.Add(d);
}
return days;
}
private async Task GenerateDeviceTasksAsync(VisitorAppointmentDetailEntity detail, bool withWorkplace, DeviceTaskEnumType deviceTaskType, string source) private async Task GenerateDeviceTasksAsync(VisitorAppointmentDetailEntity detail, bool withWorkplace, DeviceTaskEnumType deviceTaskType, string source)
{ {

View File

@@ -28,7 +28,7 @@ public class HolidayService : IHolidayService
var exists = await _dbContext.Queryable<HolidayEntity>() var exists = await _dbContext.Queryable<HolidayEntity>()
.WhereIF(req.Id.HasValue, x => x.Id != req.Id) .WhereIF(req.Id.HasValue, x => x.Id != req.Id)
.Where(x => x.Year == req.Year) .Where(x => x.Year == req.Year)
.Where(x => x.Start < req.End && req.Start < x.End) .Where(x => x.Start <= req.End && req.Start <= x.End)
.Where(x => x.Type != req.Type) .Where(x => x.Type != req.Type)
.AnyAsync(); .AnyAsync();
@@ -36,20 +36,22 @@ public class HolidayService : IHolidayService
if (!req.Id.HasValue) if (!req.Id.HasValue)
{ {
await _dbContext.InsertAsync(req.Adapt<HolidayEntity>()); var holiday = req.Adapt<HolidayEntity>();
await _dbContext.InsertAsync(holiday);
} }
else else
{ {
var entity = await _dbContext.Queryable<HolidayEntity>().SingleAsync(x => x.Id == req.Id); var holiday = await _dbContext.Queryable<HolidayEntity>().SingleAsync(x => x.Id == req.Id);
entity.ThrowIfNull("节假日数据不存在"); holiday.ThrowIfNull("节假日数据不存在");
req.Adapt(entity); req.Adapt(holiday);
await _dbContext.UpdateAsync(entity); await _dbContext.UpdateAsync(holiday);
} }
} }
public async Task DeleteAsync(long id) public async Task DeleteAsync(long id)
{ {
await _dbContext.Deleteable<HolidayEntity>().Where(x => x.Id == id).ExecuteCommandAsync(); var holiday = await _dbContext.Queryable<HolidayEntity>().Where(x => x.Id == id).SingleAsync();
await _dbContext.DeleteReallyAsync(holiday);
} }
} }

View File

@@ -22,4 +22,10 @@ public class MessagesController : ControllerBase
{ {
await _jinkoApiService.SendWorkMessageAsync(request); await _jinkoApiService.SendWorkMessageAsync(request);
} }
[HttpPost("dingtalk/workgrid/workmessage")]
public async Task SendWorkMessageByWorkGridAsync(DingTalkWorkMessageRequest request)
{
await _jinkoApiService.SendWorkMessageByWorkGridAsync(request);
}
} }

View File

@@ -5,4 +5,5 @@ namespace Dlhis.Basic.Common.Message.Services;
public interface IJinkoApiService : ISingletonDependency public interface IJinkoApiService : ISingletonDependency
{ {
Task SendWorkMessageAsync(DingTalkWorkMessageRequest request); Task SendWorkMessageAsync(DingTalkWorkMessageRequest request);
Task SendWorkMessageByWorkGridAsync(DingTalkWorkMessageRequest request);
} }

View File

@@ -82,6 +82,11 @@ public class JinkoApiService : IJinkoApiService
var jObject = JObject.Parse(jsonResponse); var jObject = JObject.Parse(jsonResponse);
(jObject.Value<string>("errcode") == "0").ThrowIfFalse(jObject.Value<string>("errmsg")); (jObject.Value<string>("errcode") == "0").ThrowIfFalse(jObject.Value<string>("errmsg"));
}
public async Task SendWorkMessageByWorkGridAsync(DingTalkWorkMessageRequest request)
{
await SendWorkMessageAsync(request);
using var scope = _serviceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var ol = scope.ServiceProvider.GetService<IOperateLog>(); var ol = scope.ServiceProvider.GetService<IOperateLog>();

View File

@@ -1,3 +1,4 @@
using Dlhis.Basic.Utils;
using Dlhis.DataPermission.Model; using Dlhis.DataPermission.Model;
using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Entities;