gaoluyang
3 天以前 d39e4f7d839167c16425086dfa2f8747bccfdff9
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. 口径与单个供应商详情保持一致:订单按审核状态过滤、来票不过滤状态、付款含未审核/审批中/已审核
        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. 填充供应商编码 / 名称(SRM 中已删除的供应商用 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;
    }