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 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")); } }