gongchunyi
6 天以前 7828b982da116070fe11526733609ecce23631b6
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -308,6 +308,47 @@
        return analysisCustomerContractAmountsDto;
    }
    private static BigDecimal nz(BigDecimal v) {
        return v == null ? BigDecimal.ZERO : v;
    }
    /**
     * 大屏/报表统计用合格数量:以 qualified_quantity
     */
    private BigDecimal inspectQualifiedQtyForStat(QualityInspect item) {
        if (item.getQualifiedQuantity() != null) {
            return item.getQualifiedQuantity();
        }
        BigDecimal qty = nz(item.getQuantity());
        if ("合格".equals(item.getCheckResult())) {
            return qty;
        }
        return BigDecimal.ZERO;
    }
    /**
     * 大屏/报表统计用不合格数量:以 unqualified_quantity
     */
    private BigDecimal inspectUnqualifiedQtyForStat(QualityInspect item) {
        if (item.getUnqualifiedQuantity() != null) {
            return item.getUnqualifiedQuantity();
        }
        BigDecimal qty = nz(item.getQuantity());
        String cr = item.getCheckResult();
        if ("不合格".equals(cr) || "部分合格".equals(cr)) {
            return qty;
        }
        return BigDecimal.ZERO;
    }
    private boolean inspectHasUnqualifiedVolume(QualityInspect item) {
        return inspectUnqualifiedQtyForStat(item).compareTo(BigDecimal.ZERO) > 0;
    }
    private static int toStatInt(BigDecimal v) {
        return nz(v).setScale(0, RoundingMode.HALF_UP).intValue();
    }
    @Override
    public QualityStatisticsDto qualityStatistics() {
        // 获取近四个月数据(往前推三个月,共4个完整月份)
@@ -355,29 +396,27 @@
            QualityStatisticsItem item = new QualityStatisticsItem();
            item.setDate(monthStart.format(monthFormatter)); // 日期显示为“年月”(如 2025-10)
            // 1. 供应商检验(类型0)- 合格数量
            BigDecimal supplierQualified = monthInspects.stream()
            // 1~3:本月「不合格数量」(仅已提交检验),按检验类别拆分——用于图表图例「××不合格数」
            BigDecimal supplierUnq = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(0)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                            && Objects.equals(inspect.getInspectState(), 1))
                    .map(this::inspectUnqualifiedQtyForStat)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setSupplierNum(supplierQualified);
            item.setSupplierNum(supplierUnq);
            // 2. 工序检验(类型1)- 合格数量
            BigDecimal processQualified = monthInspects.stream()
            BigDecimal processUnq = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(1)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                            && Objects.equals(inspect.getInspectState(), 1))
                    .map(this::inspectUnqualifiedQtyForStat)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setProcessNum(processQualified);
            item.setProcessNum(processUnq);
            // 3. 工厂检验(类型2)- 合格数量
            BigDecimal factoryQualified = monthInspects.stream()
            BigDecimal factoryUnq = monthInspects.stream()
                    .filter(inspect -> inspect.getInspectType().equals(2)
                            && "合格".equals(inspect.getCheckResult()))
                    .map(QualityInspect::getQuantity)
                            && Objects.equals(inspect.getInspectState(), 1))
                    .map(this::inspectUnqualifiedQtyForStat)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            item.setFactoryNum(factoryQualified);
            item.setFactoryNum(factoryUnq);
            qualityStatisticsItems.add(item);
        }
@@ -666,64 +705,21 @@
    @Override
    public HomeSummaryDto summaryStatistics() {
        HomeSummaryDto dto = new HomeSummaryDto();
        LocalDate now = LocalDate.now();
        YearMonth currentMonth = YearMonth.from(now);
        YearMonth prevMonth = currentMonth.minusMonths(1);
        LocalDateTime currentMonthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59);
        LocalDateTime prevMonthEnd = prevMonth.atEndOfMonth().atTime(23, 59, 59);
        // 总工作人员
        Long currentStaff = countStaff(currentMonthEnd);
        Long prevStaff = countStaff(prevMonthEnd);
        Long currentStaff = 0L;
        dto.setTotalStaff(currentStaff);
        dto.setStaffGrowthRate(calculateMoM(currentStaff, prevStaff));
        // 总客户数
        Long currentCustomers = countCustomers(currentMonthEnd);
        Long prevCustomers = countCustomers(prevMonthEnd);
        Long currentCustomers = customerMapper.selectCount(null);
        dto.setTotalCustomer(currentCustomers);
        dto.setCustomerGrowthRate(calculateMoM(currentCustomers, prevCustomers));
        // 总供应商数
        Long currentSuppliers = countSuppliers(currentMonthEnd);
        Long prevSuppliers = countSuppliers(prevMonthEnd);
        Long currentSuppliers = supplierManageMapper.selectCount(null);
        dto.setTotalSupplier(currentSuppliers);
        dto.setSupplierGrowthRate(calculateMoM(currentSuppliers, prevSuppliers));
        return dto;
    }
    private Long countStaff(LocalDateTime dateTime) {
        Long staffCountItem = staffOnJobMapper.selectCount(new LambdaQueryWrapper<StaffOnJob>()
                .isNotNull(StaffOnJob::getStaffState)
                .eq(StaffOnJob::getStaffState, 1)
                .le(StaffOnJob::getCreateTime, dateTime));
        return staffCountItem;
    }
    private Long countCustomers(LocalDateTime dateTime) {
        return customerMapper.selectCount(new LambdaQueryWrapper<Customer>()
                .le(Customer::getMaintenanceTime, dateTime.toLocalDate()));
    }
    private Long countSuppliers(LocalDateTime dateTime) {
        return supplierManageMapper.selectCount(new LambdaQueryWrapper<SupplierManage>()
                .le(SupplierManage::getCreateTime, dateTime));
    }
    private String calculateMoM(Number current, Number prev) {
        BigDecimal curVal = new BigDecimal(current.toString());
        BigDecimal prevVal = new BigDecimal(prev.toString());
        if (prevVal.compareTo(BigDecimal.ZERO) == 0) {
            return curVal.compareTo(BigDecimal.ZERO) > 0 ? "100.00" : "0.00";
        }
        return curVal.subtract(prevVal)
                .divide(prevVal, 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal("100"))
                .setScale(2, RoundingMode.HALF_UP)
                .toString();
    }
    @Override
    public List<SupplierPurchaseRankingDto> supplierPurchaseRanking(Integer type) {
@@ -1945,17 +1941,14 @@
        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(inspectQualifiedQtyForStat(item));
            unqualifiedCount = unqualifiedCount.add(inspectUnqualifiedQtyForStat(item));
        }
        BigDecimal totalCount = qualifiedCount.add(unqualifiedCount);
        dto.setQualifiedCount(qualifiedCount.intValue());
        dto.setUnqualifiedCount(unqualifiedCount.intValue());
        dto.setQualifiedCount(toStatInt(qualifiedCount));
        dto.setUnqualifiedCount(toStatInt(unqualifiedCount));
        if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
            dto.setQualifiedRate(BigDecimal.ZERO.setScale(2));
@@ -2218,13 +2211,8 @@
                continue;
            }
            BigDecimal quantity = item.getQuantity();
            if ("合格".equals(item.getCheckResult())) {
                dto.setQualifiedCount(dto.getQualifiedCount().add(quantity));
            } else {
                dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity));
            }
            dto.setQualifiedCount(dto.getQualifiedCount().add(inspectQualifiedQtyForStat(item)));
            dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(inspectUnqualifiedQtyForStat(item)));
        }
        // 计算合格率
@@ -2265,14 +2253,11 @@
            BigDecimal unqualifiedCount = BigDecimal.ZERO;
            for (QualityInspect item : items) {
                BigDecimal qty = item.getQuantity();
                BigDecimal qty = nz(item.getQuantity());
                totalCount = totalCount.add(qty);
                if ("合格".equals(item.getCheckResult())) {
                    qualifiedCount = qualifiedCount.add(qty);
                } else {
                    unqualifiedCount = unqualifiedCount.add(qty);
                }
                qualifiedCount = qualifiedCount.add(inspectQualifiedQtyForStat(item));
                unqualifiedCount = unqualifiedCount.add(inspectUnqualifiedQtyForStat(item));
            }
            if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
@@ -2401,10 +2386,10 @@
        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("不合格");
        // 存在不合格数量的检验单(含按数量拆分的新数据;旧数据仍可用检测结果兜底)
        List<QualityInspect> qualityInspects = qualityInspectList.stream()
                .filter(this::inspectHasUnqualifiedVolume)
                .collect(Collectors.toList());
        if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) {
            return dto;
        }
@@ -2459,11 +2444,11 @@
        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(this::inspectUnqualifiedQtyForStat)
                .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(this::inspectUnqualifiedQtyForStat)
                .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(this::inspectUnqualifiedQtyForStat)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        return item;