From d39e4f7d839167c16425086dfa2f8747bccfdff9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 05 十一月 2026 17:39:01 +0800
Subject: [PATCH] feat: 打通销售采购财务闭环并完成累计业务优化

---
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierStatementServiceImpl.java |   96 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierStatementServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierStatementServiceImpl.java
index ba1084c..aa7350a 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierStatementServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierStatementServiceImpl.java
@@ -1,9 +1,12 @@
 package cn.iocoder.yudao.module.erp.service.purchase;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.statement.ErpSupplierStatementReqVO;
 import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.statement.ErpSupplierStatementRespVO;
+import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.statement.ErpSupplierStatementSummaryReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.statement.ErpSupplierStatementSummaryRespVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
@@ -156,6 +159,99 @@
         return respVO;
     }
 
+    @Override
+    public List<ErpSupplierStatementSummaryRespVO> getSupplierSummaryList(ErpSupplierStatementSummaryReqVO reqVO) {
+        // 1. 鍙e緞涓庡崟涓緵搴斿晢璇︽儏淇濇寔涓�鑷达細璁㈠崟鎸夊鏍哥姸鎬佽繃婊ゃ�佹潵绁ㄤ笉杩囨护鐘舵�併�佷粯娆惧惈鏈鏍�/瀹℃壒涓�/宸插鏍�
+        List<Integer> orderStatuses = Boolean.TRUE.equals(reqVO.getIncludeUnapprovedOrder())
+                ? List.of(ErpAuditStatus.PROCESS.getStatus(), ErpAuditStatus.APPROVING.getStatus(),
+                ErpAuditStatus.APPROVE.getStatus())
+                : List.of(ErpAuditStatus.APPROVE.getStatus());
+        List<ErpPurchaseOrderDO> orders = purchaseOrderMapper.selectListByOrderTimeBetween(
+                reqVO.getBeginTime(), reqVO.getEndTime(), orderStatuses);
+        List<ErpPurchaseInvoiceDO> invoices = purchaseInvoiceMapper.selectListByInvoiceTimeBetween(
+                reqVO.getBeginTime(), reqVO.getEndTime());
+        List<Integer> paymentStatuses = List.of(ErpAuditStatus.PROCESS.getStatus(),
+                ErpAuditStatus.APPROVING.getStatus(), ErpAuditStatus.APPROVE.getStatus());
+        List<ErpFinancePaymentDO> payments = financePaymentMapper.selectListByPaymentTimeBetween(
+                reqVO.getBeginTime(), reqVO.getEndTime(), paymentStatuses);
+
+        // 2. 鎸変緵搴斿晢姹囨��
+        Map<Long, ErpSupplierStatementSummaryRespVO> summaryMap = new HashMap<>();
+        for (ErpPurchaseOrderDO order : orders) {
+            if (order.getSupplierId() == null) {
+                continue;
+            }
+            ErpSupplierStatementSummaryRespVO summary = getOrCreateSummary(summaryMap, order.getSupplierId());
+            summary.setOrderCount(summary.getOrderCount() + 1);
+            summary.setTotalPurchaseAmount(summary.getTotalPurchaseAmount().add(zero(order.getTotalPrice())));
+        }
+        for (ErpPurchaseInvoiceDO invoice : invoices) {
+            if (invoice.getSupplierId() == null) {
+                continue;
+            }
+            ErpSupplierStatementSummaryRespVO summary = getOrCreateSummary(summaryMap, invoice.getSupplierId());
+            summary.setInvoiceCount(summary.getInvoiceCount() + 1);
+            summary.setTotalInvoiceAmount(summary.getTotalInvoiceAmount().add(zero(invoice.getPrice())));
+        }
+        for (ErpFinancePaymentDO payment : payments) {
+            if (payment.getSupplierId() == null) {
+                continue;
+            }
+            ErpSupplierStatementSummaryRespVO summary = getOrCreateSummary(summaryMap, payment.getSupplierId());
+            summary.setPaymentCount(summary.getPaymentCount() + 1);
+            summary.setTotalPaymentAmount(summary.getTotalPaymentAmount().add(zero(payment.getPaymentPrice())));
+        }
+
+        // 3. 濉厖渚涘簲鍟嗙紪鐮� / 鍚嶇О锛圫RM 涓凡鍒犻櫎鐨勪緵搴斿晢鐢� ID 鍏滃簳灞曠ず锛岄伩鍏嶅嚭鐜扮┖琛岋級
+        Map<Long, SrmSupplierRespDTO> supplierMap = new HashMap<>();
+        if (!summaryMap.isEmpty()) {
+            List<SrmSupplierRespDTO> suppliers = srmSupplierApi.getSupplierList(summaryMap.keySet()).getCheckedData();
+            if (CollUtil.isNotEmpty(suppliers)) {
+                suppliers.forEach(item -> supplierMap.put(item.getId(), item));
+            }
+        }
+        for (ErpSupplierStatementSummaryRespVO summary : summaryMap.values()) {
+            summary.setUnpaidAmount(summary.getTotalInvoiceAmount().subtract(summary.getTotalPaymentAmount()));
+            SrmSupplierRespDTO supplier = supplierMap.get(summary.getSupplierId());
+            if (supplier == null) {
+                summary.setSupplierName("鏈煡渚涘簲鍟�(ID=" + summary.getSupplierId() + ")");
+                continue;
+            }
+            summary.setSupplierCode(supplier.getCode());
+            summary.setSupplierName(StrUtil.blankToDefault(supplier.getName(),
+                    "鏈懡鍚嶄緵搴斿晢(ID=" + summary.getSupplierId() + ")"));
+        }
+
+        // 4. 鏈粯浣欓澶氱殑鎺掑墠闈紝鍏舵鎸夐噰璐銆佷緵搴斿晢鍚嶇О
+        Comparator<ErpSupplierStatementSummaryRespVO> comparator =
+                Comparator.comparing(ErpSupplierStatementSummaryRespVO::getUnpaidAmount,
+                                Comparator.nullsFirst(Comparator.<BigDecimal>naturalOrder()))
+                        .thenComparing(ErpSupplierStatementSummaryRespVO::getTotalPurchaseAmount,
+                                Comparator.nullsFirst(Comparator.<BigDecimal>naturalOrder()))
+                        .reversed()
+                        .thenComparing(ErpSupplierStatementSummaryRespVO::getSupplierName,
+                                Comparator.nullsLast(Comparator.naturalOrder()));
+        return summaryMap.values().stream()
+                .sorted(comparator)
+                .collect(Collectors.toList());
+    }
+
+    private ErpSupplierStatementSummaryRespVO getOrCreateSummary(
+            Map<Long, ErpSupplierStatementSummaryRespVO> summaryMap, Long supplierId) {
+        return summaryMap.computeIfAbsent(supplierId, id -> {
+            ErpSupplierStatementSummaryRespVO summary = new ErpSupplierStatementSummaryRespVO();
+            summary.setSupplierId(id);
+            summary.setOrderCount(0);
+            summary.setInvoiceCount(0);
+            summary.setPaymentCount(0);
+            summary.setTotalPurchaseAmount(BigDecimal.ZERO);
+            summary.setTotalInvoiceAmount(BigDecimal.ZERO);
+            summary.setTotalPaymentAmount(BigDecimal.ZERO);
+            summary.setUnpaidAmount(BigDecimal.ZERO);
+            return summary;
+        });
+    }
+
     private BigDecimal zero(BigDecimal value) {
         return value != null ? value : BigDecimal.ZERO;
     }

--
Gitblit v1.9.3