liyong
4 天以前 be5783c8a7e13bbc76d33c95643d75779cce21db
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package cn.iocoder.yudao.module.erp.service.sale.listener;
 
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO;
import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi;
import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
 
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
 
/**
 * 销售订单审批状态监听器
 *
 * 监听 BPM 流程实例状态变更事件,审核通过时自动创建 MPS
 *
 * @author 芋道源码
 */
@Component
@Slf4j
public class ErpSaleOrderStatusListener extends cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener {
 
    /**
     * 销售订单审批流程定义 Key
     */
    private static final String PROCESS_DEFINITION_KEY = "sale_order_approve";
 
    @Resource
    private ErpSaleOrderMapper saleOrderMapper;
    @Resource
    private ErpSaleOrderItemMapper saleOrderItemMapper;
    @Resource
    private MesProMpsApi mpsApi;
    @Resource
    private MdmItemApi mdmItemApi;
 
    @Override
    protected String getProcessDefinitionKey() {
        return PROCESS_DEFINITION_KEY;
    }
 
    @Override
    protected void onEvent(BpmProcessInstanceStatusEvent event) {
        Long orderId;
        try {
            orderId = Long.parseLong(event.getBusinessKey());
        } catch (NumberFormatException e) {
            log.warn("[onEvent] businessKey({}) 不是有效的销售订单编号", event.getBusinessKey());
            return;
        }
 
        log.info("[onEvent] 收到 BPM 审批事件,orderId={}, status={}", orderId, event.getStatus());
 
        // 只有审批通过才创建 MPS
        if (!BpmTaskStatusEnum.APPROVE.getStatus().equals(event.getStatus())) {
            return;
        }
 
        try {
            // 1. 获取销售订单
            ErpSaleOrderDO saleOrder = saleOrderMapper.selectById(orderId);
            if (saleOrder == null) {
                log.warn("[onEvent] 销售订单不存在,orderId={}", orderId);
                return;
            }
 
            // 2. 获取销售订单明细
            List<ErpSaleOrderItemDO> items = saleOrderItemMapper.selectListByOrderId(orderId);
            if (CollUtil.isEmpty(items)) {
                log.info("[onEvent] 销售订单({}) 没有明细,无需创建 MPS", orderId);
                return;
            }
 
            // 3. 更新订单状态为已审核
            saleOrderMapper.updateById(new ErpSaleOrderDO()
                    .setId(orderId)
                    .setStatus(ErpAuditStatus.APPROVE.getStatus()));
 
            // 4. 遍历明细,为需要生产的明细创建 MPS
            int mpsCount = 0;
            for (ErpSaleOrderItemDO item : items) {
                if (item.getNeedProduction() == null || item.getNeedProduction() != 1) {
                    continue;
                }
                try {
                    Long mpsId = createMpsForSaleOrderItem(saleOrder, item);
                    if (mpsId != null) {
                        mpsCount++;
                        // 更新销售订单明细的 MPS 关联
                        saleOrderItemMapper.updateById(new ErpSaleOrderItemDO()
                                .setId(item.getId())
                                .setMpsId(mpsId));
                    }
                } catch (Exception e) {
                    log.error("[onEvent] 创建 MPS 失败,saleOrderItemId={}", item.getId(), e);
                }
            }
 
            log.info("[onEvent] 销售订单({}) 审批完成,创建 MPS {} 条", orderId, mpsCount);
        } catch (Exception e) {
            log.error("[onEvent] 处理销售订单审批事件失败,orderId={}", orderId, e);
        }
    }
 
    /**
     * 为销售订单明细创建 MPS
     *
     * 注意:销售订单明细的 productId 是 MDM 物料 ID,需要映射到 MES 产品
     */
    private Long createMpsForSaleOrderItem(ErpSaleOrderDO saleOrder, ErpSaleOrderItemDO item) {
        // 获取 MDM 物料信息(用于获取产品名称)
        String productName = null;
        try {
            MdmItemRespDTO mdmItem = mdmItemApi.getItem(item.getProductId()).getCheckedData();
            if (mdmItem != null) {
                productName = mdmItem.getName();
            }
        } catch (Exception e) {
            log.warn("[createMpsForSaleOrderItem] 获取 MDM 物料信息失败,productId={}", item.getProductId(), e);
        }
 
        MesProMpsCreateReqDTO createReqDTO = new MesProMpsCreateReqDTO();
        createReqDTO.setSaleOrderId(saleOrder.getId());
        createReqDTO.setSaleOrderNo(saleOrder.getNo());
        createReqDTO.setSaleOrderItemId(item.getId());
        createReqDTO.setMdmItemId(item.getProductId()); // 销售订单明细的 productId 是 MDM 物料 ID
        createReqDTO.setProductName(productName); // 产品名称用于错误提示
        createReqDTO.setQuantity(item.getCount());
        createReqDTO.setClientId(saleOrder.getCustomerId());
        createReqDTO.setRequestDate(formatRequestDate(saleOrder.getOrderTime()));
        createReqDTO.setRemark("自动生成,来自销售订单:" + saleOrder.getNo());
 
        Long mpsId = mpsApi.createMps(createReqDTO);
        log.info("[createMpsForSaleOrderItem] MPS 创建成功,mpsId={}, saleOrderItemId={}", mpsId, item.getId());
        return mpsId;
    }
 
    /**
     * 格式化需求日期
     */
    private String formatRequestDate(LocalDateTime dateTime) {
        if (dateTime == null) {
            return null;
        }
        return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
 
}