Files
jinko.yikatong/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
2025-03-24 10:54:06 +08:00

507 lines
24 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<DeviceUploadLogService> _logger;
private readonly IDingTalkApi _dingTalkApi;
public DeviceUploadLogService(IDbContext dbContext,
ICurrentUser currentUser,
IJinkoJipApi jinkoJipApi,
ILogger<DeviceUploadLogService> logger,
IDingTalkApi dingTalkApi)
{
_dbContext = dbContext;
_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 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 _dbContext.Queryable<WorkGridEntity>().ToListAsync();
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)))
{
if (await _dbContext.Queryable<DeviceUploadLogEntity>().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<OldDeviceGainfoEntity>()
.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();
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 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
};
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 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
};
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 = $"{workGridInfo.WorkGrid.WorkGridName}的网格长,你好,检测到你网格中 {currentGainfo.Name}({currentGainfo.Code})今日未排班,但是有考勤记录,请前往系统处理!",
WorkCodes = new List<string> { workGridInfo.WorkGrid.LeaderUserCode }
});
await _dingTalkApi.SendWorkMessageAsync(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);
}
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
});
}
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)
{
DeviceUploadLogTypeEnumType? 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 r = await _dbContext.Queryable<DeviceUploadLogEntity>()
.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)
.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,
WorkGridInfo = x.WorkGridInfo
}).ToPageListAsync(request.PageIndex, request.PageSize);
return new Pagination<DeviceUploadLogResponse>
{
PageIndex = request.PageIndex,
PageSize = request.PageSize,
Total = 0,
Data = r
};
}
}
public class WorkGridInfo
{
public bool IsError => TimeSetting != null && PeriodType.HasValue == false;
public WorkGridInfoDetail WorkGrid { get; set; }
public WorkGridTimePeriodEnumType? PeriodType { get; set; }
public object TimeSetting { get; set; }
}
public class WorkGridInfoDetail
{
public Guid WorkGridCode { get; set; }
public string WorkGridName { get; set; }
public string LeaderUserCode { get; set; }
}