299 lines
13 KiB
C#
299 lines
13 KiB
C#
using Dlhis.Basic.Appointment.Request;
|
|
using Dlhis.Basic.Appointment.Response;
|
|
using Dlhis.Basic.Organization.Request;
|
|
using Dlhis.Basic.Organization.Services;
|
|
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 Kurisu.AspNetCore.Authentication.Abstractions;
|
|
using Kurisu.AspNetCore.CustomClass;
|
|
using Kurisu.AspNetCore.DataAccess.Dto;
|
|
using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions;
|
|
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
|
using Kurisu.AspNetCore.Utils.Extensions;
|
|
using Microsoft.AspNetCore.DataProtection;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using SqlSugar;
|
|
|
|
namespace Dlhis.Basic.Appointment.Services.Implements;
|
|
|
|
public class AppointmentService : IAppointmentService
|
|
{
|
|
private readonly IDbContext _dbContext;
|
|
private readonly IDataProtectionProvider _dataProtectionProvider;
|
|
private readonly ICurrentUser _currentUser;
|
|
private readonly IGainfoFaceService _gainfoFaceService;
|
|
|
|
public AppointmentService(IDbContext dbContext,
|
|
IDataProtectionProvider dataProtectionProvider,
|
|
ICurrentUser currentUser,
|
|
IGainfoFaceService gainfoFaceService)
|
|
{
|
|
_dbContext = dbContext;
|
|
_dataProtectionProvider = dataProtectionProvider;
|
|
_currentUser = currentUser;
|
|
_gainfoFaceService = gainfoFaceService;
|
|
}
|
|
|
|
public async Task<Pagination<AppointmentPageResponse>> GetPageAsync(AppointmentPageRequest request)
|
|
{
|
|
var factory = _currentUser.GetStringTenantId();
|
|
|
|
return await _dbContext.Queryable<VisitorAppointmentEntity>()
|
|
.WhereIF(request.SearchDateTimePeriod.HasValue(),
|
|
x => x.Date >= request.SearchDateTimePeriod.Start && x.Date <= request.SearchDateTimePeriod.End)
|
|
.WhereIF(request.Search.IsPresent(), x => x.Code == request.Search)
|
|
.Where(x => x.Factory == factory)
|
|
.Select<AppointmentPageResponse>()
|
|
.ToPageListAsync(request);
|
|
}
|
|
|
|
public async Task<List<AppointmentDetailResponse>> GetAppointmentDetailsByIdAsync(string no)
|
|
{
|
|
return await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.Where(x => x.No == no)
|
|
.Select(x => new AppointmentDetailResponse
|
|
{
|
|
Id = x.Id,
|
|
No = x.No,
|
|
UserNo = x.UserNo,
|
|
IdType = x.IdType,
|
|
IdNo = x.IdNo,
|
|
Name = x.Name,
|
|
Phone = x.Phone,
|
|
LicensePlate = x.LicensePlate,
|
|
IsEnterDoorArea = x.IsEnterDoorArea,
|
|
ApplyDoorArea = SqlFunc.Subqueryable<AppointmentAreaEntity>().Where(p => p.CustomCode == x.ApplyDoorArea).Select(p => p.Name),
|
|
DoorStart = x.DoorStart,
|
|
DoorEnd = x.DoorEnd,
|
|
IsEnterWorkplace = x.IsEnterWorkplace,
|
|
ApplyWorkplaceAreas = SqlFunc.Subqueryable<AppointmentAreaEntity>().Where(p => x.ApplyWorkplaceAreas.ToString().Contains(p.CustomCode)).ToList(p => p.Name),
|
|
WorkplaceStart = x.WorkplaceStart,
|
|
WorkplaceEnd = x.WorkplaceEnd,
|
|
ImageUrl = x.ImageUrl,
|
|
Remark = x.Remark,
|
|
DoorStatus = x.DoorStatus,
|
|
WorkplaceStatus = x.WorkplaceStatus,
|
|
})
|
|
.ToListAsync();
|
|
}
|
|
|
|
public async Task ConfirmAsync(AppointmentConfirmRequest request)
|
|
{
|
|
var detail = await _dbContext.Queryable<VisitorAppointmentDetailEntity>().Where(x => x.Id == request.Id).SingleAsync();
|
|
detail.ThrowIfNull("预约信息不存在");
|
|
|
|
await GenerateTaskAndUpdateFaceAsync(detail.Id, request.Base64Image, DeviceTaskEnumType.Add);
|
|
|
|
if (detail.DoorStatus == VisitorAppointmentDetailStatusEnumType.Wait)
|
|
{
|
|
detail.DoorStatus = VisitorAppointmentDetailStatusEnumType.Arrived;
|
|
}
|
|
|
|
detail.ArrivedTime = DateTime.Now;
|
|
await _dbContext.UpdateAsync(detail);
|
|
}
|
|
|
|
public async Task GenerateTaskAndUpdateFaceAsync(long detailId, string base64, DeviceTaskEnumType deviceTaskType)
|
|
{
|
|
var detail = await _dbContext.Queryable<VisitorAppointmentDetailEntity>().Where(x => x.Id == detailId).SingleAsync();
|
|
detail.ThrowIfNull("预约信息不存在");
|
|
|
|
var areaCodes = GetValidAreaCodes(detail);
|
|
var existsAreaCodes = await _dbContext.Queryable<AppointmentAreaEntity>().Where(x => areaCodes.Contains(x.CustomCode)).Select(x => x.CustomCode).ToListAsync();
|
|
|
|
//当前分配的设备组code
|
|
var deviceGroupCodes = await _dbContext.Queryable<AppointmentAreaAssignmentEntity>()
|
|
.Where(x => existsAreaCodes.Contains(x.CustomCode))
|
|
.Select(x => x.DeviceGroupCode)
|
|
.ToListAsync();
|
|
|
|
var deviceCodes = await _dbContext.Queryable<DeviceGroupRelationshipEntity>().Where(x => deviceGroupCodes.Contains(x.GroupCode)).Select(x => x.DeviceCode).ToListAsync();
|
|
var deviceUniqueNos = await _dbContext.Queryable<DeviceEntity>().Where(x => deviceCodes.Contains(x.Code)).Select(x => new { x.UniqueNo, x.TenantId }).ToListAsync();
|
|
|
|
await _dbContext.InsertAsync(deviceUniqueNos.Select(x => new DeviceTaskEntity
|
|
{
|
|
DeviceType = DeviceTypeEnumType.Door,
|
|
DeviceUniqueNo = x.UniqueNo,
|
|
Status = DeviceTaskStatusEnumType.Wait,
|
|
UserNo = detail.UserNo,
|
|
Type = deviceTaskType,
|
|
Priority = 100,
|
|
TenantId = x.TenantId,
|
|
Source = DeviceTaskSourceEnumType.Appointment,
|
|
Version = 0
|
|
}).ToList());
|
|
|
|
await _gainfoFaceService.UploadExternalFaceAsync(new GainfoUploadFaceRequest
|
|
{
|
|
UserNo = detail.IdNo,
|
|
Face = base64
|
|
});
|
|
}
|
|
|
|
|
|
private static IEnumerable<string> GetValidAreaCodes(VisitorAppointmentDetailEntity detail)
|
|
{
|
|
if (detail.IsEnterDoorArea)
|
|
{
|
|
yield return detail.ApplyDoorArea;
|
|
}
|
|
}
|
|
|
|
|
|
public async Task<AppointmentDetailResponse> GetTodayByIdNoAsync(string idNo, string factory)
|
|
{
|
|
var protector = _dataProtectionProvider.CreateProtector("gainfo:external:idno");
|
|
try
|
|
{
|
|
idNo = protector.Unprotect(idNo);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//ignore
|
|
}
|
|
|
|
var now = DateTime.Now;
|
|
return await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.LeftJoin<GainfoEntity>((x, ga) => ga.IdNo == x.IdNo)
|
|
.Where((x, ga) => ga.IdNo == idNo)
|
|
.Where(x => (x.IsEnterDoorArea && SqlFunc.DateIsSame(x.DoorStart, now) && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Wait))
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Where(p => p.No == x.No).Any())
|
|
.Select(x => new AppointmentDetailResponse
|
|
{
|
|
No = x.No,
|
|
Mst = SqlFunc.Subqueryable<VisitorAppointmentEntity>()
|
|
.LeftJoin<GainfoEntity>((p, ga) => p.Code == ga.Code)
|
|
.Where((p, ga) => p.No == x.No)
|
|
.First((p, ga) => new AppointmentPageResponse
|
|
{
|
|
No = p.No,
|
|
Title = p.Title,
|
|
Code = p.Code,
|
|
Name = ga.Name,
|
|
Source = p.Source,
|
|
Date = p.Date,
|
|
Remark = p.Remark,
|
|
Factory = p.Factory,
|
|
Reason = p.Reason
|
|
}, false)
|
|
}, true)
|
|
.FirstAsync();
|
|
}
|
|
|
|
public async Task<Pagination<AppointmentDetailResponse>> GetRecordPageByIdNoAsync([FromQuery] AppointmentIdNoPageRequest request)
|
|
{
|
|
var protector = _dataProtectionProvider.CreateProtector("gainfo:external:idno");
|
|
try
|
|
{
|
|
request.IdNo = protector.Unprotect(request.IdNo);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//ignore
|
|
}
|
|
|
|
var page = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.LeftJoin<GainfoEntity>((x, ga) => x.UserNo == ga.No)
|
|
.Where((x, ga) => ga.IdNo == request.IdNo)
|
|
.OrderBy(x => x.CreateTime)
|
|
.Select<AppointmentDetailResponse>()
|
|
.ToPageListAsync(request);
|
|
|
|
return page;
|
|
}
|
|
|
|
|
|
public async Task<List<AppointmentDetailResponse>> GetRecordListAsync(string factory, VisitorAppointmentDetailStatusEnumType? status, DateTime start, DateTime end)
|
|
{
|
|
return await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.LeftJoin<GainfoEntity>((x, ga) => ga.IdNo == x.IdNo)
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Any())
|
|
.Where(x => x.IsEnterDoorArea)
|
|
.WhereIF(status.HasValue, x => x.DoorStatus == status)
|
|
.Where(x => x.DoorStart >= start && x.DoorEnd <= end)
|
|
.Select(x => new AppointmentDetailResponse
|
|
{
|
|
No = x.No,
|
|
Mst = SqlFunc.Subqueryable<VisitorAppointmentEntity>()
|
|
.LeftJoin<GainfoEntity>((p, ga) => p.Code == ga.Code)
|
|
.Where((p, ga) => p.No == x.No)
|
|
.First((p, ga) => new AppointmentPageResponse
|
|
{
|
|
No = p.No,
|
|
Title = p.Title,
|
|
Code = p.Code,
|
|
Name = ga.Name,
|
|
Source = p.Source,
|
|
Date = p.Date,
|
|
Remark = p.Remark,
|
|
Factory = p.Factory,
|
|
Reason = p.Reason
|
|
}, false)
|
|
}, true)
|
|
.ToListAsync();
|
|
}
|
|
|
|
|
|
/// <inheritdoc />
|
|
public async Task<AppointmentSummaryResponse> GetSummaryAsync(string factory, DateTime start, DateTime end)
|
|
{
|
|
var total = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.Where(x => x.IsEnterDoorArea && ((x.DoorStart >= start && x.DoorStart <= end) || (x.DoorEnd >= start && x.DoorEnd <= end))
|
|
//|| (x.IsEnterWorkplace && ((x.WorkplaceStart >= start && x.WorkplaceStart <= end) || (x.WorkplaceEnd >= start && x.WorkplaceEnd <= end)))
|
|
)
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Any())
|
|
.CountAsync();
|
|
|
|
var @in = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.Where(x => x.IsEnterDoorArea && ((x.DoorStart >= start && x.DoorStart <= end) || (x.DoorEnd >= start && x.DoorEnd <= end))
|
|
// || (x.IsEnterWorkplace && ((x.WorkplaceStart >= start && x.WorkplaceStart <= end) || (x.WorkplaceEnd >= start && x.WorkplaceEnd <= end)))
|
|
)
|
|
.Where(x => (x.IsEnterDoorArea && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived)
|
|
//|| (x.IsEnterWorkplace && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Arrived)
|
|
)
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Any())
|
|
.CountAsync();
|
|
|
|
var notIn = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.Where(x => x.IsEnterDoorArea && ((x.DoorStart >= start && x.DoorStart <= end) || (x.DoorEnd >= start && x.DoorEnd <= end))
|
|
//|| (x.IsEnterWorkplace && ((x.WorkplaceStart >= start && x.WorkplaceStart <= end) || (x.WorkplaceEnd >= start && x.WorkplaceEnd <= end)))
|
|
)
|
|
.Where(x => (x.IsEnterDoorArea && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Wait)
|
|
//|| (x.IsEnterWorkplace && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Wait)
|
|
)
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Any())
|
|
.CountAsync();
|
|
|
|
var leave = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.Where(x => (x.IsEnterDoorArea && x.DoorEnd >= start && x.DoorEnd <= end) ||
|
|
(x.IsEnterWorkplace && x.WorkplaceEnd >= start && x.WorkplaceEnd <= end)
|
|
)
|
|
.Where(x => (x.IsEnterDoorArea && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Leave)
|
|
//|| (x.IsEnterWorkplace && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Leave)
|
|
)
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Any())
|
|
.CountAsync();
|
|
|
|
var notLeave = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
|
|
.Where(x => (x.IsEnterDoorArea && x.DoorEnd >= start && x.DoorEnd <= end) ||
|
|
(x.IsEnterWorkplace && x.WorkplaceEnd >= start && x.WorkplaceEnd <= end)
|
|
)
|
|
.Where(x => (x.IsEnterDoorArea && x.DoorStatus != VisitorAppointmentDetailStatusEnumType.Leave)
|
|
// || (x.IsEnterWorkplace && x.WorkplaceStatus != VisitorAppointmentDetailStatusEnumType.Leave)
|
|
)
|
|
.Where(x => SqlFunc.Subqueryable<VisitorAppointmentEntity>().Where(p => p.Factory == factory).Any())
|
|
.CountAsync();
|
|
|
|
return new AppointmentSummaryResponse
|
|
{
|
|
Total = total,
|
|
In = @in,
|
|
NotIn = notIn,
|
|
Leave = leave,
|
|
NotLeave = notLeave
|
|
};
|
|
}
|
|
} |