219 lines
8.1 KiB
C#
219 lines
8.1 KiB
C#
using Dlhis.Basic.Organization.Services;
|
|
using Dlhis.Basic.Summary.Dto;
|
|
using Dlhis.Basic.Summary.Response;
|
|
using Dlhis.Entity.Basic.Entity;
|
|
using Dlhis.Entity.Basic.Enums;
|
|
using Dlhis.Entity.Device.Entities;
|
|
using Dlhis.Entity.Device.Enums;
|
|
using Kurisu.AspNetCore.Authentication.Abstractions;
|
|
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
|
|
|
|
namespace Dlhis.Basic.Summary.Services.Implements;
|
|
|
|
public class SummaryService : ISummaryService
|
|
{
|
|
private readonly IDbContext _dbContext;
|
|
private readonly IGainfoStore _gainfoStore;
|
|
private readonly ICurrentUser _currentUser;
|
|
|
|
public SummaryService(IDbContext dbContext, IGainfoStore gainfoStore, ICurrentUser currentUser)
|
|
{
|
|
_dbContext = dbContext;
|
|
_gainfoStore = gainfoStore;
|
|
_currentUser = currentUser;
|
|
}
|
|
|
|
public async Task<AttendanceSummaryResponse> GetAttendanceSummaryAsync()
|
|
{
|
|
var now = DateTime.Now;
|
|
var tenantId = _currentUser.GetStringTenantId();
|
|
|
|
var currentDay = DateTime.Today.AddDays(1).AddSeconds(-1);
|
|
var before30Day = DateTime.Today.AddDays(-29);
|
|
var before7Day = DateTime.Today.AddDays(-6);
|
|
|
|
var devices = await _dbContext.Queryable<DeviceEntity>()
|
|
.Where(x => x.Type == DeviceTypeEnumType.Attendance || (x.Type == DeviceTypeEnumType.Door && x.AsAttendance))
|
|
.ToListAsync();
|
|
|
|
var deviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
|
|
|
|
var deviceRegistries = await _dbContext.Queryable<DeviceRegistryEntity>()
|
|
.LeftJoin<DeviceEntity>((x, d) => x.DeviceUniqueNo == d.UniqueNo)
|
|
.Where(x => deviceUniqueNos.Contains(x.DeviceUniqueNo))
|
|
.Select((x, d) => new
|
|
{
|
|
d.HeartbeatInterval,
|
|
x.LastHeartbeatTime
|
|
})
|
|
.ToListAsync();
|
|
|
|
var workingGainfos = await _gainfoStore.Queryable(GainfoStatusEnumType.Working)
|
|
.Where(x => x.Factory == tenantId).ToListAsync();
|
|
var leaveGainfos = await _gainfoStore.Queryable(GainfoStatusEnumType.Leave)
|
|
.Where(x => x.Factory == tenantId)
|
|
.ToListAsync();
|
|
|
|
return new AttendanceSummaryResponse
|
|
{
|
|
DeviceSummary = new AttendanceDeviceSummary
|
|
{
|
|
Total = devices.Count,
|
|
EnableCount = devices.Count(x => x.Enable),
|
|
OnlineCount = deviceRegistries.Where(x =>
|
|
{
|
|
if (x.HeartbeatInterval <= 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return x.LastHeartbeatTime.AddSeconds(x.HeartbeatInterval) >= now;
|
|
}).Count(),
|
|
Trend = FixTrend(devices.Where(x => x.CreateTime >= before30Day && x.CreateTime <= currentDay)
|
|
.GroupBy(x => x.CreateTime.Date)
|
|
.Select(x => new TrendDto { Date = x.Key, Count = x.Count() }), before30Day, currentDay)
|
|
},
|
|
AttendanceDetailSummary = new AttendanceDetailSummary
|
|
{
|
|
Employed = workingGainfos.Count,
|
|
Unemployed = leaveGainfos.Count,
|
|
GainfoTrend = new GainfoTrendResponse
|
|
{
|
|
EmployedTrend = FixTrend(workingGainfos.Where(x => x.EntryDate >= before7Day && x.EntryDate <= currentDay)
|
|
.GroupBy(x => x.EntryDate)
|
|
.Select(x => new TrendDto { Date = x.Key!.Value, Count = x.Count() }), before7Day, currentDay),
|
|
UnemployedTrend = FixTrend(leaveGainfos.Where(x => x.ResignationDate >= before7Day && x.ResignationDate <= currentDay)
|
|
.GroupBy(x => x.ResignationDate)
|
|
.Select(x => new TrendDto { Date = x.Key!.Value, Count = x.Count() }), before7Day, currentDay),
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
public async Task<DoorHomeDataResponse> GetDoorHomeDataAsync()
|
|
{
|
|
var devices = await _dbContext.Queryable<DeviceEntity>().Where(x => x.Type == DeviceTypeEnumType.Door).ToListAsync();
|
|
|
|
var offDevices = await GetOfflineDevicesCount(devices);
|
|
|
|
DateTime currentDate = DateTime.Now;
|
|
var times = new List<string>();
|
|
for (int i = 0; i < 30; i++)
|
|
{
|
|
DateTime date = currentDate.AddDays(-i);
|
|
string dateString = date.ToString("yyyy-MM-dd");
|
|
times.Add(dateString);
|
|
}
|
|
|
|
var list = new List<TrendDto>();
|
|
times.ForEach(time =>
|
|
{
|
|
var count = devices.Count(x => x.CreateTime.ToString("yyyy-MM-dd") == time);
|
|
var trend = new TrendDto
|
|
{
|
|
Date = DateTime.ParseExact(time, "yyyy-MM-dd", null),
|
|
Count = count,
|
|
};
|
|
list.Add(trend);
|
|
});
|
|
var res = new DoorHomeDataResponse
|
|
{
|
|
OffNum = offDevices.Count,
|
|
TotalNum = devices.Count,
|
|
Trend = list
|
|
};
|
|
return res;
|
|
}
|
|
|
|
public async Task<DoorDataResponse> GetDoorDataAsync()
|
|
{
|
|
var workingGainfos = await _gainfoStore.Queryable(GainfoStatusEnumType.Working).ToListAsync();
|
|
var leaveGainfos = await _gainfoStore.Queryable(GainfoStatusEnumType.Leave).ToListAsync();
|
|
|
|
var currentDay = DateTime.Today.AddDays(1).AddSeconds(-1);
|
|
var before7Day = DateTime.Today.AddDays(-6);
|
|
|
|
return new DoorDataResponse
|
|
{
|
|
Employed = workingGainfos.Count,
|
|
Unemployed = leaveGainfos.Count,
|
|
GainfoTrend = new GainfoTrendResponse()
|
|
{
|
|
EmployedTrend = FixTrend(workingGainfos.Where(x => x.EntryDate >= before7Day && x.EntryDate <= currentDay)
|
|
.GroupBy(x => x.EntryDate)
|
|
.Select(x => new TrendDto { Date = x.Key!.Value, Count = x.Count() }), before7Day, currentDay),
|
|
UnemployedTrend = FixTrend(leaveGainfos.Where(x => x.ResignationDate >= before7Day && x.ResignationDate <= currentDay)
|
|
.GroupBy(x => x.ResignationDate)
|
|
.Select(x => new TrendDto { Date = x.Key!.Value, Count = x.Count() }), before7Day, currentDay)
|
|
}
|
|
};
|
|
}
|
|
|
|
private static List<TrendDto> FixTrend(IEnumerable<TrendDto> dtos, DateTime start, DateTime end)
|
|
{
|
|
var result = dtos.ToList();
|
|
|
|
start = start.Date;
|
|
end = end.Date;
|
|
|
|
var currentDate = start;
|
|
while (currentDate <= end)
|
|
{
|
|
if (result.Any(x => x.Date == currentDate))
|
|
{
|
|
currentDate = currentDate.AddDays(1);
|
|
continue;
|
|
}
|
|
|
|
result.Add(new TrendDto { Date = currentDate, Count = 0 });
|
|
|
|
currentDate = currentDate.AddDays(1);
|
|
}
|
|
|
|
return result.OrderBy(x => x.Date).ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取离线设备
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private async Task<List<DeviceEntity>> GetOfflineDevicesCount(List<DeviceEntity> devices)
|
|
{
|
|
var now = DateTime.Now;
|
|
|
|
var deviceUniqueNos = devices.Select(x => x.UniqueNo).ToList();
|
|
|
|
var deviceRegistries = await _dbContext.Queryable<DeviceRegistryEntity>()
|
|
.LeftJoin<DeviceEntity>((x, d) => x.DeviceUniqueNo == d.UniqueNo)
|
|
.Where(x => deviceUniqueNos.Contains(x.DeviceUniqueNo))
|
|
.Select((x, d) => new
|
|
{
|
|
UniqueNo = d.UniqueNo,
|
|
d.HeartbeatInterval,
|
|
x.LastHeartbeatTime
|
|
})
|
|
.ToListAsync();
|
|
|
|
var onlineDevices = deviceRegistries
|
|
.Where(x =>
|
|
{
|
|
if (x.HeartbeatInterval <= 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return x.LastHeartbeatTime.AddSeconds(x.HeartbeatInterval) >= now;
|
|
})
|
|
.Select(x => new
|
|
{
|
|
UniqueNo = x.UniqueNo,
|
|
})
|
|
.ToList();
|
|
var onlineUniqueNos = new List<string>();
|
|
onlineDevices.ForEach(x => onlineUniqueNos.Add(x.UniqueNo));
|
|
|
|
var offUniqueNos = deviceUniqueNos.Except(onlineUniqueNos).ToList();
|
|
var list = devices.Where(x => offUniqueNos.Contains(x.UniqueNo)).ToList();
|
|
return list;
|
|
}
|
|
} |