Files
jinko.yikatong/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
2025-03-07 17:14:58 +08:00

462 lines
22 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>()
.LeftJoin<WorkGridEntity>((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<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();
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<string> { 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<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,
}).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,
}).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 => !PeriodType.HasValue;
public object WorkGrid { get; set; }
public WorkGridTimePeriodEnumType? PeriodType { get; set; }
public object TimeSetting { get; set; }
}