liyong
5 天以前 be5783c8a7e13bbc76d33c95643d75779cce21db
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/listener/ErpSaleOrderStatusListener.java
@@ -1,31 +1,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.api.event.BpmProcessInstanceStatusEventListener;
import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOrderService;
import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOrderServiceImpl;
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
public class ErpSaleOrderStatusListener extends BpmProcessInstanceStatusEventListener {
@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 ErpSaleOrderService saleOrderService;
    private ErpSaleOrderMapper saleOrderMapper;
    @Resource
    private ErpSaleOrderItemMapper saleOrderItemMapper;
    @Resource
    private MesProMpsApi mpsApi;
    @Resource
    private MdmItemApi mdmItemApi;
    @Override
    public String getProcessDefinitionKey() {
        return ErpSaleOrderServiceImpl.BPM_PROCESS_DEFINITION_KEY;
    protected String getProcessDefinitionKey() {
        return PROCESS_DEFINITION_KEY;
    }
    @Override
    protected void onEvent(BpmProcessInstanceStatusEvent event) {
        saleOrderService.updateSaleOrderAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
        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"));
    }
}