gaoluyang
2026-10-30 cbadfd8e691ab335965202a984db16e55ac8e42c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package cn.iocoder.yudao.module.erp.service.statistics;
 
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale.ErpSaleCustomerSummaryRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.statistics.vo.sale.ErpSaleProductSummaryRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleCustomerReceiptStatisticsDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleCustomerStatisticsDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleProductStatisticsDO;
import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
 
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
/**
 * ERP 销售统计 Service 实现类
 *
 * @author 超级管理员
 */
@Service
public class ErpSaleStatisticsServiceImpl implements ErpSaleStatisticsService {
 
    @Resource
    private ErpSaleStatisticsMapper saleStatisticsMapper;
 
    @Resource
    private CrmCustomerApi customerApi;
 
    @Resource
    private MdmItemApi mdmItemApi;
 
    @Override
    public BigDecimal getSalePrice(LocalDateTime beginTime, LocalDateTime endTime) {
        return saleStatisticsMapper.getSalePrice(beginTime, endTime);
    }
 
    @Override
    public List<ErpSaleCustomerSummaryRespVO> getCustomerSummary(Long customerId, LocalDateTime beginTime, LocalDateTime endTime) {
        List<ErpSaleCustomerStatisticsDO> saleList = saleStatisticsMapper.selectCustomerStatistics(customerId, beginTime, endTime);
        if (CollectionUtils.isAnyEmpty(saleList)) {
            return new ArrayList<>();
        }
        // 1. 已收款金额按客户归集(收款单可能早于/晚于订单,不做订单级勾稽,只按客户汇总)
        Map<Long, BigDecimal> receiptMap = CollectionUtils.convertMap(
                saleStatisticsMapper.selectCustomerReceiptStatistics(customerId, beginTime, endTime),
                ErpSaleCustomerReceiptStatisticsDO::getCustomerId,
                ErpSaleCustomerReceiptStatisticsDO::getReceiptAmount);
        // 2. 客户名称
        Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(
                CollectionUtils.convertSet(saleList, ErpSaleCustomerStatisticsDO::getCustomerId));
        // 3. 组装
        List<ErpSaleCustomerSummaryRespVO> result = new ArrayList<>(saleList.size());
        for (ErpSaleCustomerStatisticsDO sale : saleList) {
            BigDecimal saleAmount = sale.getSaleAmount() == null ? BigDecimal.ZERO : sale.getSaleAmount();
            BigDecimal receiptAmount = receiptMap.getOrDefault(sale.getCustomerId(), BigDecimal.ZERO);
            CrmCustomerRespDTO customer = customerMap.get(sale.getCustomerId());
            ErpSaleCustomerSummaryRespVO vo = new ErpSaleCustomerSummaryRespVO();
            vo.setCustomerId(sale.getCustomerId());
            vo.setCustomerName(customer != null ? customer.getName() : "客户(" + sale.getCustomerId() + ")");
            vo.setOrderCount(sale.getOrderCount());
            vo.setSaleAmount(saleAmount);
            vo.setReceiptAmount(receiptAmount);
            vo.setUnreceivedAmount(saleAmount.subtract(receiptAmount));
            vo.setLastOrderTime(sale.getLastOrderTime());
            result.add(vo);
        }
        return result;
    }
 
    @Override
    public List<ErpSaleProductSummaryRespVO> getProductSummary(Long productId, LocalDateTime beginTime, LocalDateTime endTime) {
        List<ErpSaleProductStatisticsDO> saleList = saleStatisticsMapper.selectProductStatistics(productId, beginTime, endTime);
        if (CollectionUtils.isAnyEmpty(saleList)) {
            return new ArrayList<>();
        }
        // 1. 产品名称与参考成本价
        Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
                CollectionUtils.convertSet(saleList, ErpSaleProductStatisticsDO::getProductId));
        // 2. 组装,毛利 = 销售金额 - 数量 × 参考成本价
        List<ErpSaleProductSummaryRespVO> result = new ArrayList<>(saleList.size());
        for (ErpSaleProductStatisticsDO sale : saleList) {
            MdmItemRespDTO item = itemMap.get(sale.getProductId());
            BigDecimal saleAmount = sale.getSaleAmount() == null ? BigDecimal.ZERO : sale.getSaleAmount();
            BigDecimal costPrice = item != null && item.getCostPrice() != null ? item.getCostPrice() : BigDecimal.ZERO;
            BigDecimal totalCount = sale.getTotalCount() == null ? BigDecimal.ZERO : sale.getTotalCount();
            BigDecimal costAmount = costPrice.multiply(totalCount);
            ErpSaleProductSummaryRespVO vo = new ErpSaleProductSummaryRespVO();
            vo.setProductId(sale.getProductId());
            vo.setProductName(item != null ? item.getName() : "产品(" + sale.getProductId() + ")");
            vo.setOrderCount(sale.getOrderCount());
            vo.setTotalCount(totalCount);
            vo.setSaleAmount(saleAmount);
            vo.setCostAmount(costAmount);
            vo.setProfitAmount(saleAmount.subtract(costAmount));
            result.add(vo);
        }
        return result;
    }
 
}