using Dlhis.Basic.Api; using Dlhis.Basic.Api.Requests; using Dlhis.Constants; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Device.Entities; using Dlhis.Entity.Device.Enums; 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 ICurrentUser _currentUser; private readonly IJinkoJipApi _jinkoJipApi; private readonly ILogger _logger; private readonly IDingTalkApi _dingTalkApi; public DeviceUploadLogService(IDbContext dbContext, ICurrentUser currentUser, IJinkoJipApi jinkoJipApi, ILogger logger, IDingTalkApi dingTalkApi) { _dbContext = dbContext; _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 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() .LeftJoin((x, wg) => x.WorkGridCode == wg.Code) .Where(x => x.Date >= min && x.Date <= max && userCodes2.Contains(x.UserCode)) .Select((x, wg) => new { x.UserCode, x.WorkGridCode, x.Date, x.PeriodType, WorkGridName = wg.Name, wg.LeaderUserCode }) .ToListAsync(); var inserts = new List(); foreach (var request in requests.Where(x => existsDeviceUniqueNos.Contains(x.DeviceUniqueNo))) { 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 device = devices.First(x => x.UniqueNo == request.DeviceUniqueNo); 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(); if (needUpload && currentWorkGridTimePeriods.Any() && currentWorkGridSchedules.Any()) { workGridInfo.TimeSetting = currentWorkGridTimePeriods.Select(x => new { Type = x.Type.GetDescription(), x.Before, x.Start, x.End, x.After, x.TenantId }).ToList(); var currentWorkGridSchedule = currentWorkGridSchedules.First(); workGridInfo.WorkGrid = new { currentWorkGridSchedule.WorkGridCode, currentWorkGridSchedule.WorkGridName, currentWorkGridSchedule.LeaderUserCode }; var currentDate = request.RaiseDateTime.Date; var currentDateOnly = DateOnly.FromDateTime(currentDate); //白班判断 var currentDayWorkGridTimePeriod = currentWorkGridTimePeriods.FirstOrDefault(x => x.Type == WorkGridTimePeriodEnumType.Day); if (currentDayWorkGridTimePeriod != null) { var currentDayWorkGridSchedule = currentWorkGridSchedules.FirstOrDefault(x => x.PeriodType == WorkGridTimePeriodEnumType.Day && x.Date == currentDateOnly); if (currentDayWorkGridSchedule != null) { var start = currentDate.Add(currentDayWorkGridTimePeriod.Start.AddMinutes(-currentDayWorkGridTimePeriod.Before).ToTimeSpan()); var end = currentDate.Add(currentDayWorkGridTimePeriod.End.AddMinutes(currentDayWorkGridTimePeriod.After).ToTimeSpan()); if (request.RaiseDateTime >= start && request.RaiseDateTime <= end) { workGridInfo.PeriodType = WorkGridTimePeriodEnumType.Day; } } } //晚班判断 var currentNightWorkGridTimePeriod = currentWorkGridTimePeriods.FirstOrDefault(x => x.Type == WorkGridTimePeriodEnumType.Night); if (currentNightWorkGridTimePeriod != 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 = currentNightWorkGridTimePeriod.Start.AddMinutes(-currentNightWorkGridTimePeriod.Before); var endTime = currentNightWorkGridTimePeriod.End.AddMinutes(currentNightWorkGridTimePeriod.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; } } 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; } } } } needUpload = workGridInfo.PeriodType.HasValue; if (!needUpload) { try { await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest { Content = $"{currentWorkGridSchedule.WorkGridName}的网格长,你好,检测到你网格中 {currentGainfo.Name}({currentGainfo.Code})今日未排班,但是有考勤记录,请前往系统处理!", WorkCodes = new List { currentWorkGridSchedule.LeaderUserCode } }); } catch (Exception e) { _logger.LogError(e, "推送信息错误:{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); } 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 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, }).ToPageListAsync(request.PageIndex, request.PageSize); return new Pagination { PageIndex = request.PageIndex, PageSize = request.PageSize, Total = 0, Data = r }; } public async Task> GetPageAsync(DeviceUploadLogPageRequest request) { DeviceUploadLogTypeEnumType? 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 r = await _dbContext.Queryable() .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) .WhereIF(request.SearchDateTimePeriod.HasValue(), 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(request.Search.IsPresent() && userTypes.Contains(GainfoUserTypeEnumType.Outsource), (x, device, ga, os) => x.UserUniqueNo == request.Search || x.DeviceUniqueNo == request.Search || os.Supplier == request.Search || os.SapCode == request.Search ) .WhereIF(request.Search.IsPresent() && !userTypes.Contains(GainfoUserTypeEnumType.Outsource), (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 = ga.Code, UserName = ga.Name, DeployPlace = device.DeployPlace, NeedUpload = x.NeedUpload, Sync = x.Sync, Status = x.Status, }).ToPageListAsync(request.PageIndex, request.PageSize); return new Pagination { PageIndex = request.PageIndex, PageSize = request.PageSize, Total = 0, Data = r }; } } public class WorkGridInfo { public bool IsError => !PeriodType.HasValue; public object WorkGrid { get; set; } public WorkGridTimePeriodEnumType? PeriodType { get; set; } public object TimeSetting { get; set; } }