gongchunyi
21 小时以前 875adbd59a28453cdf443c3244e2691ad1dd02ac
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -185,28 +185,31 @@
        LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(PurchaseLedger::getEntryDate, currentMonth.atDay(1).atStartOfDay()) // 大于等于本月第一天
                .lt(PurchaseLedger::getEntryDate, currentMonth.plusMonths(1).atDay(1).atStartOfDay()); // 小于下月第一天
        // 执行查询并计算总和
        List<PurchaseLedger> purchaseLedgers = purchaseLedgerMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(purchaseLedgers)) {
            LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<SalesLedgerProduct>();
            salesLedgerProductMapperLambdaQueryWrapperCopy.eq(SalesLedgerProduct::getType, 2)
            LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductMapperLambdaQueryWrapperCopy = new LambdaQueryWrapper<>();
            salesLedgerProductMapperLambdaQueryWrapperCopy.eq(SalesLedgerProduct::getType, 2) // 采购类型
                    .in(SalesLedgerProduct::getSalesLedgerId,
                            purchaseLedgers.stream().map(PurchaseLedger::getId).collect(Collectors.toList()));
            List<SalesLedgerProduct> salesLedgerProductsCopy = salesLedgerProductMapper
                    .selectList(salesLedgerProductMapperLambdaQueryWrapperCopy);
            // 合计合同金额
            // 合计合同总金额
            BigDecimal receiveAmount = purchaseLedgers.stream()
                    .map(PurchaseLedger::getContractAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 未开票金额
            //  待付款总金额
            BigDecimal unReceiptPaymentAmount = salesLedgerProductsCopy.stream()
                    .map(SalesLedgerProduct::getNoInvoiceAmount)
                    .map(SalesLedgerProduct::getPendingTicketsTotal)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            homeBusinessDto.setMonthPurchaseMoney(receiveAmount.setScale(2, RoundingMode.HALF_UP).toString());
            homeBusinessDto
                    .setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString());
            homeBusinessDto.setMonthPurchaseHaveMoney(unReceiptPaymentAmount.setScale(2, RoundingMode.HALF_UP).toString());
        }
        // 统计库存
        BigDecimal stockQuantityTotal = stockInventoryMapper.selectTotal();
@@ -1085,26 +1088,17 @@
    @Override
    public List<Map<String, Object>> productInOutAnalysis(Integer type) {
        String targetName;
        // 0-原材料 1-半成品 2-成品
        Integer modelType;
        if (type == 1) {
            targetName = "原材料";
            modelType = 0;
        } else if (type == 2) {
            targetName = "成品";
            modelType = 2;
        } else if (type == 3) {
            targetName = "半成品";
            modelType = 1;
        } else {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Product::getProductName, targetName).isNull(Product::getParentId);
        Product rootCategory = productMapper.selectOne(queryWrapper);
        if (rootCategory == null) {
            log.warn("未找到名称为 {} 的顶级产品分类", targetName);
            return new ArrayList<>();
        }
        Long rootCategoryId = rootCategory.getId();
        LocalDate now = LocalDate.now();
        DateTimeFormatter displayDtf = DateTimeFormatter.ofPattern("M/d");
@@ -1112,10 +1106,10 @@
        String startDate = now.minusDays(6).toString();
        String endDate = now.toString();
        List<Map<String, Object>> inCounts = stockInventoryMapper.selectDailyStockInCounts(rootCategoryId, startDate,
        List<Map<String, Object>> inCounts = stockInventoryMapper.selectDailyStockInCounts(modelType, startDate,
                endDate + " 23:59:59");
        List<Map<String, Object>> outCounts = stockInventoryMapper.selectDailyStockOutCounts(rootCategoryId, startDate,
        List<Map<String, Object>> outCounts = stockInventoryMapper.selectDailyStockOutCounts(modelType, startDate,
                endDate + " 23:59:59");
        Map<LocalDate, BigDecimal> inMap = inCounts.stream()
@@ -2110,33 +2104,23 @@
                continue;
            }
            // 找到产品大类
            Product parent = product.getParentId() == null
                    ? product
                    : productMap.get(product.getParentId());
            // 找到产品库根节点(产品大类)
            Product rootProduct = findRootProduct(product, productMap);
            if (parent == null) {
                continue;
            }
            String categoryTitle = resolveProductCategory(rootProduct.getProductName());
            switch (parent.getProductName()) {
                case "原材料":
                    rawMaterialCount = rawMaterialCount.add(quantity);
                    break;
                case "半成品":
                    semiFinishedCount = semiFinishedCount.add(quantity);
                    break;
                case "成品":
                    finishedCount = finishedCount.add(quantity);
                    break;
                default:
                    break;
            if ("原材料".equals(categoryTitle)) {
                rawMaterialCount = rawMaterialCount.add(quantity);
            } else if ("半成品".equals(categoryTitle)) {
                semiFinishedCount = semiFinishedCount.add(quantity);
            } else if ("成品".equals(categoryTitle)) {
                finishedCount = finishedCount.add(quantity);
            }
            // 组装明细
            NonComplianceWarningDto.Item child = new NonComplianceWarningDto.Item();
            // child.setProductTitle(item.getProductName());
            child.setParentProductTitle(parent.getProductName());
            child.setParentProductTitle(categoryTitle);
            child.setProductTitle(item.getProductName());
            child.setDescription(item.getDefectivePhenomena());
            child.setDate(formatDate(item.getCheckTime()));
@@ -2155,6 +2139,42 @@
        return dto;
    }
    /**
     * 向上查找产品库根节点(产品大类)
     */
    private Product findRootProduct(Product product, Map<Long, Product> productMap) {
        Product current = product;
        int depth = 0;
        while (current.getParentId() != null && depth++ < 20) {
            Product parent = productMap.get(current.getParentId());
            if (parent == null) {
                break;
            }
            current = parent;
        }
        return current;
    }
    /**
     * 根据产品库根节点名称识别产品大类:原材料/半成品/成品
     * 注意先判断半成品,避免被成品包含
     */
    private String resolveProductCategory(String rootName) {
        if (rootName == null) {
            return "";
        }
        if (rootName.contains("半成品")) {
            return "半成品";
        }
        if (rootName.contains("成品")) {
            return "成品";
        }
        if (rootName.contains("原材料")) {
            return "原材料";
        }
        return rootName;
    }
    private BigDecimal calcRate(BigDecimal part, BigDecimal total) {
        if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO.setScale(2);