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
package cn.iocoder.yudao.module.mes.service.pro.cost;
 
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
import cn.iocoder.yudao.module.mes.service.pro.cost.dto.MesProMaterialPriceRespDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
 
/**
 * MES 物料价格 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class MesProMaterialPriceServiceImpl implements MesProMaterialPriceService {
 
    private static final String SOURCE_PURCHASE_PRICE = "PURCHASE_PRICE";
    private static final String SOURCE_ERP_AVERAGE = "ERP_AVERAGE";
    private static final String SOURCE_NONE = "NONE";
 
    @Resource
    private MesMdItemService itemService;
    @Resource
    private MesMdmItemService mdmItemService;
    @Resource
    private ErpPurchaseOrderApi purchaseOrderApi;
 
    @Override
    public Map<Long, MesProMaterialPriceRespDTO> getMaterialPriceMap(Collection<Long> itemIds) {
        if (CollUtil.isEmpty(itemIds)) {
            return Collections.emptyMap();
        }
        // 1. MES 物料 → MDM 物料
        Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(itemIds);
        Set<Long> mdmItemIds = new HashSet<>();
        for (MesMdItemDO item : itemMap.values()) {
            if (item.getMdmItemId() != null) {
                mdmItemIds.add(item.getMdmItemId());
            }
        }
        Map<Long, MesMdmItemDO> mdmItemMap = mdmItemIds.isEmpty()
                ? Collections.emptyMap() : mdmItemService.getItemMap(mdmItemIds);
 
        // 2. 主数据没有采购价的,查已审核采购订单加权平均价
        Set<Long> missingPriceMdmIds = new HashSet<>();
        for (Long mdmItemId : mdmItemIds) {
            MesMdmItemDO mdmItem = mdmItemMap.get(mdmItemId);
            if (mdmItem == null || !isPositive(mdmItem.getPurchasePrice())) {
                missingPriceMdmIds.add(mdmItemId);
            }
        }
        Map<Long, BigDecimal> averagePriceMap = missingPriceMdmIds.isEmpty()
                ? Collections.emptyMap()
                : purchaseOrderApi.getItemAveragePurchasePriceMap(missingPriceMdmIds).getCheckedData();
 
        // 3. 组装结果
        Map<Long, MesProMaterialPriceRespDTO> result = new HashMap<>(itemMap.size());
        for (Long itemId : itemIds) {
            MesMdItemDO item = itemMap.get(itemId);
            MesMdmItemDO mdmItem = item != null && item.getMdmItemId() != null
                    ? mdmItemMap.get(item.getMdmItemId()) : null;
            BigDecimal purchasePrice = mdmItem != null ? mdmItem.getPurchasePrice() : null;
            BigDecimal averagePrice = mdmItem != null ? averagePriceMap.get(mdmItem.getId()) : null;
            if (isPositive(purchasePrice)) {
                result.put(itemId, buildPrice(itemId, purchasePrice, SOURCE_PURCHASE_PRICE));
            } else if (isPositive(averagePrice)) {
                result.put(itemId, buildPrice(itemId, averagePrice, SOURCE_ERP_AVERAGE));
            } else {
                result.put(itemId, MesProMaterialPriceRespDTO.builder()
                        .itemId(itemId).unitPrice(BigDecimal.ZERO)
                        .source(SOURCE_NONE).priceMissing(true).build());
            }
        }
        return result;
    }
 
    private static MesProMaterialPriceRespDTO buildPrice(Long itemId, BigDecimal price, String source) {
        return MesProMaterialPriceRespDTO.builder()
                .itemId(itemId)
                .unitPrice(price.setScale(6, RoundingMode.HALF_UP))
                .source(source)
                .priceMissing(false)
                .build();
    }
 
    private static boolean isPositive(BigDecimal value) {
        return value != null && value.compareTo(BigDecimal.ZERO) > 0;
    }
 
}