11
gongchunyi
9 天以前 1f5fdca1ab73461fb930f64c26dcb4038a9d4bf7
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -313,19 +313,35 @@
            queryWrapper.ge(QualityInspect::getCheckTime, monthStart.toString())
                    .le(QualityInspect::getCheckTime, monthEnd.toString());
            List<QualityInspect> monthInspects = qualityStatisticsMapper.selectList(queryWrapper);
            // 统计总数量(合格数量 + 不合格数量)
            BigDecimal reduce = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(0))
                    .map(QualityInspect::getQuantity)
                    .map(inspect -> {
                        BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO;
                        BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO;
                        return qualified.add(unqualified);
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            supplierNum = supplierNum.add(reduce);
            BigDecimal reduce1 = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(1))
                    .map(QualityInspect::getQuantity)
                    .map(inspect -> {
                        BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO;
                        BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO;
                        return qualified.add(unqualified);
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            processNum = processNum.add(reduce1);
            BigDecimal reduce2 = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(2))
                    .map(QualityInspect::getQuantity)
                    .map(inspect -> {
                        BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO;
                        BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO;
                        return qualified.add(unqualified);
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            factoryNum = factoryNum.add(reduce2);
@@ -335,25 +351,22 @@
            // 1. 供应商检验(类型0)- 合格数量
            BigDecimal supplierQualified = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(0)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                    .filter(inspect -> inspect.getInspectType().equals(0))
                    .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setSupplierNum(supplierQualified);
            // 2. 工序检验(类型1)- 合格数量
            BigDecimal processQualified = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(1)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                    .filter(inspect -> inspect.getInspectType().equals(1))
                    .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setProcessNum(processQualified);
            // 3. 工厂检验(类型2)- 合格数量
            BigDecimal factoryQualified = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(2)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                    .filter(inspect -> inspect.getInspectType().equals(2))
                    .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setFactoryNum(factoryQualified);
@@ -1006,7 +1019,7 @@
    public List<Map<String, Object>> productInOutAnalysis(Integer type) {
        String targetName;
        if (type == 1) {
            targetName = "原材料";
            targetName = "原料";
        } else if (type == 2) {
            targetName = "成品";
        } else if (type == 3) {
@@ -1465,95 +1478,80 @@
        String endStr = endDate.atTime(LocalTime.MAX).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        List<ProductionTaskStatisticsDto> startList = productionOperationTaskMapper.selectTaskStartStats(startStr, endStr);
        List<ProductionProductOutputDto> outputList = productionProductOutputMapper
                .selectOutputStats(startStr, endStr);
        List<ProductionProductOutputDto> outputList = productionProductOutputMapper.selectOutputStats(startStr, endStr);
        Map<String, WorkOrderEfficiencyDto> dateMap = new HashMap<>();
        // 1. 处理开工数量(统一将时间转为 LocalDate 字符串,去除时分秒)
        if (!CollectionUtils.isEmpty(startList)) {
            for (ProductionTaskStatisticsDto item : startList) {
                if (item.getActualStartTime() != null) {
                    String date = item.getActualStartTime().toString();
                    WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto());
                    dto.setDate(date);
                    // 💡 关键修改:如果是 LocalDateTime,必须先 toLocalDate() 再 toString()
                    String dateStr = item.getActualStartTime().toString();
                    WorkOrderEfficiencyDto dto = dateMap.computeIfAbsent(dateStr, k -> {
                        WorkOrderEfficiencyDto newDto = new WorkOrderEfficiencyDto();
                        newDto.setDate(k);
                        newDto.setStartQuantity(BigDecimal.ZERO);
                        newDto.setFinishQuantity(BigDecimal.ZERO);
                        newDto.setYieldRate("0.00");
                        return newDto;
                    });
                    BigDecimal qty = item.getPlanQuantity() != null ? item.getPlanQuantity() : BigDecimal.ZERO;
                    dto.setStartQuantity(dto.getStartQuantity() != null ? dto.getStartQuantity().add(qty) : qty);
                    dateMap.put(date, dto);
                    dto.setStartQuantity(dto.getStartQuantity().add(qty));
                }
            }
        }
        // 完工数量和良品率
        // 2. 处理完工数量和报废数量(仅通过 1 次循环搞定,大幅提升性能)
        if (!CollectionUtils.isEmpty(outputList)) {
            // 定义一个临时的报废数计数器,方便后面算良品率
            Map<String, BigDecimal> scrapMap = new HashMap<>();
            for (ProductionProductOutputDto item : outputList) {
                if (item.getCreateTime() != null) {
                    String date = item.getCreateTime().toLocalDate().toString();
                    WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto());
                    dto.setDate(date);
                    String dateStr = item.getCreateTime().toLocalDate().toString();
                    BigDecimal finishQty = item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO;
                    BigDecimal scrapQty = item.getScrapQty() != null ? item.getScrapQty() : BigDecimal.ZERO;
                    WorkOrderEfficiencyDto dto = dateMap.computeIfAbsent(dateStr, k -> {
                        WorkOrderEfficiencyDto newDto = new WorkOrderEfficiencyDto();
                        newDto.setDate(k);
                        newDto.setStartQuantity(BigDecimal.ZERO);
                        newDto.setFinishQuantity(BigDecimal.ZERO);
                        newDto.setYieldRate("0.00");
                        return newDto;
                    });
                    dto.setFinishQuantity(
                            dto.getFinishQuantity() != null ? dto.getFinishQuantity().add(finishQty) : finishQty);
                    BigDecimal qty = item.getQuantity() != null ? item.getQuantity() : BigDecimal.ZERO;
                    BigDecimal scrap = item.getScrapQty() != null ? item.getScrapQty() : BigDecimal.ZERO;
                    // 良品数 = 总投入数 - 报废数 (对应你原代码中 finishMap 的逻辑)
                    BigDecimal goodQty = qty.subtract(scrap);
                    dto.setFinishQuantity(dto.getFinishQuantity().add(goodQty));
                    // 累加报废数
                    scrapMap.put(dateStr, scrapMap.getOrDefault(dateStr, BigDecimal.ZERO).add(scrap));
                }
            }
            Map<String, BigDecimal> scrapMap = outputList.stream()
                    .filter(i -> i.getCreateTime() != null)
                    .collect(Collectors.groupingBy(
                            i -> i.getCreateTime().toLocalDate().toString(),
                            Collectors.reducing(BigDecimal.ZERO,
                                    i -> i.getScrapQty() != null ? i.getScrapQty() : BigDecimal.ZERO,
                                    BigDecimal::add)));
            Map<String, BigDecimal> finishMap = outputList.stream()
                    .filter(i -> i.getCreateTime() != null)
                    .collect(Collectors.groupingBy(
                            i -> i.getCreateTime().toLocalDate().toString(),
                            Collectors.reducing(BigDecimal.ZERO, i -> {
                                BigDecimal qty = (i.getQuantity() != null) ? i.getQuantity() : BigDecimal.ZERO;
                                BigDecimal scrap = (i.getScrapQty() != null) ? i.getScrapQty() : BigDecimal.ZERO;
                                return qty.subtract(scrap);
                            }, BigDecimal::add)));
            finishMap.forEach((date, qty) -> {
                WorkOrderEfficiencyDto dto = dateMap.getOrDefault(date, new WorkOrderEfficiencyDto());
                dto.setDate(date);
                dto.setFinishQuantity(qty);
                dateMap.put(date, dto);
            });
            dateMap.forEach((date, dto) -> {
                BigDecimal finish = dto.getFinishQuantity() != null ? dto.getFinishQuantity() : BigDecimal.ZERO;
                BigDecimal scrap = scrapMap.getOrDefault(date, BigDecimal.ZERO);
            // 3. 计算良品率
            dateMap.forEach((dateStr, dto) -> {
                BigDecimal finish = dto.getFinishQuantity();
                BigDecimal scrap = scrapMap.getOrDefault(dateStr, BigDecimal.ZERO);
                BigDecimal total = finish.add(scrap);
                if (total.compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal rate = finish.divide(total, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))
                            .setScale(2, RoundingMode.HALF_UP);
                    // 💡 延续你之前的逻辑:使用 RoundingMode.DOWN 截断,防止 99.999% 四舍五入变成 100.00
                    BigDecimal rate = finish.divide(total, 4, RoundingMode.DOWN)
                            .multiply(new BigDecimal("100"))
                            .setScale(2, RoundingMode.DOWN);
                    dto.setYieldRate(rate.toString());
                } else {
                    dto.setYieldRate("0.00");
                }
                if (dto.getStartQuantity() == null)
                    dto.setStartQuantity(BigDecimal.ZERO);
                if (dto.getFinishQuantity() == null)
                    dto.setFinishQuantity(BigDecimal.ZERO);
            });
        }
        dateMap.values().forEach(dto -> {
            if (dto.getStartQuantity() == null)
                dto.setStartQuantity(BigDecimal.ZERO);
            if (dto.getFinishQuantity() == null)
                dto.setFinishQuantity(BigDecimal.ZERO);
            if (dto.getYieldRate() == null)
                dto.setYieldRate("0.00");
        });
        // 4. 排序并输出
        return dateMap.values().stream()
                .sorted(Comparator.comparing(WorkOrderEfficiencyDto::getDate))
                .collect(Collectors.toList());
@@ -1737,11 +1735,8 @@
        BigDecimal unqualifiedCount = BigDecimal.ZERO;
        for (QualityInspect item : list) {
            if ("合格".equals(item.getCheckResult())) {
                qualifiedCount = qualifiedCount.add(item.getQuantity());
            } else {
                unqualifiedCount = unqualifiedCount.add(item.getQuantity());
            }
            qualifiedCount = qualifiedCount.add(item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO);
            unqualifiedCount = unqualifiedCount.add(item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO);
        }
        BigDecimal totalCount = qualifiedCount.add(unqualifiedCount);
@@ -1905,7 +1900,7 @@
            }
            switch (parent.getProductName()) {
                case "原材料":
                case "原料":
                    rawMaterialCount = rawMaterialCount.add(quantity);
                    break;
                case "半成品":
@@ -2010,13 +2005,11 @@
                continue;
            }
            BigDecimal quantity = item.getQuantity();
            BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO;
            BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO;
            if ("合格".equals(item.getCheckResult())) {
                dto.setQualifiedCount(dto.getQualifiedCount().add(quantity));
            } else {
                dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity));
            }
            dto.setQualifiedCount(dto.getQualifiedCount().add(qualifiedQty));
            dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(unqualifiedQty));
        }
        // 计算合格率
@@ -2057,14 +2050,12 @@
            BigDecimal unqualifiedCount = BigDecimal.ZERO;
            for (QualityInspect item : items) {
                BigDecimal qty = item.getQuantity();
                totalCount = totalCount.add(qty);
                BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO;
                BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO;
                if ("合格".equals(item.getCheckResult())) {
                    qualifiedCount = qualifiedCount.add(qty);
                } else {
                    unqualifiedCount = unqualifiedCount.add(qty);
                }
                totalCount = totalCount.add(qualifiedQty.add(unqualifiedQty));
                qualifiedCount = qualifiedCount.add(qualifiedQty);
                unqualifiedCount = unqualifiedCount.add(unqualifiedQty);
            }
            if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
@@ -2193,13 +2184,17 @@
        dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // 过程
        dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // 出厂
        // 假设 qualityInspectList 是一个 List<QualityInspect> 类型的集合
        Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream()
                .collect(Collectors.groupingBy(QualityInspect::getCheckResult));
        List<QualityInspect> qualityInspects = groupedByCheckResult.get("不合格");
        if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) {
            return null;
        // 根据 unqualifiedQuantity > 0 筛选不合格记录
        List<QualityInspect> qualityInspects = qualityInspectList.stream()
                .filter(i -> i.getUnqualifiedQuantity() != null && i.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.toList());
        if (ObjectUtils.isEmpty(qualityInspects)) {
            // 即使没有不合格记录,也应该返回统计数据,只是图表项为空
            dto.setItem(new ArrayList<>());
            return dto;
        }
        // 4. 处理图表项 (Item)
        List<QualityStatisticsItem> itemList = new ArrayList<>();
@@ -2242,8 +2237,11 @@
    private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) {
        return list.stream()
                .filter(i -> i.getInspectType().equals(type))
                .map(QualityInspect::getQuantity)
                .filter(Objects::nonNull)
                .map(i -> {
                    BigDecimal qualified = i.getQualifiedQuantity() != null ? i.getQualifiedQuantity() : BigDecimal.ZERO;
                    BigDecimal unqualified = i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO;
                    return qualified.add(unqualified);
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
@@ -2251,11 +2249,18 @@
        QualityStatisticsItem item = new QualityStatisticsItem();
        item.setDate(dateLabel);
        item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity)
        // 统计每种检验类型的不合格数量
        item.setSupplierNum(list.stream()
                .filter(i -> i.getInspectType() == 0)
                .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity)
        item.setProcessNum(list.stream()
                .filter(i -> i.getInspectType() == 1)
                .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity)
        item.setFactoryNum(list.stream()
                .filter(i -> i.getInspectType() == 2)
                .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        return item;