From 0df438dfa99a51fd29d842c726994bb59b892448 Mon Sep 17 00:00:00 2001 From: "zangch@mesnac.com" Date: Thu, 15 Jan 2026 15:21:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(wms):=20=E6=96=B0=E5=A2=9E=E8=B4=A8?= =?UTF-8?q?=E6=A3=80=E5=8F=91=E8=B5=B7=E6=9C=8D=E5=8A=A1=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=92=8C=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 IWmsInspectionInitiationService 接口定义质检发起相关方法 - 实现批量发起质检任务功能,支持过滤必检且未发起的批次 - 实现单个批次发起质检任务功能,调用 QMS Dubbo 接口创建质检任务 - 添加质检校验逻辑,验证批次是否可以发起质检及获取失败原因 - 实现质检状态更新,成功后将打印记录状态更新为质检中 - 支持动态指定检验类型,默认为原材料检 - 集成分布式事务处理,确保数据一致性 --- .../IWmsInspectionInitiationService.java | 64 ++++++ .../WmsInspectionInitiationServiceImpl.java | 202 ++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionInitiationService.java create mode 100644 ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInspectionInitiationServiceImpl.java diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionInitiationService.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionInitiationService.java new file mode 100644 index 00000000..caea21a1 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionInitiationService.java @@ -0,0 +1,64 @@ +package org.dromara.wms.service; + +import org.dromara.wms.domain.bo.WmsInstockPrintBo; + +import java.util.List; +import java.util.Map; + +/** + * WMS 质检发起服务接口 + *

+ * 专门负责 WMS 向 QMS 发起质检任务的业务逻辑 + * 独立抽离便于维护和调试,可复用现有服务方法 + * + * @author zch + * @date 2026-01-15 + */ +public interface IWmsInspectionInitiationService { + + /** + * 批量发起质检任务 + *

+ * 业务流程: + * 1. 过滤:只处理 inspectionRequest='0'(必检)且 inspectionType='0'(未发起)的批次 + * 2. 调用 QMS Dubbo 接口创建质检任务 + * 3. 更新打印记录状态:inspectionType='1'(质检中) + * 4. 返回每个批次的处理结果 + *

+ * 说明:调用方(Controller)需要添加 @GlobalTransactional 注解 + * + * @param prints 选中的打印记录列表 + * @return Map<批次号, 质检单号或错误信息> + */ + Map createInspection(List prints); + + /** + * 单个批次发起质检任务 + *

+ * 说明:调用方(Controller)需要添加 @GlobalTransactional 注解 + * + * @param print 单个打印记录 + * @return 质检单号 + */ + String createInspectionForSingle(WmsInstockPrintBo print); + + /** + * 校验批次是否可以发起质检 + *

+ * 校验规则: + * 1. inspectionRequest 必须为 '0'(必检) + * 2. inspectionType 必须为 '0' 或 null(未发起) + * + * @param print 打印记录 + * @return true=可以发起,false=不可以发起 + */ + boolean canInitiateInspection(WmsInstockPrintBo print); + + /** + * 获取不能发起质检的原因 + * + * @param print 打印记录 + * @return 错误原因描述,如果可以发起则返回 null + */ + String getCannotInitiateReason(WmsInstockPrintBo print); +} diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInspectionInitiationServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInspectionInitiationServiceImpl.java new file mode 100644 index 00000000..0cb951e6 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInspectionInitiationServiceImpl.java @@ -0,0 +1,202 @@ +package org.dromara.wms.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.dubbo.config.annotation.DubboReference; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.qms.api.RemoteQmsInspectionService; +import org.dromara.qms.api.dto.WmsInspectionTaskRequest; +import org.dromara.wms.domain.bo.WmsInstockPrintBo; +import org.dromara.wms.service.IWmsInspectionInitiationService; +import org.dromara.wms.service.IWmsInstockPrintService; +import org.springframework.stereotype.Service; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * WMS 质检发起服务实现 + *

+ * 负责 WMS 向 QMS 发起质检任务的完整业务流程 + *

+ * 说明:此服务为独立抽离的新文件,不修改现有文件,便于维护和调试 + * + * @author zch + * @date 2026-01-15 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class WmsInspectionInitiationServiceImpl implements IWmsInspectionInitiationService { + + /** + * 引用 QMS Dubbo 服务(创建质检任务) + */ + @DubboReference(timeout = 300000) + private RemoteQmsInspectionService remoteQmsInspectionService; + + /** + * 复用现有的入库打印服务 + */ + private final IWmsInstockPrintService instockPrintService; + + /** + * 批量发起质检任务 + *

+ * 说明:调用方(Controller)需要添加 @GlobalTransactional 注解开启分布式事务 + */ + @Override + public Map createInspection(List prints) { + Map result = new LinkedHashMap<>(); + + for (WmsInstockPrintBo print : prints) { + String batchCode = print.getBatchCode(); + try { + // 1. 校验是否可以发起质检 + String reason = getCannotInitiateReason(print); + if (reason != null) { + result.put(batchCode, "跳过: " + reason); + log.warn("批次 {} 不能发起质检: {}", batchCode, reason); + continue; + } + + // 2. 调用单批次发起方法 + String inspectionNo = createInspectionForSingle(print); + result.put(batchCode, inspectionNo); + + } catch (Exception e) { + log.error("批次 {} 创建质检任务失败: {}", batchCode, e.getMessage(), e); + result.put(batchCode, "失败: " + e.getMessage()); + // 全局事务会自动回滚 + throw new ServiceException("批次 " + batchCode + " 创建质检任务失败: " + e.getMessage()); + } + } + + return result; + } + + /** + * 单个批次发起质检任务 + *

+ * 说明:调用方(Controller)需要添加 @GlobalTransactional 注解开启分布式事务 + */ + @Override + public String createInspectionForSingle(WmsInstockPrintBo print) { + String batchCode = print.getBatchCode(); + String instockCode = print.getInstockCode(); + + // 1. 构建质检任务请求参数 + WmsInspectionTaskRequest request = buildInspectionRequest(print); + + // 2. 调用 QMS Dubbo 接口创建质检任务 + String inspectionNo; + try { + inspectionNo = remoteQmsInspectionService.createInspectionTaskForWMS(request); + } catch (ServiceException e) { + // 直接抛出 ServiceException + throw e; + } catch (RuntimeException e) { + // Dubbo 跨服务调用时,ServiceException 会被包装成 RuntimeException + // 解析原始异常信息并抛出 ServiceException + String message = e.getMessage(); + if (message != null && message.contains("ServiceException")) { + // 提取 ServiceException 中的 message 部分 + int msgStart = message.indexOf("message="); + if (msgStart != -1) { + int msgEnd = message.indexOf(",", msgStart); + if (msgEnd == -1) { + msgEnd = message.indexOf(")", msgStart); + } + if (msgEnd != -1) { + String extractedMsg = message.substring(msgStart + 8, msgEnd); + throw new ServiceException(extractedMsg); + } + } + } + throw new ServiceException("QMS 创建质检任务失败: " + message); + } + + if (StringUtils.isBlank(inspectionNo)) { + throw new ServiceException("QMS 返回质检单号为空"); + } + + log.info("批次 {} 质检任务创建成功,质检单号: {}, 入库单号: {}", batchCode, inspectionNo, instockCode); + + // 3. 更新本地打印记录状态(只有远程调用成功才更新) + WmsInstockPrintBo updateBo = new WmsInstockPrintBo(); + updateBo.setInstockPrintId(print.getInstockPrintId()); + updateBo.setInspectionType("1"); // 质检中 + instockPrintService.updateByBo(updateBo); + + log.info("批次 {} 质检状态已更新为'质检中'", batchCode); + + return inspectionNo; + } + + /** + * 校验批次是否可以发起质检 + */ + @Override + public boolean canInitiateInspection(WmsInstockPrintBo print) { + return getCannotInitiateReason(print) == null; + } + + /** + * 获取不能发起质检的原因 + */ + @Override + public String getCannotInitiateReason(WmsInstockPrintBo print) { + String inspectionRequest = print.getInspectionRequest(); + String inspectionType = print.getInspectionType(); + + // 校验1:是否必检 + if (!"0".equals(inspectionRequest)) { + return "该批次为免检,不需要质检"; + } + + // 校验2:是否已发起 + if (StringUtils.isNotBlank(inspectionType) && !"0".equals(inspectionType)) { + switch (inspectionType) { + case "1": + return "该批次质检中,请勿重复发起"; + case "2": + return "该批次已质检合格"; + case "3": + return "该批次质检不合格"; + default: + return "该批次质检状态异常"; + } + } + + return null; // 可以发起 + } + + /** + * 构建质检任务请求参数 + *

+ * 从 WmsInstockPrintBo 转换为 WmsInspectionTaskRequest + * 支持通过 inspectionTypeParam 动态指定检验类型 + */ + private WmsInspectionTaskRequest buildInspectionRequest(WmsInstockPrintBo print) { + WmsInspectionTaskRequest request = new WmsInspectionTaskRequest(); + request.setInstockCode(print.getInstockCode()); // 入库单号 + request.setMaterialCode(print.getMaterialCode()); // 物料编码 + request.setMaterialName(print.getMaterialName()); // 物料名称 + request.setInspectionQty(print.getApportionQty()); // 质检数量(分包数量) + request.setBatchCode(print.getBatchCode()); // 批次号 + // 检验类型:优先使用前端传入的参数,默认为"4"(原材料检) + //首检=0, 专检=1, 自检=2, 互检=3, 原材料检=4, 抽检=5, 成品检=6, 入库检=7,出库检=8 + String inspectionType = StringUtils.isNotBlank(print.getInspectionTypeParam()) + ? print.getInspectionTypeParam() : "4"; + request.setInspectionType(inspectionType); + // 以下字段可预留扩展 + request.setStationName(null); // 工位名称(WMS入库无需工位) + request.setProcessCode(null); // 工序编码(WMS入库无需工序) + request.setSupplierName(null); // 供应商名称(可从入库单获取) + request.setProductionOrder(null); // 生产订单号(可从入库单获取) + request.setWorkshop(null); // 车间(可从入库单获取) + return request; + } +}