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.CustomClass; using Kurisu.AspNetCore.DataAccess.Dto; 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 IDormitoryRoomPowerSwitchApi _dormitoryRoomPowerSwitchApi; private readonly ICurrentUser _currentUser; private readonly IJinkoJipApi _jinkoJipApi; private readonly ILogger _logger; private readonly IDingTalkApi _dingTalkApi; public DeviceUploadLogService(IDbContext dbContext, IDormitoryRoomPowerSwitchApi dormitoryRoomPowerSwitchApi, ICurrentUser currentUser, IJinkoJipApi jinkoJipApi, ILogger logger, IDingTalkApi dingTalkApi) { _dbContext = dbContext; _dormitoryRoomPowerSwitchApi = dormitoryRoomPowerSwitchApi; _currentUser = currentUser; _jinkoJipApi = jinkoJipApi; _logger = logger; _dingTalkApi = dingTalkApi; } public async Task UploadLogsAsync(List requests) { var deviceUniqueNos = requests.Select(x => x.DeviceUniqueNo).Distinct().ToList(); var devices = await _dbContext.Queryable().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().Where(x => userCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name, x.Type }).ToListAsync(); var gainfo2 = await _dbContext.Queryable().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().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() .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() .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 _dbContext.Queryable().ToListAsync(); var workGridUsers = await _dbContext.Queryable().Where(x => userCodes2.Contains(x.UserCode)).ToListAsync(); var inserts = new List(); 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().Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo && x.SerialNo == request.SerialNo && x.RaiseDateTime == request.RaiseDateTime).AnyAsync()) { continue; } if (request.CardNo.IsPresent() && request.UserUniqueNo != request.CardNo) { //UserUniqueNo为老系统档案号(自动生成),CardNo为工号 if (await _dbContext.Queryable() .Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo) .Where(x => x.No == request.UserUniqueNo && x.Code == request.CardNo) .Select(x => x.Code) .AnyAsync()) { request.UserUniqueNo = request.CardNo; } } 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.SendWorkMessageAsync(new JinkoSendWorkMessageRequest { Content = $"{workGridInfo.WorkGrid.WorkGridName}的网格长,你好,检测到你网格中 {currentGainfo.Name}({currentGainfo.Code}){request.RaiseDateTime.ToString("yyyy年MM月dd日")}未排班,但是有考勤记录,请前往系统处理!", WorkCodes = new List { workGridInfo.WorkGrid.LeaderUserCode } }); await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest { Content = $"{currentGainfo.Name}({currentGainfo.Code},检测到你在{workGridInfo.WorkGrid.WorkGridName}网格中,当日未排班,考勤记录不生效,请立即联系网格长", WorkCodes = new List { 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> GetDeviceCodeInEFencesAsync(List deviceCodes) { var eFenceDeviceRelations = await _dbContext.Queryable() .Where(x => deviceCodes.Contains(x.DeviceCode)) .ToListAsync(); var eFenceCodes = eFenceDeviceRelations.Select(x => x.DeviceCode).Distinct().ToList(); var eFences = await _dbContext.Queryable().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)); } /// /// 宿舍只能空开触发 /// /// /// /// private async Task HandlerPowerSwitchAsync(Guid eFenceCode, string userCode, DeviceDeployDirectionEnumType directionType) { try { //调用获取人员信息接口 var roomInfo = await _dormitoryRoomPowerSwitchApi.GetUserRoomInfoAsync(userCode); if (!roomInfo.MCB) { return; } var room = await _dbContext.Queryable().Where(x => x.RoomId == roomInfo.RoomId).SingleAsync(); if (room == null) { 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() .Where(x => x.RoomId != roomInfo.RoomId && x.UserCode == userCode) .FirstAsync(); if (person != null) { await _dbContext.DeleteAsync(person); } } else { var existsPersons = await _dbContext.Queryable() .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() .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)); } } else { // 只在房间断电状态时才上电 if (!room.PowerSwitch) { room.PowerSwitch = true; // 上电 await _dbContext.UpdateAsync(room); await _dormitoryRoomPowerSwitchApi.SwitchAsync(new PowerSwitchRequest(room.RoomId, 1)); } } } catch (Exception e) { _logger.LogError(e, "宿舍空开触发失败, userCode:{userCode} directionType:{directionType} error:{error}", userCode, directionType, e.Message); } } public async Task> GetMyRecordsAsync(DeviceUploadLogMyRecordRequest request) { var jinkoCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode) ?? string.Empty; return await _dbContext.Queryable() .LeftJoin((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(); } /// public async Task ManuallyUploadAsync(List requestIds) { var requests = await _dbContext.Queryable() .LeftJoin((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() .SetColumns(x => x.Sync == true) .SetColumns(x => x.ModifiedTime == DateTime.Now) .Where(x => ids.Contains(x.Id)) .ExecuteCommandAsync(); } } } } /// public async Task ManuallySetTimeInfoAsync(string deviceNo, DateTime start, DateTime end) { var device = await _dbContext.Queryable().Where(x => x.UniqueNo == deviceNo).SingleAsync(); (device.Type != DeviceTypeEnumType.Attendance && device.Type != DeviceTypeEnumType.Door).ThrowIfTrue("不支持该设备类型"); var exists = await _dbContext.Queryable().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().Where(x => x.Code == request.UserCode).SingleAsync(); gainfo.ThrowIfNull("人员不存在"); var device = await _dbContext.Queryable().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 }); } /// public async Task Test() { var before60Days = DateTime.Today.AddDays(-60).AddSeconds(1); var data = await _dbContext.Queryable().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 GetDeviceUploadRecordSettingAsync(string deviceNo) { var start = await _dbContext.Queryable() .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> GetUserPageAsync(DeviceUploadLogUserPageRequest request) { var r = await _dbContext.Queryable() .LeftJoin((x, device) => x.DeviceUniqueNo == device.UniqueNo) .LeftJoin((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 { PageIndex = request.PageIndex, PageSize = request.PageSize, Total = 0, Data = r }; } public async Task> GetPageAsync(DeviceUploadLogPageRequest request) { var type = request.Type switch { DeviceTypeEnumType.Attendance => DeviceUploadLogTypeEnumType.Attendance, DeviceTypeEnumType.Door => DeviceUploadLogTypeEnumType.Door, _ => throw new UserFriendlyException("不支持当前设备类型") }; var userTypes = new List { 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().AS("deviceuploadlog_20250107") : _dbContext.Queryable(); var isNormalSearch = !userTypes.Contains(GainfoUserTypeEnumType.Outsource); var isOutsourceSearch = userTypes.Contains(GainfoUserTypeEnumType.Outsource); var r = await table .LeftJoin((x, device) => x.DeviceUniqueNo == device.UniqueNo) .LeftJoin((x, device, ga) => x.UserUniqueNo == ga.Code) .LeftJoin((x, device, ga, os) => x.UserUniqueNo == os.Code) .LeftJoin((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().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 { PageIndex = request.PageIndex, PageSize = request.PageSize, Total = 0, Data = r }; } }