diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsReportController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsReportController.java new file mode 100644 index 00000000..6819ed10 --- /dev/null +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsReportController.java @@ -0,0 +1,56 @@ +package com.nflg.qms.admin.controller; + +import com.nflg.qms.admin.service.QmsReportControllerService; +import com.nflg.wms.common.pojo.ApiResult; +import com.nflg.wms.common.pojo.qo.QmsReportQueryQO; +import com.nflg.wms.common.pojo.vo.*; +import com.nflg.wms.starter.BaseController; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 报表管理 + */ +@RestController +@RequestMapping("/report") +public class QmsReportController extends BaseController { + + @Resource + private QmsReportControllerService reportControllerService; + + /** + * IQC报表数据 + */ + @PostMapping("iqc") + public ApiResult getIqcReport(@Valid @RequestBody QmsReportQueryQO request) { + return ApiResult.success(reportControllerService.getIqcReport(request)); + } + + /** + * PDI报表数据 + */ + @PostMapping("pdi") + public ApiResult getPdiReport(@Valid @RequestBody QmsReportQueryQO request) { + return ApiResult.success(reportControllerService.getPdiReport(request)); + } + + /** + * 工单报表数据 + */ + @PostMapping("ticket") + public ApiResult getTicketReport(@Valid @RequestBody QmsReportQueryQO request) { + return ApiResult.success(reportControllerService.getTicketReport(request)); + } + + /** + * 超时统计数据 + */ + @PostMapping("overdue") + public ApiResult getOverdueReport() { + return ApiResult.success(reportControllerService.getOverdueReport()); + } +} diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsReportControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsReportControllerService.java new file mode 100644 index 00000000..1de88656 --- /dev/null +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsReportControllerService.java @@ -0,0 +1,469 @@ +package com.nflg.qms.admin.service; + +import com.nflg.wms.common.pojo.qo.QmsReportQueryQO; +import com.nflg.wms.common.pojo.vo.*; +import com.nflg.wms.repository.entity.*; +import com.nflg.wms.repository.service.*; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.time.DayOfWeek; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.temporal.TemporalAdjusters; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 报表管理 ControllerService + */ +@Service +public class QmsReportControllerService { + + @Resource + private IQmsIncomingInspectionTaskService incomingInspectionTaskService; + + @Resource + private IQmsQcMaterialService qcMaterialService; + + @Resource + private IQmsQcMaterialCategoryService qcMaterialCategoryService; + + @Resource + private IQmsIncomingInspectionTaskRecordService incomingInspectionTaskRecordService; + + @Resource + private IQmsIncomingInspectionTaskRecordItemService incomingInspectionTaskRecordItemService; + + @Resource + private IQmsInspectionStandardItemContentService inspectionStandardItemContentService; + + @Resource + private com.nflg.wms.repository.mapper.QmsReportMapper reportMapper; + + @Resource + private IUserService userService; + + /** + * IQC报表数据 + */ + public QmsIqcReportVO getIqcReport(QmsReportQueryQO request) { + QmsIqcReportVO vo = new QmsIqcReportVO(); + + // 计算时间范围 + LocalDateTime currentStart = request.getStartTime(); + LocalDateTime currentEnd = request.getEndTime(); + boolean hasTimeRange = currentStart != null || currentEnd != null; + + // 如果都没传,查询全部 + if (!hasTimeRange) { + currentStart = LocalDateTime.MIN; + currentEnd = LocalDateTime.MAX; + } else { + if (currentStart == null) currentStart = LocalDateTime.MIN; + if (currentEnd == null) currentEnd = LocalDateTime.MAX; + } + + // 计算上周期 + long daysBetween = java.time.temporal.ChronoUnit.DAYS.between(currentStart, currentEnd); + LocalDateTime previousStart = currentStart.minusDays(daysBetween); + LocalDateTime previousEnd = currentStart; + + // 1. 总工单统计 + Map totalStats = calculateTotalTasks(currentStart, currentEnd, previousStart, previousEnd, hasTimeRange); + vo.setTotalTasks((Integer) totalStats.get("currentTotal")); + vo.setPreviousTotalTasks((Integer) totalStats.get("previousTotal")); + vo.setTotalTasksChangeRate((Double) totalStats.get("changeRate")); + + // 2. 已完成数统计 + Map completedStats = calculateCompletedTasks(currentStart, currentEnd, previousStart, previousEnd, hasTimeRange); + vo.setCompletedCount((Integer) completedStats.get("currentCompleted")); + vo.setPreviousCompletedCount((Integer) completedStats.get("previousCompleted")); + vo.setCompletedChangeRate((Double) completedStats.get("changeRate")); + vo.setAvgCompletedTime((String) completedStats.get("avgTime")); + + // 3. 待检测任务数 + vo.setPendingCount(calculatePendingTasks(currentStart, currentEnd)); + + // 4. 合格率 + vo.setPassRate(calculatePassRate(currentStart, currentEnd)); + + // 5. 每周合格率 + vo.setWeeklyPassRates(calculateWeeklyPassRates(currentStart, currentEnd)); + + // 6. 检测分布类别(前5) + vo.setCategoryDistributions(calculateCategoryDistribution(currentStart, currentEnd)); + + // 7. 供应商合格率(最高5+最低2) + vo.setSupplierPassRates(calculateSupplierPassRate(currentStart, currentEnd)); + + // 8. 物料类别不合格率(前5) + vo.setMaterialCategoryFailRates(calculateMaterialCategoryFailRate(currentStart, currentEnd)); + + // 9. 检测人效率(前5) + vo.setInspectorEfficiencies(calculateInspectorEfficiency(currentStart, currentEnd)); + + return vo; + } + + /** + * 计算总工单统计 + */ + private Map calculateTotalTasks(LocalDateTime currentStart, LocalDateTime currentEnd, + LocalDateTime previousStart, LocalDateTime previousEnd, + boolean hasTimeRange) { + Map result = new HashMap<>(); + + // 当前周期总工单 + long currentTotal = incomingInspectionTaskService.lambdaQuery() + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .count(); + + // 上周期总工单 + long previousTotal = 0; + if (hasTimeRange) { + previousTotal = incomingInspectionTaskService.lambdaQuery() + .ge(QmsIncomingInspectionTask::getSubmitTime, previousStart) + .le(QmsIncomingInspectionTask::getSubmitTime, previousEnd) + .count(); + } + + // 增减百分比 + double changeRate = 0; + if (previousTotal > 0) { + changeRate = ((double) (currentTotal - previousTotal) / previousTotal) * 100; + } + + result.put("currentTotal", (int) currentTotal); + result.put("previousTotal", (int) previousTotal); + result.put("changeRate", changeRate); + return result; + } + + /** + * 计算已完成任务统计 + */ + private Map calculateCompletedTasks(LocalDateTime currentStart, LocalDateTime currentEnd, + LocalDateTime previousStart, LocalDateTime previousEnd, + boolean hasTimeRange) { + Map result = new HashMap<>(); + + // 当前周期已完成 + long currentCompleted = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .count(); + + // 上周期已完成 + long previousCompleted = 0; + if (hasTimeRange) { + previousCompleted = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .ge(QmsIncomingInspectionTask::getSubmitTime, previousStart) + .le(QmsIncomingInspectionTask::getSubmitTime, previousEnd) + .count(); + } + + // 增减百分比 + double changeRate = 0; + if (previousCompleted > 0) { + changeRate = ((double) (currentCompleted - previousCompleted) / previousCompleted) * 100; + } + + // 平均耗时(当前周期) + String avgTime = "0小时0分钟"; + if (currentCompleted > 0) { + List completedTasks = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .isNotNull(QmsIncomingInspectionTask::getInspectionStartTime) + .isNotNull(QmsIncomingInspectionTask::getInspectionFinishTime) + .list(); + + if (!completedTasks.isEmpty()) { + long totalSeconds = 0; + for (QmsIncomingInspectionTask task : completedTasks) { + Duration duration = Duration.between(task.getInspectionStartTime(), task.getInspectionFinishTime()); + totalSeconds += duration.getSeconds(); + } + long avgSeconds = totalSeconds / completedTasks.size(); + avgTime = formatDuration(avgSeconds); + } + } + + result.put("currentCompleted", (int) currentCompleted); + result.put("previousCompleted", (int) previousCompleted); + result.put("changeRate", changeRate); + result.put("avgTime", avgTime); + return result; + } + + /** + * 计算待检测任务数 + */ + private int calculatePendingTasks(LocalDateTime currentStart, LocalDateTime currentEnd) { + long count = incomingInspectionTaskService.lambdaQuery() + .in(QmsIncomingInspectionTask::getInspectionStatus, (short) 0, (short) 1) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .count(); + return (int) count; + } + + /** + * 计算合格率 + */ + private double calculatePassRate(LocalDateTime currentStart, LocalDateTime currentEnd) { + long completedCount = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .count(); + + if (completedCount == 0) return 0; + + long qualifiedCount = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .eq(QmsIncomingInspectionTask::getInspectionResult, true) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .count(); + + return ((double) qualifiedCount / completedCount) * 100; + } + + /** + * 计算每周合格率 + */ + private List calculateWeeklyPassRates(LocalDateTime currentStart, LocalDateTime currentEnd) { + // 补全到完整的周 + LocalDateTime weekStart = currentStart.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + LocalDateTime weekEnd = currentEnd.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); + + List weeklyRates = new ArrayList<>(); + + // 按周遍历 + LocalDateTime currentWeekStart = weekStart; + int weekNum = 1; + + while (currentWeekStart.isBefore(weekEnd) || currentWeekStart.isEqual(weekEnd)) { + LocalDateTime currentWeekEnd = currentWeekStart.plusDays(6).withHour(23).withMinute(59).withSecond(59); + + // 该周已完成数 + long weekCompleted = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentWeekStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentWeekEnd) + .count(); + + // 该周合格数 + long weekQualified = 0; + if (weekCompleted > 0) { + weekQualified = incomingInspectionTaskService.lambdaQuery() + .eq(QmsIncomingInspectionTask::getInspectionStatus, (short) 2) + .eq(QmsIncomingInspectionTask::getInspectionResult, true) + .ge(QmsIncomingInspectionTask::getSubmitTime, currentWeekStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentWeekEnd) + .count(); + } + + double passRate = weekCompleted > 0 ? ((double) weekQualified / weekCompleted) * 100 : 0; + + QmsIqcReportVO.WeeklyPassRate weekRate = new QmsIqcReportVO.WeeklyPassRate(); + weekRate.setWeek("week" + weekNum); + weekRate.setPassRate(passRate); + weeklyRates.add(weekRate); + + currentWeekStart = currentWeekEnd.plusSeconds(1); + weekNum++; + } + + return weeklyRates; + } + + /** + * 计算检测分布类别(前5) + */ + private List calculateCategoryDistribution(LocalDateTime currentStart, LocalDateTime currentEnd) { + List> results = reportMapper.getInspectionItemDistribution(currentStart, currentEnd); + + // 只取前5项 + List> top5 = results.stream().limit(5).collect(Collectors.toList()); + + // 计算前5项的总数 + long top5Total = top5.stream() + .mapToLong(m -> ((Number) m.get("itemCount")).longValue()) + .sum(); + + List distributions = new ArrayList<>(); + for (Map row : top5) { + QmsIqcReportVO.InspectionCategoryDistribution dist = new QmsIqcReportVO.InspectionCategoryDistribution(); + dist.setItemName((String) row.get("itemName")); + long itemCount = ((Number) row.get("itemCount")).longValue(); + double percentage = top5Total > 0 ? ((double) itemCount / top5Total) * 100 : 0; + dist.setPercentage(percentage); + distributions.add(dist); + } + + return distributions; + } + + /** + * 计算供应商合格率(最高5+最低2) + */ + private List calculateSupplierPassRate(LocalDateTime currentStart, LocalDateTime currentEnd) { + // 查询所有供应商 + List tasks = incomingInspectionTaskService.lambdaQuery() + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .isNotNull(QmsIncomingInspectionTask::getSupplierCode) + .list(); + + // 按供应商分组统计 + Map> supplierMap = tasks.stream() + .collect(Collectors.groupingBy(QmsIncomingInspectionTask::getSupplierCode)); + + List supplierRates = new ArrayList<>(); + for (Map.Entry> entry : supplierMap.entrySet()) { + String supplierCode = entry.getKey(); + List supplierTasks = entry.getValue(); + + long total = supplierTasks.size(); + long qualified = supplierTasks.stream() + .filter(t -> Boolean.TRUE.equals(t.getInspectionResult())) + .count(); + + double passRate = total > 0 ? ((double) qualified / total) * 100 : 0; + + QmsIqcReportVO.SupplierPassRate rate = new QmsIqcReportVO.SupplierPassRate(); + rate.setSupplierCode(supplierCode); + rate.setSupplierName(supplierTasks.get(0).getSupplierName()); + rate.setPassRate(passRate); + supplierRates.add(rate); + } + + // 排序:按合格率降序 + supplierRates.sort(Comparator.comparingDouble(QmsIqcReportVO.SupplierPassRate::getPassRate).reversed() + .thenComparing(QmsIqcReportVO.SupplierPassRate::getSupplierCode)); + + // 取最高5个 + List top5 = supplierRates.stream().limit(5).collect(Collectors.toList()); + + // 取最低2个(如果总数>5) + List bottom2 = new ArrayList<>(); + if (supplierRates.size() > 5) { + bottom2 = supplierRates.stream() + .skip(Math.max(0, supplierRates.size() - 2)) + .collect(Collectors.toList()); + } + + // 合并 + List result = new ArrayList<>(top5); + result.addAll(bottom2); + + return result; + } + + /** + * 计算物料类别不合格率(前5) + */ + private List calculateMaterialCategoryFailRate(LocalDateTime currentStart, LocalDateTime currentEnd) { + List> results = reportMapper.getMaterialCategoryFailRate(currentStart, currentEnd); + + // 只取前5个(不合格数量最多的) + List> top5 = results.stream().limit(5).collect(Collectors.toList()); + + // 计算前5个的不合格总数 + long top5FailTotal = top5.stream() + .mapToLong(m -> ((Number) m.get("failCount")).longValue()) + .sum(); + + List failRates = new ArrayList<>(); + for (Map row : top5) { + QmsIqcReportVO.MaterialCategoryFailRate rate = new QmsIqcReportVO.MaterialCategoryFailRate(); + rate.setCategoryName((String) row.get("categoryName")); + long failCount = ((Number) row.get("failCount")).longValue(); + double failRate = top5FailTotal > 0 ? ((double) failCount / top5FailTotal) * 100 : 0; + rate.setFailRate(failRate); + failRates.add(rate); + } + + return failRates; + } + + /** + * 计算检测人效率(前5) + */ + private List calculateInspectorEfficiency(LocalDateTime currentStart, LocalDateTime currentEnd) { + // 查询所有任务 + List tasks = incomingInspectionTaskService.lambdaQuery() + .ge(QmsIncomingInspectionTask::getSubmitTime, currentStart) + .le(QmsIncomingInspectionTask::getSubmitTime, currentEnd) + .isNotNull(QmsIncomingInspectionTask::getInspectorId) + .list(); + + // 按检测人分组统计 + Map> inspectorMap = tasks.stream() + .collect(Collectors.groupingBy(QmsIncomingInspectionTask::getInspectorId)); + + List efficiencies = new ArrayList<>(); + for (Map.Entry> entry : inspectorMap.entrySet()) { + Long inspectorId = entry.getKey(); + List inspectorTasks = entry.getValue(); + + long total = inspectorTasks.size(); + long completed = inspectorTasks.stream() + .filter(t -> t.getInspectionStatus() != null && t.getInspectionStatus() == 2) + .count(); + + double efficiency = total > 0 ? ((double) completed / total) * 100 : 0; + + QmsIqcReportVO.InspectorEfficiency eff = new QmsIqcReportVO.InspectorEfficiency(); + eff.setInspectorId(inspectorId); + eff.setInspectorName(inspectorTasks.get(0).getInspectorName()); + eff.setCompletedCount((int) completed); + eff.setEfficiency(efficiency); + efficiencies.add(eff); + } + + // 按效率降序,取前5 + efficiencies.sort(Comparator.comparingDouble(QmsIqcReportVO.InspectorEfficiency::getEfficiency).reversed()); + return efficiencies.stream().limit(5).collect(Collectors.toList()); + } + + /** + * 格式化时长:秒 -> xx小时xx分钟 + */ + private String formatDuration(long seconds) { + long hours = seconds / 3600; + long minutes = (seconds % 3600) / 60; + return hours + "小时" + minutes + "分钟"; + } + + /** + * PDI报表数据 + */ + public QmsPdiReportVO getPdiReport(QmsReportQueryQO request) { + // TODO: 实现逻辑 + return new QmsPdiReportVO(); + } + + /** + * 工单报表数据 + */ + public QmsTicketReportVO getTicketReport(QmsReportQueryQO request) { + // TODO: 实现逻辑 + return new QmsTicketReportVO(); + } + + /** + * 超时统计数据 + */ + public QmsOverdueReportVO getOverdueReport() { + // TODO: 实现逻辑 + return new QmsOverdueReportVO(); + } +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsReportQueryQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsReportQueryQO.java new file mode 100644 index 00000000..8efe16b0 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsReportQueryQO.java @@ -0,0 +1,22 @@ +package com.nflg.wms.common.pojo.qo; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 报表查询请求QO + */ +@Data +public class QmsReportQueryQO { + + /** + * 开始时间(可选) + */ + private LocalDateTime startTime; + + /** + * 结束时间(可选) + */ + private LocalDateTime endTime; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIqcReportVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIqcReportVO.java new file mode 100644 index 00000000..bada6523 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIqcReportVO.java @@ -0,0 +1,152 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; + +import java.util.List; + +/** + * IQC报表VO + */ +@Data +public class QmsIqcReportVO { + + /** + * 总工单数 + */ + private Integer totalTasks; + + /** + * 已完成数 + */ + private Integer completedCount; + + /** + * 待检测任务数 + */ + private Integer pendingCount; + + /** + * 合格率(百分比) + */ + private Double passRate; + + /** + * 每周合格率列表 + */ + private List weeklyPassRates; + + /** + * 检测分布类别列表 + */ + private List categoryDistributions; + + /** + * 供应商合格率列表 + */ + private List supplierPassRates; + + /** + * 物料类别不合格率列表 + */ + private List materialCategoryFailRates; + + /** + * 检测人效率列表 + */ + private List inspectorEfficiencies; + + /** + * 每周合格率 + */ + @Data + public static class WeeklyPassRate { + /** + * 周数(week1、week2...) + */ + private String week; + + /** + * 合格率(百分比) + */ + private Double passRate; + } + + /** + * 检测分布类别 + */ + @Data + public static class InspectionCategoryDistribution { + /** + * 检测项名称 + */ + private String itemName; + + /** + * 占比(百分比) + */ + private Double percentage; + } + + /** + * 供应商合格率 + */ + @Data + public static class SupplierPassRate { + /** + * 供应商编码 + */ + private String supplierCode; + + /** + * 供应商名称 + */ + private String supplierName; + + /** + * 合格率(百分比) + */ + private Double passRate; + } + + /** + * 物料类别不合格率 + */ + @Data + public static class MaterialCategoryFailRate { + /** + * 物料类别名称 + */ + private String categoryName; + + /** + * 不合格率(百分比) + */ + private Double failRate; + } + + /** + * 检测人效率 + */ + @Data + public static class InspectorEfficiency { + /** + * 检测人姓名 + */ + private String inspectorName; + + /** + * 检测人ID + */ + private Long inspectorId; + + /** + * 完成数量 + */ + private Integer completedCount; + + /** + * 效率(百分比) + */ + private Double efficiency; + } +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsOverdueReportVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsOverdueReportVO.java new file mode 100644 index 00000000..c499ca03 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsOverdueReportVO.java @@ -0,0 +1,83 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 超时统计报表VO + */ +@Data +public class QmsOverdueReportVO { + + /** + * 超时任务总数 + */ + private Integer totalOverdueCount; + + /** + * 平均超时时间(格式:xx小时xx分钟xx秒) + */ + private String avgOverdueTime; + + /** + * 严重超时数(阈值待定) + */ + private Integer severeOverdueCount; + + /** + * IQC超时任务列表 + */ + private List iqcOverdueTasks; + + /** + * PDI超时任务列表 + */ + private List pdiOverdueTasks; + + /** + * 工单超时任务列表 + */ + private List ticketOverdueTasks; + + /** + * 超时任务项 + */ + @Data + public static class OverdueTaskItem { + /** + * 工单编号 + */ + private String taskNo; + + /** + * 类型(IQC/PDI/工单类型) + */ + private String type; + + /** + * 处理人姓名列表 + */ + private List handlerNames; + + /** + * 处理人ID列表 + */ + private List handlerIds; + + /** + * 创建日期 + */ + private String createDate; + + /** + * 要求完成时间 + */ + private String requiredCompletionTime; + + /** + * 超时时长(格式:xx小时xx分钟xx秒) + */ + private String overdueDuration; + } +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsPdiReportVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsPdiReportVO.java new file mode 100644 index 00000000..f364ad83 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsPdiReportVO.java @@ -0,0 +1,84 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; + +import java.util.List; + +/** + * PDI报表VO + */ +@Data +public class QmsPdiReportVO { + + /** + * 总单数 + */ + private Integer totalTasks; + + /** + * 已完成检测数 + */ + private Integer completedCount; + + /** + * 待检数量 + */ + private Integer pendingCount; + + /** + * 平均检测时间(格式:xx小时xx分钟xx秒) + */ + private String avgInspectionTime; + + /** + * 计划达成率(百分比) + */ + private Double planCompletionRate; + + /** + * 不合格率(百分比) + */ + private Double failRate; + + /** + * 每周合格率列表 + */ + private List weeklyPassRates; + + /** + * 部件描述比例列表 + */ + private List componentDistributions; + + /** + * 每周合格率 + */ + @Data + public static class WeeklyPassRate { + /** + * 周数(week1、week2...) + */ + private String week; + + /** + * 合格率(百分比) + */ + private Double passRate; + } + + /** + * 部件描述比例 + */ + @Data + public static class ComponentDistribution { + /** + * 机型编号 + */ + private String machineNo; + + /** + * 占比(百分比) + */ + private Double percentage; + } +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsTicketReportVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsTicketReportVO.java new file mode 100644 index 00000000..d61a12a5 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsTicketReportVO.java @@ -0,0 +1,110 @@ +package com.nflg.wms.common.pojo.vo; + +import lombok.Data; + +import java.util.List; + +/** + * 工单报表VO + */ +@Data +public class QmsTicketReportVO { + + /** + * 总工单数 + */ + private Integer totalTickets; + + /** + * 已完成数 + */ + private Integer completedCount; + + /** + * 未完成数 + */ + private Integer unfinishedCount; + + /** + * 总体完成率(百分比) + */ + private Double completionRate; + + /** + * 平均处理耗时(格式:xx小时xx分钟xx秒) + */ + private String avgProcessingTime; + + /** + * 各状态占比列表 + */ + private List statusDistributions; + + /** + * 问题类别数量列表 + */ + private List issueTypeCounts; + + /** + * 用户完成率列表 + */ + private List userCompletionRates; + + /** + * 状态分布 + */ + @Data + public static class StatusDistribution { + /** + * 状态(0=待流转,1=处理中,2=已完成) + */ + private Short status; + + /** + * 状态名称 + */ + private String statusName; + + /** + * 占比(百分比) + */ + private Double percentage; + } + + /** + * 问题类别数量 + */ + @Data + public static class IssueTypeCount { + /** + * 问题类别名称 + */ + private String issueTypeName; + + /** + * 数量 + */ + private Integer count; + } + + /** + * 用户完成率 + */ + @Data + public static class UserCompletionRate { + /** + * 用户姓名 + */ + private String userName; + + /** + * 用户ID + */ + private Long userId; + + /** + * 完成率(百分比) + */ + private Double completionRate; + } +} diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsReportMapper.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsReportMapper.java new file mode 100644 index 00000000..feb77684 --- /dev/null +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsReportMapper.java @@ -0,0 +1,27 @@ +package com.nflg.wms.repository.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.nflg.wms.repository.entity.QmsIncomingInspectionTask; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +/** + * 报表统计 Mapper + */ +public interface QmsReportMapper extends BaseMapper { + + /** + * 查询检测项分布(按检测项名称统计数量) + */ + List> getInspectionItemDistribution(@Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + + /** + * 查询物料类别不合格率 + */ + List> getMaterialCategoryFailRate(@Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); +} diff --git a/nflg-wms-repository/src/main/resources/mapper/QmsReportMapper.xml b/nflg-wms-repository/src/main/resources/mapper/QmsReportMapper.xml new file mode 100644 index 00000000..e1f5e1a0 --- /dev/null +++ b/nflg-wms-repository/src/main/resources/mapper/QmsReportMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + +