343 lines
14 KiB
C#
343 lines
14 KiB
C#
using Model;
|
|
using Model.Dto.Inspection;
|
|
using Model.Entity.Asset;
|
|
using Model.Entity.Inspection;
|
|
using ORM;
|
|
using Service.Interface;
|
|
using SqlSugar;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Service.Implement
|
|
{
|
|
/// <summary>
|
|
/// 统计报表 服务实现
|
|
/// </summary>
|
|
public class StatisticsReportService : IStatisticsReportService
|
|
{
|
|
#region 设备统计报表
|
|
|
|
/// <summary>
|
|
/// 设备统计概览(总数/在用/闲置/报废等)
|
|
/// </summary>
|
|
public async Task<Result<DeviceStatisticsDto>> GetDeviceStatisticsAsync()
|
|
{
|
|
try
|
|
{
|
|
var query = SqlSugarContext.DbContext.Queryable<EquipmentEntity>()
|
|
.Where(x => x.IsDel == 0);
|
|
|
|
var all = await query.ToListAsync();
|
|
var total = all.Count;
|
|
|
|
var dto = new DeviceStatisticsDto
|
|
{
|
|
Total = total,
|
|
InUse = all.Count(x => x.Status == EquipmentStatusEnum.InUse),
|
|
Idle = all.Count(x => x.Status == EquipmentStatusEnum.Idle),
|
|
Scrapped = all.Count(x => x.Status == EquipmentStatusEnum.Disposed || x.Status == EquipmentStatusEnum.PendingDisposal),
|
|
Repairing = all.Count(x => x.Status == EquipmentStatusEnum.Repairing),
|
|
Suspended = all.Count(x => x.Status == EquipmentStatusEnum.Suspended),
|
|
Other = all.Count(x =>
|
|
x.Status != EquipmentStatusEnum.InUse &&
|
|
x.Status != EquipmentStatusEnum.Idle &&
|
|
x.Status != EquipmentStatusEnum.Disposed &&
|
|
x.Status != EquipmentStatusEnum.PendingDisposal &&
|
|
x.Status != EquipmentStatusEnum.Repairing &&
|
|
x.Status != EquipmentStatusEnum.Suspended)
|
|
};
|
|
|
|
return Result<DeviceStatisticsDto>.Success(dto);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<DeviceStatisticsDto>.Error("查询设备统计失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按分类统计设备数量
|
|
/// </summary>
|
|
public async Task<Result<List<CategoryStatisticsDto>>> GetCategoryStatisticsAsync()
|
|
{
|
|
try
|
|
{
|
|
var list = await SqlSugarContext.DbContext.Queryable<EquipmentEntity>()
|
|
.LeftJoin<EquipmentCategoryEntity>((e, c) => e.CategoryId == c.Id)
|
|
.Where((e, c) => e.IsDel == 0)
|
|
.GroupBy((e, c) => new { c.Name })
|
|
.Select((e, c) => new CategoryStatisticsDto
|
|
{
|
|
CategoryName = c.Name,
|
|
Count = SqlFunc.AggregateCount(e.Id)
|
|
})
|
|
.ToListAsync();
|
|
|
|
return Result<List<CategoryStatisticsDto>>.Success(list);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<List<CategoryStatisticsDto>>.Error("查询分类统计失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按部门统计设备数量
|
|
/// </summary>
|
|
public async Task<Result<List<DepartmentStatisticsDto>>> GetDepartmentStatisticsAsync()
|
|
{
|
|
try
|
|
{
|
|
var list = await SqlSugarContext.DbContext.Queryable<EquipmentEntity>()
|
|
.Where(x => x.IsDel == 0)
|
|
.GroupBy(x => x.Department)
|
|
.Select(x => new DepartmentStatisticsDto
|
|
{
|
|
Department = x.Department,
|
|
Count = SqlFunc.AggregateCount(x.Id)
|
|
})
|
|
.OrderByDescending(x => x.Count)
|
|
.ToListAsync();
|
|
|
|
return Result<List<DepartmentStatisticsDto>>.Success(list);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<List<DepartmentStatisticsDto>>.Error("查询部门统计失败", ex);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 设备维护报表
|
|
|
|
/// <summary>
|
|
/// 设备维护统计(校准/保养及时率、超期数量等)
|
|
/// </summary>
|
|
public async Task<Result<MaintenanceStatisticsDto>> GetMaintenanceStatisticsAsync()
|
|
{
|
|
try
|
|
{
|
|
var all = await SqlSugarContext.DbContext.Queryable<EquipmentEntity>()
|
|
.Where(x => x.IsDel == 0)
|
|
.ToListAsync();
|
|
|
|
var total = all.Count;
|
|
var calNormal = all.Count(x => x.CalibrationStatus == ComplianceStatusEnum.Normal);
|
|
var calOverdue = all.Count(x => x.CalibrationStatus == ComplianceStatusEnum.Overdue);
|
|
var maintNormal = all.Count(x => x.MaintenanceStatus == ComplianceStatusEnum.Normal);
|
|
var maintOverdue = all.Count(x => x.MaintenanceStatus == ComplianceStatusEnum.Overdue);
|
|
|
|
var dto = new MaintenanceStatisticsDto
|
|
{
|
|
Total = total,
|
|
CalibrationNormal = calNormal,
|
|
CalibrationOverdue = calOverdue,
|
|
MaintenanceNormal = maintNormal,
|
|
MaintenanceOverdue = maintOverdue,
|
|
CalibrationTimelyRate = total > 0 ? Math.Round((decimal)calNormal / total * 100, 1) : 0,
|
|
MaintenanceTimelyRate = total > 0 ? Math.Round((decimal)maintNormal / total * 100, 1) : 0
|
|
};
|
|
|
|
return Result<MaintenanceStatisticsDto>.Success(dto);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<MaintenanceStatisticsDto>.Error("查询维护统计失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 维护超期设备明细
|
|
/// </summary>
|
|
public async Task<Result<List<MaintenanceOverdueDetailDto>>> GetMaintenanceOverdueDetailsAsync()
|
|
{
|
|
try
|
|
{
|
|
var now = DateTime.Now;
|
|
var list = await SqlSugarContext.DbContext.Queryable<EquipmentEntity>()
|
|
.Where(x => x.IsDel == 0 &&
|
|
(x.CalibrationStatus == ComplianceStatusEnum.Overdue ||
|
|
x.MaintenanceStatus == ComplianceStatusEnum.Overdue))
|
|
.ToListAsync();
|
|
|
|
var details = new List<MaintenanceOverdueDetailDto>();
|
|
foreach (var eq in list)
|
|
{
|
|
if (eq.CalibrationStatus == ComplianceStatusEnum.Overdue && eq.NextCalibrationDate.HasValue)
|
|
{
|
|
var days = (int)(now - eq.NextCalibrationDate.Value).TotalDays;
|
|
details.Add(new MaintenanceOverdueDetailDto
|
|
{
|
|
EquipmentCode = eq.Code,
|
|
EquipmentName = eq.Name,
|
|
Department = eq.Department,
|
|
OverdueType = "校准超期",
|
|
ExpireDate = eq.NextCalibrationDate,
|
|
OverdueDays = days > 0 ? days : 0
|
|
});
|
|
}
|
|
if (eq.MaintenanceStatus == ComplianceStatusEnum.Overdue && eq.NextMaintenanceDate.HasValue)
|
|
{
|
|
var days = (int)(now - eq.NextMaintenanceDate.Value).TotalDays;
|
|
details.Add(new MaintenanceOverdueDetailDto
|
|
{
|
|
EquipmentCode = eq.Code,
|
|
EquipmentName = eq.Name,
|
|
Department = eq.Department,
|
|
OverdueType = "保养超期",
|
|
ExpireDate = eq.NextMaintenanceDate,
|
|
OverdueDays = days > 0 ? days : 0
|
|
});
|
|
}
|
|
}
|
|
|
|
return Result<List<MaintenanceOverdueDetailDto>>.Success(details);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<List<MaintenanceOverdueDetailDto>>.Error("查询维护超期明细失败", ex);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 维修类报表
|
|
|
|
/// <summary>
|
|
/// 维修统计概览
|
|
/// </summary>
|
|
public async Task<Result<RepairStatisticsDto>> GetRepairStatisticsAsync()
|
|
{
|
|
try
|
|
{
|
|
var all = await SqlSugarContext.DbContext.Queryable<RepairRecordEntity>()
|
|
.Where(x => x.IsDel == 0)
|
|
.ToListAsync();
|
|
|
|
var total = all.Count;
|
|
var completed = all.Count(x => x.RepairStatus == "已完成");
|
|
var inProgress = all.Count(x => x.RepairStatus == "维修中");
|
|
var pending = all.Count(x => x.RepairStatus == "待维修");
|
|
|
|
var totalHours = all.Where(x => x.RepairHours.HasValue).Sum(x => x.RepairHours ?? 0);
|
|
var completedWithHours = all.Where(x => x.RepairHours.HasValue && x.RepairStatus == "已完成").ToList();
|
|
var avgHours = completedWithHours.Count > 0
|
|
? Math.Round(completedWithHours.Sum(x => x.RepairHours ?? 0) / completedWithHours.Count, 1)
|
|
: 0;
|
|
|
|
var totalCost = all.Where(x => x.RepairCost.HasValue).Sum(x => x.RepairCost ?? 0);
|
|
|
|
var dto = new RepairStatisticsDto
|
|
{
|
|
Total = total,
|
|
Completed = completed,
|
|
InProgress = inProgress,
|
|
Pending = pending,
|
|
AvgRepairHours = avgHours,
|
|
TotalRepairHours = totalHours,
|
|
TotalRepairCost = totalCost
|
|
};
|
|
|
|
return Result<RepairStatisticsDto>.Success(dto);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<RepairStatisticsDto>.Error("查询维修统计失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 故障类型分布
|
|
/// </summary>
|
|
public async Task<Result<List<FaultTypeDistributionDto>>> GetFaultTypeDistributionAsync()
|
|
{
|
|
try
|
|
{
|
|
var list = await SqlSugarContext.DbContext.Queryable<RepairRecordEntity>()
|
|
.Where(x => x.IsDel == 0)
|
|
.GroupBy(x => x.FaultType)
|
|
.Select(x => new FaultTypeDistributionDto
|
|
{
|
|
FaultType = x.FaultType,
|
|
Count = SqlFunc.AggregateCount(x.Id)
|
|
})
|
|
.OrderByDescending(x => x.Count)
|
|
.ToListAsync();
|
|
|
|
return Result<List<FaultTypeDistributionDto>>.Success(list);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<List<FaultTypeDistributionDto>>.Error("查询故障类型分布失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 维修工时分析
|
|
/// </summary>
|
|
public async Task<Result<List<RepairHoursAnalysisDto>>> GetRepairHoursAnalysisAsync()
|
|
{
|
|
try
|
|
{
|
|
var list = await SqlSugarContext.DbContext.Queryable<RepairRecordEntity>()
|
|
.Where(x => x.IsDel == 0 && x.RepairHours.HasValue)
|
|
.GroupBy(x => x.FaultType)
|
|
.Select(x => new RepairHoursAnalysisDto
|
|
{
|
|
FaultType = x.FaultType,
|
|
AvgHours = SqlFunc.AggregateAvg(x.RepairHours) ?? 0,
|
|
MaxHours = SqlFunc.AggregateMax(x.RepairHours) ?? 0,
|
|
MinHours = SqlFunc.AggregateMin(x.RepairHours) ?? 0,
|
|
Count = SqlFunc.AggregateCount(x.Id)
|
|
})
|
|
.OrderByDescending(x => x.AvgHours)
|
|
.ToListAsync();
|
|
|
|
return Result<List<RepairHoursAnalysisDto>>.Success(list);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<List<RepairHoursAnalysisDto>>.Error("查询维修工时分析失败", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 维修记录明细列表
|
|
/// </summary>
|
|
public async Task<Result<List<RepairRecordDetailDto>>> GetRepairRecordDetailsAsync()
|
|
{
|
|
try
|
|
{
|
|
var list = await SqlSugarContext.DbContext.Queryable<RepairRecordEntity>()
|
|
.Where(x => x.IsDel == 0)
|
|
.OrderByDescending(x => x.CreateTime)
|
|
.Select(x => new RepairRecordDetailDto
|
|
{
|
|
EquipmentCode = x.EquipmentCode,
|
|
EquipmentName = x.EquipmentName,
|
|
FaultType = x.FaultType,
|
|
FaultDescription = x.FaultDescription,
|
|
ReportDate = x.ReportDate,
|
|
RepairEndDate = x.RepairEndDate,
|
|
RepairHours = x.RepairHours,
|
|
RepairPerson = x.RepairPerson,
|
|
RepairCost = x.RepairCost,
|
|
RepairStatus = x.RepairStatus
|
|
})
|
|
.ToListAsync();
|
|
|
|
return Result<List<RepairRecordDetailDto>>.Success(list);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result<List<RepairRecordDetailDto>>.Error("查询维修记录明细失败", ex);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|