From 1f5fdca1ab73461fb930f64c26dcb4038a9d4bf7 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 25 五月 2026 10:10:06 +0800
Subject: [PATCH] 11

---
 src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java |  232 +++++++++++++++++++++++++++++++++------------------------
 1 files changed, 133 insertions(+), 99 deletions(-)

diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index e4e8888..87a2358 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -3,10 +3,18 @@
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto;
+import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto;
+import com.ruoyi.account.bean.dto.sales.SalesOutboundDto;
+import com.ruoyi.account.bean.dto.sales.SalesReturnDto;
+import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
+import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo;
+import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
+import com.ruoyi.account.bean.vo.sales.SalesReturnVo;
 import com.ruoyi.account.mapper.AccountStatementMapper;
 import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
 import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
-import com.ruoyi.account.pojo.AccountStatement;
 import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
 import com.ruoyi.account.pojo.sales.AccountSalesCollection;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
@@ -29,11 +37,13 @@
 import com.ruoyi.home.dto.*;
 import com.ruoyi.home.mapper.HomeMapper;
 import com.ruoyi.home.service.HomeService;
+import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper;
 import com.ruoyi.production.bean.dto.ProductionProductOutputDto;
 import com.ruoyi.production.mapper.*;
 import com.ruoyi.project.system.domain.SysDept;
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
 import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
@@ -45,7 +55,9 @@
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.StaffOnJob;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
 import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -71,6 +83,10 @@
 public class HomeServiceImpl implements HomeService {
 
     private final SalesLedgerMapper salesLedgerMapper;
+    private final StockOutRecordMapper stockOutRecordMapper;
+    private final ReturnManagementMapper returnManagementMapper;
+    private final StockInRecordMapper stockInRecordMapper;
+    private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
 
     private final PurchaseLedgerMapper purchaseLedgerMapper;
 
@@ -417,14 +433,26 @@
         LocalDate startDate = range[0];
         LocalDate endDate = range[1];
 
+        //閿�鍞嚭搴�
         BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate);
+        //閿�鍞��璐�
+        BigDecimal salesReturnAmount = sumSalesReturnAmount(startDate, endDate);
+        //閲囪喘鍏ュ簱
         BigDecimal payableBase = sumPurchaseContractAmount(startDate, endDate);
+        //閲囪喘閫�璐�
+        BigDecimal purchaseReturnAmount = sumPurchaseReturnAmount(startDate, endDate);
+        //鏀舵
         BigDecimal advanceMoney = sumCollectionAmount(startDate, endDate);
+        //浠樻
         BigDecimal prepayMoney = sumPaymentAmount(startDate, endDate);
 
-        dto.setReceivableMoney(scaleMoney(maxZero(receivableBase.subtract(advanceMoney))));
-        dto.setPayableMoney(scaleMoney(maxZero(payableBase.subtract(prepayMoney))));
+        //搴旀敹閲戦=閿�鍞嚭搴�-閿�鍞��璐�
+        dto.setReceivableMoney(scaleMoney(maxZero(receivableBase.subtract(salesReturnAmount))));
+        //搴斾粯閲戦=閲囪喘鍏ュ簱-閲囪喘閫�璐�
+        dto.setPayableMoney(scaleMoney(maxZero(payableBase.subtract(purchaseReturnAmount))));
+        //鏀舵閲戦=鏀舵鍗�
         dto.setAdvanceMoney(scaleMoney(advanceMoney));
+        //浠樻閲戦=浠樻鍗�
         dto.setPrepayMoney(scaleMoney(prepayMoney));
         return dto;
     }
@@ -991,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) {
@@ -1239,33 +1267,21 @@
         YearMonth currentMonth = YearMonth.from(today);
         LocalDate startDate = currentMonth.atDay(1);
         LocalDate endDate = currentMonth.atEndOfMonth();
-
+        //鏀舵
         BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate);
+        //閿�鍞嚭搴�
         BigDecimal receivableBase = sumSalesContractAmount(startDate, endDate);
-        String collectionRate = toRateString(monthlyIncome, receivableBase);
-
-        String currentMonthText = currentMonth.toString();
-        List<AccountStatement> receivableStatements = defaultList(accountStatementMapper.selectList(
-                new LambdaQueryWrapper<AccountStatement>()
-                        .eq(AccountStatement::getAccountType, 1)
-                        .le(AccountStatement::getStatementMonth, currentMonthText)));
-
-        long overdueNum = receivableStatements.stream()
-                .filter(item -> item.getStatementMonth() != null && item.getStatementMonth().compareTo(currentMonthText) < 0)
-                .filter(item -> defaultDecimal(item.getClosingBalance()).compareTo(BigDecimal.ZERO) > 0)
-                .count();
-
-        long totalReceivableCount = receivableStatements.size();
-        String overdueRate = totalReceivableCount == 0
-                ? "0.00"
-                : BigDecimal.valueOf(overdueNum)
-                .multiply(BigDecimal.valueOf(100))
-                .divide(BigDecimal.valueOf(totalReceivableCount), 2, RoundingMode.HALF_UP)
-                .toString();
-
+        //閿�鍞��璐�
+        BigDecimal salesReturnAmount = sumSalesReturnAmount(startDate, endDate);
+        //鍥炴鐜�=鏀舵/(閿�鍞嚭搴�-閿�鍞��璐�)搴旀敹
+        String collectionRate = toRateString(monthlyIncome, receivableBase.subtract(salesReturnAmount));
+        //閫炬湡鏁�=(閿�鍞嚭搴撻噾棰�-閿�鍞��璐ч噾棰�)搴旀敹閲戦-鏀舵閲戦
+        BigDecimal overdueAmount = receivableBase.subtract(salesReturnAmount).subtract(monthlyIncome);
+        //閫炬湡鐜�=閫炬湡鏁�/搴旀敹閲戦
+        String overdueRate = toRateString(overdueAmount, receivableBase);
         dto.setMonthlyIncome(scaleMoney(monthlyIncome));
         dto.setCollectionRate(collectionRate);
-        dto.setOverdueNum(BigDecimal.valueOf(overdueNum));
+        dto.setOverdueNum(overdueAmount);
         dto.setOverdueRate(overdueRate);
         return dto;
     }
@@ -1277,16 +1293,25 @@
         YearMonth currentMonth = YearMonth.from(today);
         LocalDate startDate = currentMonth.atDay(1);
         LocalDate endDate = currentMonth.atEndOfMonth();
-
+        //鏀嚭
         BigDecimal monthlyExpenditure = sumPaymentAmount(startDate, endDate);
+        //閲囪喘鍏ュ簱
         BigDecimal payableBase = sumPurchaseContractAmount(startDate, endDate);
+        //閲囪喘閫�璐�
+        BigDecimal purchaseReturnAmount = sumPurchaseReturnAmount(startDate, endDate);
+        //浠樻鐜�=浠樻/(閲囪喘鍏ュ簱-閲囪喘閫�璐�)搴斾粯
+        String paymentRate = toRateString(monthlyExpenditure, payableBase.subtract(purchaseReturnAmount));
+        //鏀舵
         BigDecimal monthlyIncome = sumCollectionAmount(startDate, endDate);
+        //姣涘埄娑�= 鏀舵-鏀嚭
         BigDecimal grossProfit = monthlyIncome.subtract(monthlyExpenditure);
+        //鍒╂鼎鐜�=姣涘埄娑�/鏀舵
+        String profitMarginRate = toRateString(grossProfit, monthlyIncome);
 
         dto.setMonthlyExpenditure(scaleMoney(monthlyExpenditure));
-        dto.setPaymentRate(toRateString(monthlyExpenditure, payableBase));
+        dto.setPaymentRate(paymentRate);
         dto.setGrossProfit(scaleMoney(grossProfit));
-        dto.setProfitMarginRate(toRateString(grossProfit, monthlyIncome));
+        dto.setProfitMarginRate(profitMarginRate);
         return dto;
     }
 
@@ -1453,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;
+
+                    // 鑹搧鏁� = 鎬绘姇鍏ユ暟 - 鎶ュ簾鏁� (瀵瑰簲浣犲師浠g爜涓� 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());
@@ -1890,7 +1900,7 @@
             }
 
             switch (parent.getProductName()) {
-                case "鍘熸潗鏂�":
+                case "鍘熸枡":
                     rawMaterialCount = rawMaterialCount.add(quantity);
                     break;
                 case "鍗婃垚鍝�":
@@ -2317,20 +2327,43 @@
         return new LocalDate[]{startDate, endDate};
     }
 
+    //璁$畻鏃ユ湡鍐呯殑閿�鍞嚭搴撻噾棰�
     private BigDecimal sumSalesContractAmount(LocalDate startDate, LocalDate endDate) {
-        List<SalesLedger> salesLedgers = defaultList(salesLedgerMapper.selectList(new LambdaQueryWrapper<SalesLedger>()
-                .ge(SalesLedger::getEntryDate, toDate(startDate))
-                .lt(SalesLedger::getEntryDate, toExclusiveEndDate(endDate))));
-        return sumAmount(salesLedgers, SalesLedger::getContractAmount);
+        SalesOutboundDto salesOutboundDto = new SalesOutboundDto();
+        salesOutboundDto.setStartDate(startDate);
+        salesOutboundDto.setEndDate(endDate);
+        List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords();
+        return sumAmount(salesOutboundVos, SalesOutboundVo::getOutboundAmount);
     }
 
+    //璁$畻鏃ユ湡鍐呯殑閿�鍞��璐ч噾棰�
+    private BigDecimal sumSalesReturnAmount(LocalDate startDate, LocalDate endDate) {
+        SalesReturnDto salesReturnDto = new SalesReturnDto();
+        salesReturnDto.setStartDate(startDate);
+        salesReturnDto.setEndDate(endDate);
+        List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords();
+        return sumAmount(salesReturnVos, SalesReturnVo::getRefundAmount);
+    }
+
+    //璁$畻鏃ユ湡鍐呯殑閲囪喘鍏ュ簱閲戦
     private BigDecimal sumPurchaseContractAmount(LocalDate startDate, LocalDate endDate) {
-        List<PurchaseLedger> purchaseLedgers = defaultList(purchaseLedgerMapper.selectList(new LambdaQueryWrapper<PurchaseLedger>()
-                .ge(PurchaseLedger::getEntryDate, toDate(startDate))
-                .lt(PurchaseLedger::getEntryDate, toExclusiveEndDate(endDate))));
-        return sumAmount(purchaseLedgers, PurchaseLedger::getContractAmount);
+        PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto();
+        purchaseInboundDto.setStartDate(startDate);
+        purchaseInboundDto.setEndDate(endDate);
+        List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords();
+        return sumAmount(purchaseInboundVos, PurchaseInboundVo::getInboundAmount);
     }
 
+    //璁$畻鏃ユ湡鍐呯殑閲囪喘閫�璐ч噾棰�
+    private BigDecimal sumPurchaseReturnAmount(LocalDate startDate, LocalDate endDate) {
+        PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto();
+        purchaseReturnDto.setStartDate(startDate);
+        purchaseReturnDto.setEndDate(endDate);
+        List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords();
+        return sumAmount(purchaseReturnVos, PurchaseReturnVo::getTotalAmount);
+    }
+
+    //璁$畻鏃ユ湡鍐呯殑鎬绘敹娆鹃噾棰�
     private BigDecimal sumCollectionAmount(LocalDate startDate, LocalDate endDate) {
         List<AccountSalesCollection> collections = defaultList(accountSalesCollectionMapper.selectList(
                 new LambdaQueryWrapper<AccountSalesCollection>()
@@ -2339,6 +2372,7 @@
         return sumAmount(collections, AccountSalesCollection::getCollectionAmount);
     }
 
+    //璁$畻鏃ユ湡鍐呯殑鎬讳粯娆鹃噾棰�
     private BigDecimal sumPaymentAmount(LocalDate startDate, LocalDate endDate) {
         List<AccountPurchasePayment> payments = defaultList(accountPurchasePaymentMapper.selectList(
                 new LambdaQueryWrapper<AccountPurchasePayment>()

--
Gitblit v1.9.3