717 lines
33 KiB
C#
717 lines
33 KiB
C#
using Dlhis.Basic.Api;
|
||
using Dlhis.Basic.Api.Requests;
|
||
using Dlhis.Constants;
|
||
using Dlhis.Dormitory.Api;
|
||
using Dlhis.Dormitory.Api.Request;
|
||
using Dlhis.Entity.Basic.Entity;
|
||
using Dlhis.Entity.Basic.Enums;
|
||
using Dlhis.Entity.Device.Entities;
|
||
using Dlhis.Entity.Device.Enums;
|
||
using Dlhis.Entity.Device.Models;
|
||
using Dlhis.Entity.Dormitory.Entity;
|
||
using Dlhis.Jip.Api;
|
||
using Dlhis.Jip.Api.Requests;
|
||
using Dlhis.ScheduledTask.DeviceUploadLog.Request;
|
||
using Dlhis.ScheduledTask.DeviceUploadLog.Response;
|
||
using Kurisu.AspNetCore.Authentication.Abstractions;
|
||
using Kurisu.AspNetCore.Cache;
|
||
using Kurisu.AspNetCore.CustomClass;
|
||
using Kurisu.AspNetCore.DataAccess.Dto;
|
||
using Kurisu.AspNetCore.DataAccess.Entity;
|
||
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
||
using Kurisu.AspNetCore.Utils.Extensions;
|
||
using SqlSugar;
|
||
|
||
namespace Dlhis.ScheduledTask.DeviceUploadLog.Services.Implements;
|
||
|
||
public class DeviceUploadLogService : IDeviceUploadLogService
|
||
{
|
||
private readonly IDbContext _dbContext;
|
||
private readonly RedisCache _redisCache;
|
||
private readonly IDormitoryRoomPowerSwitchApi _dormitoryRoomPowerSwitchApi;
|
||
private readonly ICurrentUser _currentUser;
|
||
private readonly IJinkoJipApi _jinkoJipApi;
|
||
private readonly ILogger<DeviceUploadLogService> _logger;
|
||
private readonly IDingTalkApi _dingTalkApi;
|
||
|
||
public DeviceUploadLogService(IDbContext dbContext,
|
||
RedisCache redisCache,
|
||
IDormitoryRoomPowerSwitchApi dormitoryRoomPowerSwitchApi,
|
||
ICurrentUser currentUser,
|
||
IJinkoJipApi jinkoJipApi,
|
||
ILogger<DeviceUploadLogService> logger,
|
||
IDingTalkApi dingTalkApi)
|
||
{
|
||
_dbContext = dbContext;
|
||
_redisCache = redisCache;
|
||
_dormitoryRoomPowerSwitchApi = dormitoryRoomPowerSwitchApi;
|
||
_currentUser = currentUser;
|
||
_jinkoJipApi = jinkoJipApi;
|
||
_logger = logger;
|
||
_dingTalkApi = dingTalkApi;
|
||
}
|
||
|
||
public async Task UploadLogsAsync(List<DeviceUploadLogUploadRequest> requests)
|
||
{
|
||
var deviceUniqueNos = requests.Select(x => x.DeviceUniqueNo).Distinct().ToList();
|
||
var devices = await _dbContext.Queryable<DeviceEntity>().Where(x => deviceUniqueNos.Contains(x.UniqueNo)).ToListAsync();
|
||
var existsDeviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
|
||
|
||
var deviceCodeInEFenceMap = await GetDeviceCodeInEFencesAsync(devices.Select(x => x.Code).ToList());
|
||
|
||
var userCodes = requests.Where(x => x.UserUniqueNo.IsPresent()).Select(x => x.UserUniqueNo).Distinct().ToList();
|
||
var gainfo1 = await _dbContext.Queryable<GainfoEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
|
||
var gainfo2 = await _dbContext.Queryable<GainfoEntity>().AS("GainfoLeave").Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
|
||
var gainfoCardNos = requests.Where(x => x.CardNo.IsPresent() && x.UserUniqueNo != x.CardNo).Select(x => x.CardNo).Distinct().ToList();
|
||
var gainfo3 = await _dbContext.Queryable<GainfoEntity>().Where(x => gainfoCardNos.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync();
|
||
var gainfos = gainfo1.Concat(gainfo2).Concat(gainfo3).DistinctBy(x => x.Code).ToList();
|
||
|
||
var userCodes2 = gainfos.Select(x => x.Code).Distinct().ToList();
|
||
|
||
var factories = devices.Select(x => x.TenantId).Distinct().ToList();
|
||
var workGridTimePeriods = await _dbContext.Queryable<WorkGridTimePeriodEntity>()
|
||
.Where(x => factories.Contains(x.TenantId))
|
||
.Select(x => new
|
||
{
|
||
x.Type,
|
||
x.Start,
|
||
x.End,
|
||
x.Before,
|
||
x.After,
|
||
x.TenantId
|
||
})
|
||
.ToListAsync();
|
||
|
||
var min = DateOnly.FromDateTime(requests.Min(x => x.RaiseDateTime)).AddDays(-1);
|
||
var max = DateOnly.FromDateTime(requests.Max(x => x.RaiseDateTime));
|
||
|
||
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>()
|
||
.Where(x => x.Date >= min && x.Date <= max && userCodes2.Contains(x.UserCode))
|
||
.Select(x => new
|
||
{
|
||
x.UserCode,
|
||
x.WorkGridCode,
|
||
x.Date,
|
||
x.PeriodType
|
||
})
|
||
.ToListAsync();
|
||
|
||
var workGrids = await GetAllWorkGridAsync();
|
||
var workGridUsers = await _dbContext.Queryable<WorkGridUserEntity>().Where(x => userCodes2.Contains(x.UserCode)).ToListAsync();
|
||
|
||
var inserts = new List<DeviceUploadLogEntity>();
|
||
foreach (var request in requests.Where(x => existsDeviceUniqueNos.Contains(x.DeviceUniqueNo)))
|
||
{
|
||
var device = devices.First(x => x.UniqueNo == request.DeviceUniqueNo);
|
||
//智能空开判断
|
||
if (deviceCodeInEFenceMap.TryGetValue(device.Code, out var fence))
|
||
{
|
||
await HandlerPowerSwitchAsync(fence.Code, request.UserUniqueNo, fence.DirectionType);
|
||
}
|
||
|
||
if (await _dbContext.Queryable<DeviceUploadLogEntity>().Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo
|
||
&& x.SerialNo == request.SerialNo
|
||
&& x.RaiseDateTime == request.RaiseDateTime).AnyAsync())
|
||
{
|
||
continue;
|
||
}
|
||
|
||
var currentGainfo = gainfos.FirstOrDefault(x => x.Code == request.UserUniqueNo);
|
||
var userType = currentGainfo?.Type;
|
||
var needUpload = ((userType is GainfoUserTypeEnumType.Normal or GainfoUserTypeEnumType.SecurityWhite)
|
||
&& (device.Type == DeviceTypeEnumType.Attendance || (device.Type == DeviceTypeEnumType.Door && device.AsAttendance)));
|
||
var dataType = device.Type == DeviceTypeEnumType.Attendance
|
||
? DeviceUploadLogTypeEnumType.Attendance
|
||
: DeviceUploadLogTypeEnumType.Door;
|
||
|
||
var workGridInfo = new WorkGridInfo();
|
||
var currentWorkGridTimePeriods = workGridTimePeriods.Where(x => x.TenantId == device.TenantId).ToList();
|
||
var currentWorkGridSchedules = workGridSchedules.Where(x => x.UserCode == request.UserUniqueNo).ToList();
|
||
var currentWorkGridUser = workGridUsers.FirstOrDefault(x => x.UserCode == request.UserUniqueNo); //可能被删除,但还存在当天的排班
|
||
|
||
if (needUpload && currentWorkGridTimePeriods.Any() && (currentWorkGridUser != null || currentWorkGridSchedules.Any()))
|
||
{
|
||
workGridInfo.TimeSetting = currentWorkGridTimePeriods.Select(x => new
|
||
{
|
||
Type = x.Type.GetDescription(),
|
||
x.Before,
|
||
x.Start,
|
||
x.End,
|
||
x.After,
|
||
x.TenantId
|
||
}).ToList();
|
||
|
||
if (currentWorkGridUser != null)
|
||
{
|
||
var currentWorkGrid = workGrids.First(x => x.Code == currentWorkGridUser.WorkGridCode);
|
||
workGridInfo.WorkGrid = new WorkGridInfoDetail
|
||
{
|
||
WorkGridCode = currentWorkGrid.Code,
|
||
WorkGridName = currentWorkGrid.Name,
|
||
LeaderUserCode = currentWorkGrid.LeaderUserCode
|
||
};
|
||
}
|
||
|
||
var currentDate = request.RaiseDateTime.Date;
|
||
var currentDateOnly = DateOnly.FromDateTime(currentDate);
|
||
|
||
//白班判断
|
||
var dayTimePeriod = currentWorkGridTimePeriods.FirstOrDefault(x => x.Type == WorkGridTimePeriodEnumType.Day);
|
||
if (dayTimePeriod != null)
|
||
{
|
||
var currentDayWorkGridSchedule = currentWorkGridSchedules.FirstOrDefault(x => x.PeriodType == WorkGridTimePeriodEnumType.Day && x.Date == currentDateOnly);
|
||
if (currentDayWorkGridSchedule != null)
|
||
{
|
||
var start = currentDate.Add(dayTimePeriod.Start.AddMinutes(-dayTimePeriod.Before).ToTimeSpan());
|
||
var end = currentDate.Add(dayTimePeriod.End.AddMinutes(dayTimePeriod.After).ToTimeSpan());
|
||
|
||
if (request.RaiseDateTime >= start && request.RaiseDateTime <= end)
|
||
{
|
||
workGridInfo.PeriodType = WorkGridTimePeriodEnumType.Day;
|
||
var currentWorkGrid = workGrids.First(x => x.Code == currentDayWorkGridSchedule.WorkGridCode);
|
||
workGridInfo.WorkGrid = new WorkGridInfoDetail
|
||
{
|
||
WorkGridCode = currentWorkGrid.Code,
|
||
WorkGridName = currentWorkGrid.Name,
|
||
LeaderUserCode = currentWorkGrid.LeaderUserCode
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
//晚班判断
|
||
var nightTimePeriod = currentWorkGridTimePeriods.FirstOrDefault(x => x.Type == WorkGridTimePeriodEnumType.Night);
|
||
if (nightTimePeriod != null)
|
||
{
|
||
var currentNightWorkGridSchedules = currentWorkGridSchedules
|
||
.Where(x => x.PeriodType == WorkGridTimePeriodEnumType.Night)
|
||
.Where(x => x.Date == currentDateOnly || x.Date == currentDateOnly.AddDays(-1))
|
||
.ToList();
|
||
|
||
if (currentNightWorkGridSchedules.Any())
|
||
{
|
||
var startTime = nightTimePeriod.Start.AddMinutes(-nightTimePeriod.Before);
|
||
var endTime = nightTimePeriod.End.AddMinutes(nightTimePeriod.After);
|
||
|
||
if (currentNightWorkGridSchedules.Any(x => x.Date == currentDateOnly))
|
||
{
|
||
var start = currentDateOnly.ToDateTime(startTime);
|
||
var end = currentDateOnly.ToDateTime(new TimeOnly(23, 59, 59, 999));
|
||
|
||
if (request.RaiseDateTime >= start && request.RaiseDateTime <= end)
|
||
{
|
||
workGridInfo.PeriodType = WorkGridTimePeriodEnumType.Night;
|
||
var currentWorkGrid = workGrids.First(x => x.Code == currentNightWorkGridSchedules.First(p => p.Date == currentDateOnly).WorkGridCode);
|
||
workGridInfo.WorkGrid = new WorkGridInfoDetail
|
||
{
|
||
WorkGridCode = currentWorkGrid.Code,
|
||
WorkGridName = currentWorkGrid.Name,
|
||
LeaderUserCode = currentWorkGrid.LeaderUserCode
|
||
};
|
||
}
|
||
}
|
||
|
||
if (currentNightWorkGridSchedules.Any(x => x.Date == currentDateOnly.AddDays(-1)))
|
||
{
|
||
var start = currentDateOnly.AddDays(-1).ToDateTime(startTime);
|
||
var end = currentDateOnly.ToDateTime(endTime);
|
||
|
||
if (request.RaiseDateTime >= start && request.RaiseDateTime <= end)
|
||
{
|
||
workGridInfo.PeriodType = WorkGridTimePeriodEnumType.Night;
|
||
var currentWorkGrid = workGrids.First(x => x.Code == currentNightWorkGridSchedules.First(p => p.Date == currentDateOnly.AddDays(-1)).WorkGridCode);
|
||
workGridInfo.WorkGrid = new WorkGridInfoDetail
|
||
{
|
||
WorkGridCode = currentWorkGrid.Code,
|
||
WorkGridName = currentWorkGrid.Name,
|
||
LeaderUserCode = currentWorkGrid.LeaderUserCode
|
||
};
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
needUpload = workGridInfo.WorkGrid == null || workGridInfo.PeriodType.HasValue;
|
||
workGridInfo.IsError = !needUpload;
|
||
if (!needUpload)
|
||
{
|
||
try
|
||
{
|
||
await _dingTalkApi.SendWorkMessageByWorkGridAsync(new JinkoSendWorkMessageRequest
|
||
{
|
||
Content = $"{workGridInfo.WorkGrid.WorkGridName}的网格长,你好,检测到你网格中 {currentGainfo.Name}({currentGainfo.Code}){request.RaiseDateTime.ToString("yyyy年MM月dd日")}未排班,但是有考勤记录,请前往系统处理!",
|
||
WorkCodes = new List<string> { workGridInfo.WorkGrid.LeaderUserCode }
|
||
});
|
||
|
||
await _dingTalkApi.SendWorkMessageByWorkGridAsync(new JinkoSendWorkMessageRequest
|
||
{
|
||
Content = $"{currentGainfo.Name}({currentGainfo.Code},检测到你在{workGridInfo.WorkGrid.WorkGridName}网格中,当日未排班,考勤记录不生效,请立即联系网格长",
|
||
WorkCodes = new List<string> { currentGainfo.Code }
|
||
});
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
_logger.LogError(e, "推送信息错误schedule:{error}", e.Message);
|
||
}
|
||
}
|
||
}
|
||
|
||
inserts.Add(new DeviceUploadLogEntity
|
||
{
|
||
DeviceCode = device.Code,
|
||
DeviceUniqueNo = request.DeviceUniqueNo,
|
||
UserUniqueNo = request.UserUniqueNo,
|
||
UserType = userType,
|
||
RaiseDateTime = request.RaiseDateTime,
|
||
SerialNo = request.SerialNo ?? string.Empty,
|
||
Type = dataType,
|
||
NeedUpload = needUpload,
|
||
TenantId = device.TenantId,
|
||
Status = request.Status ?? true,
|
||
Image = request.Image,
|
||
WorkGridInfo = workGridInfo.ToJson(),
|
||
CreatedBy = 1,
|
||
ModifiedBy = 1
|
||
});
|
||
}
|
||
|
||
await _dbContext.InsertAsync(inserts);
|
||
}
|
||
|
||
private async Task<List<WorkGridEntity>> GetAllWorkGridAsync()
|
||
{
|
||
_dbContext.Client.QueryFilter.ClearAndBackup<ISoftDeleted>();
|
||
try
|
||
{
|
||
return await _dbContext.Queryable<WorkGridEntity>().ToListAsync();
|
||
}
|
||
finally
|
||
{
|
||
_dbContext.Client.QueryFilter.Restore();
|
||
}
|
||
|
||
}
|
||
|
||
private async Task<Dictionary<Guid, EFenceEntity>> GetDeviceCodeInEFencesAsync(List<Guid> deviceCodes)
|
||
{
|
||
var eFenceDeviceRelations = await _dbContext.Queryable<EFenceDeviceRelationEntity>()
|
||
.Where(x => deviceCodes.Contains(x.DeviceCode))
|
||
.ToListAsync();
|
||
|
||
var eFenceCodes = eFenceDeviceRelations.Select(x => x.EFenceCode).Distinct().ToList();
|
||
var eFences = await _dbContext.Queryable<EFenceEntity>().Where(x => eFenceCodes.Contains(x.Code)).ToListAsync();
|
||
|
||
//二次过滤
|
||
var eFenceCodesNew = eFences.Select(x => x.Code).Distinct().ToList();
|
||
eFenceDeviceRelations = eFenceDeviceRelations.Where(x => eFenceCodesNew.Contains(x.EFenceCode)).ToList();
|
||
|
||
|
||
return eFenceDeviceRelations.ToDictionary(x => x.DeviceCode, x => eFences.First(y => y.Code == x.EFenceCode));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 宿舍只能空开触发
|
||
/// </summary>
|
||
/// <param name="eFenceCode"></param>
|
||
/// <param name="userCode"></param>
|
||
/// <param name="directionType"></param>
|
||
private async Task HandlerPowerSwitchAsync(Guid eFenceCode, string userCode, DeviceDeployDirectionEnumType directionType)
|
||
{
|
||
try
|
||
{
|
||
//调用获取人员信息接口
|
||
var roomInfo = await _dormitoryRoomPowerSwitchApi.GetUserRoomInfoAsync<DormitoryResponse>(userCode);
|
||
if (!roomInfo.MCB)
|
||
{
|
||
_logger.LogInformation("MCB未开启, userCode:{userCode} directionType:{directionType}", userCode, directionType);
|
||
return;
|
||
}
|
||
|
||
var room = await _dbContext.Queryable<DormitoryRoomEntity>().Where(x => x.RoomId == roomInfo.RoomId).SingleAsync();
|
||
if (room == null)
|
||
{
|
||
//这里会有并发问题,加分布式锁
|
||
await using var lockHandler = await _redisCache.LockAsync("dormitory_room_key_" + roomInfo.RoomId, TimeSpan.FromSeconds(10), retryCount: 5);
|
||
if (lockHandler.Acquired)
|
||
{
|
||
room = new DormitoryRoomEntity
|
||
{
|
||
EFenceCode = eFenceCode,
|
||
RoomId = roomInfo.RoomId,
|
||
RoomNo = roomInfo.RoomNo,
|
||
HotelId = roomInfo.HotelId,
|
||
PowerSwitch = true
|
||
};
|
||
|
||
await _dbContext.InsertAsync(room);
|
||
|
||
var personEntities = roomInfo.Persons.Select(x => new DormitoryRoomPersonEntity
|
||
{
|
||
RoomId = roomInfo.RoomId,
|
||
UserCode = x.UserCode,
|
||
UserName = x.UserName,
|
||
In = true,
|
||
IsDeleted = false
|
||
})
|
||
.ToList();
|
||
|
||
await _dbContext.InsertAsync(personEntities);
|
||
|
||
var person = await _dbContext.Queryable<DormitoryRoomPersonEntity>()
|
||
.Where(x => x.RoomId != roomInfo.RoomId && x.UserCode == userCode)
|
||
.FirstAsync();
|
||
if (person != null)
|
||
{
|
||
await _dbContext.DeleteAsync(person);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var existsPersons = await _dbContext.Queryable<DormitoryRoomPersonEntity>()
|
||
.Where(x => x.RoomId == roomInfo.RoomId)
|
||
.ToListAsync();
|
||
|
||
//根据roomInfo.Persons和existsPersons不在当前房间的人
|
||
var toDeletePersons = existsPersons.Where(x => roomInfo.Persons.All(p => p.UserCode != x.UserCode)).ToList();
|
||
if (toDeletePersons.Any())
|
||
{
|
||
await _dbContext.DeleteAsync(toDeletePersons);
|
||
}
|
||
|
||
//需要新增的
|
||
var toAddPersons = roomInfo.Persons.Where(x => existsPersons.All(p => p.UserCode != x.UserCode)).ToList();
|
||
if (toAddPersons.Any())
|
||
{
|
||
var personEntities = toAddPersons.Select(x => new DormitoryRoomPersonEntity()
|
||
{
|
||
RoomId = roomInfo.RoomId,
|
||
UserCode = x.UserCode,
|
||
UserName = x.UserName,
|
||
In = true,
|
||
IsDeleted = false
|
||
}).ToList();
|
||
|
||
await _dbContext.InsertAsync(personEntities);
|
||
}
|
||
|
||
room.EFenceCode = eFenceCode;
|
||
await _dbContext.UpdateAsync(room);
|
||
}
|
||
|
||
|
||
//如果DormitoryRoomPersonEntity.in都为false,断电, 否则上电(前提是DormitoryRoomEntity.PowerSwitch==false)
|
||
// 查询房间所有人员
|
||
var persons = await _dbContext.Queryable<DormitoryRoomPersonEntity>()
|
||
.Where(x => x.RoomId == roomInfo.RoomId)
|
||
.ToListAsync();
|
||
|
||
persons.ForEach(x =>
|
||
{
|
||
if (x.UserCode == userCode)
|
||
{
|
||
x.In = directionType == DeviceDeployDirectionEnumType.Entry;
|
||
}
|
||
});
|
||
await _dbContext.UpdateAsync(persons);
|
||
|
||
// 如果所有人都不在房间,且当前房间是通电状态,则断电
|
||
if (persons.All(x => !x.In))
|
||
{
|
||
if (room.PowerSwitch)
|
||
{
|
||
room.PowerSwitch = false; // 断电
|
||
await _dbContext.UpdateAsync(room);
|
||
await _dormitoryRoomPowerSwitchApi.SwitchAsync(new PowerSwitchRequest(room.RoomId, 0));
|
||
_logger.LogInformation("房间下电{roomNo}", room.RoomNo);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 只在房间断电状态时才上电
|
||
if (!room.PowerSwitch)
|
||
{
|
||
room.PowerSwitch = true; // 上电
|
||
await _dbContext.UpdateAsync(room);
|
||
await _dormitoryRoomPowerSwitchApi.SwitchAsync(new PowerSwitchRequest(room.RoomId, 1));
|
||
_logger.LogInformation("房间上电{roomNo}", room.RoomNo);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
_logger.LogError(e, "宿舍空开触发失败, userCode:{userCode} directionType:{directionType} error:{error}", userCode, directionType, e.Message);
|
||
}
|
||
}
|
||
|
||
public async Task<List<DeviceUploadLogResponse>> GetMyRecordsAsync(DeviceUploadLogMyRecordRequest request)
|
||
{
|
||
var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty;
|
||
|
||
return await _dbContext.Queryable<DeviceUploadLogEntity>()
|
||
.LeftJoin<DeviceEntity>((log, d) => log.DeviceUniqueNo == d.UniqueNo)
|
||
.Where(log => log.UserUniqueNo == jinkoCode)
|
||
.Where(log => log.Status)
|
||
.WhereIF(request.DateTimePeriod.HasValue(), log => log.RaiseDateTime >= request.DateTimePeriod.Start && log.RaiseDateTime <= request.DateTimePeriod.End)
|
||
.Where((log, d) => d.Type == DeviceTypeEnumType.Attendance || (d.Type == DeviceTypeEnumType.Door && d.AsAttendance))
|
||
.OrderBy(log => log.RaiseDateTime)
|
||
.Select((log, d) => new DeviceUploadLogResponse
|
||
{
|
||
OriginUserUniqueNo = log.UserUniqueNo,
|
||
DeviceUniqueNo = log.DeviceUniqueNo,
|
||
Id = log.Id,
|
||
RaiseDateTime = log.RaiseDateTime,
|
||
CreateTime = log.CreateTime,
|
||
SerialNo = log.SerialNo,
|
||
DeployPlace = d.DeployPlace,
|
||
Sync = log.Sync,
|
||
Status = log.Status
|
||
})
|
||
.ToListAsync();
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task ManuallyUploadAsync(List<long> requestIds)
|
||
{
|
||
var requests = await _dbContext.Queryable<DeviceUploadLogEntity>()
|
||
.LeftJoin<DeviceEntity>((x, device) => x.DeviceUniqueNo == device.UniqueNo)
|
||
.Where(x => requestIds.Contains(x.Id))
|
||
.Where(x => x.NeedUpload && x.Sync == false && (x.UserType == GainfoUserTypeEnumType.Normal || x.UserType == GainfoUserTypeEnumType.SecurityWhite))
|
||
.Select((x, device) => new UploadAttendanceRequestItem
|
||
{
|
||
Id = x.Id,
|
||
RaiseDateTime = x.RaiseDateTime,
|
||
ZNOTE = device.DeployPlace,
|
||
ZWORKCODE = x.UserUniqueNo
|
||
})
|
||
.ToListAsync();
|
||
|
||
if (requests.Any())
|
||
{
|
||
foreach (var items in requests.Chunk(500))
|
||
{
|
||
var ids = items.Select(x => x.Id).ToList();
|
||
var r = await _jinkoJipApi.UploadAttendancesAsync(new UploadAttendanceRequest { Data = items.ToList() });
|
||
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();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task ManuallySetTimeInfoAsync(string deviceNo, DateTime start, DateTime end)
|
||
{
|
||
var device = await _dbContext.Queryable<DeviceEntity>().Where(x => x.UniqueNo == deviceNo).SingleAsync();
|
||
(device.Type != DeviceTypeEnumType.Attendance && device.Type != DeviceTypeEnumType.Door).ThrowIfTrue("不支持该设备类型");
|
||
var exists = await _dbContext.Queryable<DeviceUploadLogManuallyEntity>().Where(x => x.DeviceNo == deviceNo).Where(x => x.IsFinished == false).AnyAsync();
|
||
exists.ThrowIfTrue("已存在配置尚未完成");
|
||
|
||
await _dbContext.InsertAsync(new DeviceUploadLogManuallyEntity
|
||
{
|
||
DeviceNo = deviceNo,
|
||
Start = start,
|
||
End = end,
|
||
IsFinished = false
|
||
});
|
||
}
|
||
|
||
public async Task QiaoqiaoGaoshiqingAsync(DeviceUploadLogSecretAddRequest request)
|
||
{
|
||
var gainfo = await _dbContext.Queryable<GainfoEntity>().Where(x => x.Code == request.UserCode).SingleAsync();
|
||
gainfo.ThrowIfNull("人员不存在");
|
||
var device = await _dbContext.Queryable<DeviceEntity>().Where(x => x.UniqueNo == request.DeviceUniqueNo).SingleAsync();
|
||
|
||
await _dbContext.InsertAsync(new DeviceUploadLogEntity
|
||
{
|
||
DeviceUniqueNo = device.UniqueNo,
|
||
UserUniqueNo = request.UserCode,
|
||
UserType = gainfo.Type,
|
||
RaiseDateTime = request.RaiseDateTime,
|
||
Type = device.Type == DeviceTypeEnumType.Attendance
|
||
? DeviceUploadLogTypeEnumType.Attendance
|
||
: DeviceUploadLogTypeEnumType.Door,
|
||
NeedUpload = true,
|
||
Sync = false,
|
||
SerialNo = string.Empty,
|
||
DeviceCode = device.Code,
|
||
TenantId = device.TenantId,
|
||
Status = true,
|
||
Image = null,
|
||
CreatedBy = 1,
|
||
ModifiedBy = 1
|
||
});
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public async Task Test()
|
||
{
|
||
var before60Days = DateTime.Today.AddDays(-60).AddSeconds(1);
|
||
var data = await _dbContext.Queryable<DeviceUploadLogEntity>().Where(x => x.RaiseDateTime < before60Days).OrderBy(x => x.Id).ToPageListAsync(1, 500);
|
||
if (data.Any())
|
||
{
|
||
await _dbContext.DeleteReallyAsync(data);
|
||
|
||
const string tableName = "deviceuploadlog_20250107";
|
||
foreach (var item in data)
|
||
{
|
||
item.Id = 0;
|
||
}
|
||
|
||
await _dbContext.Client.Insertable(data).AS(tableName).ExecuteCommandAsync();
|
||
}
|
||
}
|
||
|
||
public async Task<DateTimePeriod> GetDeviceUploadRecordSettingAsync(string deviceNo)
|
||
{
|
||
var start = await _dbContext.Queryable<DeviceUploadLogEntity>()
|
||
.Where(x => x.DeviceUniqueNo == deviceNo)
|
||
.Select(x => SqlFunc.AggregateMax(x.RaiseDateTime))
|
||
.SingleAsync();
|
||
|
||
//0001-01-01 00:00:00
|
||
return new DateTimePeriod
|
||
{
|
||
Start = start,
|
||
End = DateTime.Now.AddDays(1)
|
||
};
|
||
}
|
||
|
||
public async Task<Pagination<DeviceUploadLogUserResponse>> GetUserPageAsync(DeviceUploadLogUserPageRequest request)
|
||
{
|
||
var r = await _dbContext.Queryable<DeviceUploadLogEntity>()
|
||
.LeftJoin<DeviceEntity>((x, device) => x.DeviceUniqueNo == device.UniqueNo)
|
||
.LeftJoin<GainfoEntity>((x, device, ga) => x.UserUniqueNo == ga.Code)
|
||
.WhereIF(request.SearchDateTimePeriod.HasValue(), x => x.RaiseDateTime >= request.SearchDateTimePeriod.Start
|
||
&& x.RaiseDateTime <= request.SearchDateTimePeriod.End)
|
||
.Where((x, device) => x.NeedUpload)
|
||
.WhereIF(request.Search.IsPresent(), (x, device, ga) =>
|
||
x.UserUniqueNo == request.Search
|
||
|| x.DeviceUniqueNo == request.Search
|
||
)
|
||
.OrderBy(x => x.RaiseDateTime, OrderByType.Desc)
|
||
.Select((x, device, ga) => new DeviceUploadLogUserResponse
|
||
{
|
||
Id = x.Id,
|
||
OriginUserUniqueNo = x.UserUniqueNo,
|
||
DeviceUniqueNo = x.DeviceUniqueNo,
|
||
RaiseDateTime = x.RaiseDateTime,
|
||
CreateTime = x.CreateTime,
|
||
SerialNo = x.SerialNo,
|
||
UserNo = ga.No,
|
||
UserCode = ga.Code,
|
||
UserName = ga.Name,
|
||
DeployPlace = device.DeployPlace,
|
||
NeedUpload = x.NeedUpload,
|
||
Sync = x.Sync,
|
||
Status = x.Status,
|
||
WorkGridInfo = x.WorkGridInfo
|
||
}).ToPageListAsync(request.PageIndex, request.PageSize);
|
||
|
||
return new Pagination<DeviceUploadLogUserResponse>
|
||
{
|
||
PageIndex = request.PageIndex,
|
||
PageSize = request.PageSize,
|
||
Total = 0,
|
||
Data = r
|
||
};
|
||
}
|
||
|
||
public async Task<Pagination<DeviceUploadLogResponse>> GetPageAsync(DeviceUploadLogPageRequest request)
|
||
{
|
||
var type = request.Type switch
|
||
{
|
||
DeviceTypeEnumType.Attendance => DeviceUploadLogTypeEnumType.Attendance,
|
||
DeviceTypeEnumType.Door => DeviceUploadLogTypeEnumType.Door,
|
||
_ => throw new UserFriendlyException("不支持当前设备类型")
|
||
};
|
||
|
||
var userTypes = new List<GainfoUserTypeEnumType?> { request.UserType };
|
||
|
||
if (request.UserType == GainfoUserTypeEnumType.Normal)
|
||
{
|
||
userTypes.Add(GainfoUserTypeEnumType.SecurityWhite);
|
||
}
|
||
|
||
var dayBefore60 = DateTime.Today.AddDays(-60);
|
||
if (request.SearchDateTimePeriod.Start <= dayBefore60 && request.SearchDateTimePeriod.End > dayBefore60)
|
||
{
|
||
throw new UserFriendlyException("请勿跨归档数据查询");
|
||
}
|
||
|
||
var isArchivedSearch = request.SearchDateTimePeriod.End <= dayBefore60;
|
||
|
||
|
||
var table = isArchivedSearch
|
||
? _dbContext.Queryable<DeviceUploadLogEntity>().AS("deviceuploadlog_20250107")
|
||
: _dbContext.Queryable<DeviceUploadLogEntity>();
|
||
|
||
var isNormalSearch = !userTypes.Contains(GainfoUserTypeEnumType.Outsource);
|
||
var isOutsourceSearch = userTypes.Contains(GainfoUserTypeEnumType.Outsource);
|
||
|
||
var r = await table
|
||
.LeftJoin<DeviceEntity>((x, device) => x.DeviceUniqueNo == device.UniqueNo)
|
||
.LeftJoin<GainfoEntity>((x, device, ga) => x.UserUniqueNo == ga.Code)
|
||
.LeftJoin<OutsourceEntity>((x, device, ga, os) => x.UserUniqueNo == os.Code)
|
||
.LeftJoin<GainfoEntity>((x, device, ga, os, gaSap) => gaSap.Code == os.SapCode)
|
||
.Where(x => x.RaiseDateTime >= request.SearchDateTimePeriod.Start && x.RaiseDateTime <= request.SearchDateTimePeriod.End)
|
||
.Where((x, device) => x.Type == type && !SqlFunc.IsNullOrEmpty(x.UserType) && userTypes.Contains(x.UserType))
|
||
.WhereIF(request.Sync.HasValue, x => x.Sync == request.Sync)
|
||
.WhereIF(isOutsourceSearch && request.Search.IsPresent(), (x, device, ga, os) =>
|
||
x.UserUniqueNo == request.Search
|
||
|| x.DeviceUniqueNo == request.Search
|
||
|| os.Supplier == request.Search
|
||
|| os.SapCode == request.Search
|
||
)
|
||
.WhereIF(isNormalSearch && request.UserCode.IsPresent(), (x, device, ga, os) => x.UserUniqueNo == request.UserCode)
|
||
.WhereIF(isNormalSearch && request.DeviceUniqueNo.IsPresent(), (x, device, ga, os) => x.DeviceUniqueNo == request.DeviceUniqueNo)
|
||
.WhereIF(request.Search.IsPresent() && isNormalSearch, (x, device, ga, os) =>
|
||
x.UserUniqueNo == request.Search
|
||
|| x.DeviceUniqueNo == request.Search
|
||
)
|
||
.OrderBy(x => x.RaiseDateTime, OrderByType.Desc)
|
||
.Select((x, device, ga, os, gaSap) => new DeviceUploadLogResponse
|
||
{
|
||
Id = x.Id,
|
||
OriginUserUniqueNo = x.UserUniqueNo,
|
||
OutsourceSupplier = os.Supplier,
|
||
SapUserCode = os.SapCode,
|
||
SapUserName = gaSap.Name,
|
||
DeviceUniqueNo = x.DeviceUniqueNo,
|
||
RaiseDateTime = x.RaiseDateTime,
|
||
CreateTime = x.CreateTime,
|
||
SerialNo = x.SerialNo,
|
||
UserNo = ga.No,
|
||
UserCode = x.UserUniqueNo,
|
||
UserName = ga.Name,
|
||
DeployPlace = device.DeployPlace,
|
||
NeedUpload = x.NeedUpload,
|
||
Sync = x.Sync,
|
||
Status = x.Status,
|
||
WorkGridInfo = x.WorkGridInfo
|
||
}).ToPageListAsync(request.PageIndex, request.PageSize);
|
||
|
||
var userCodes = r.Where(x => x.UserName.IsEmpty()).Select(x => x.UserCode).Distinct().ToList();
|
||
var gainfoLeaves = await _dbContext.Queryable<GainfoLeaveEntity>().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name }).ToListAsync();
|
||
r.ForEach(item =>
|
||
{
|
||
if (item.UserName.IsEmpty())
|
||
{
|
||
item.UserName = gainfoLeaves.FirstOrDefault(x => x.Code == item.UserCode)?.Name;
|
||
}
|
||
});
|
||
|
||
return new Pagination<DeviceUploadLogResponse>
|
||
{
|
||
PageIndex = request.PageIndex,
|
||
PageSize = request.PageSize,
|
||
Total = 0,
|
||
Data = r
|
||
};
|
||
}
|
||
} |