diff --git a/ruoyi-modules/hwmom-qms/pom.xml b/ruoyi-modules/hwmom-qms/pom.xml index 3c4c5024..bf5e1abe 100644 --- a/ruoyi-modules/hwmom-qms/pom.xml +++ b/ruoyi-modules/hwmom-qms/pom.xml @@ -118,6 +118,14 @@ compile + + + org.dromara + hwmom-api-qms + 2.2.2 + compile + + @@ -150,6 +158,12 @@ transmittable-thread-local 2.14.4 + + org.dromara + hwmom-api-wms + 2.2.2 + compile + diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsCallbackService.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsCallbackService.java new file mode 100644 index 00000000..55b93acd --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsCallbackService.java @@ -0,0 +1,80 @@ +package org.dromara.qms.service; + +import org.dromara.qms.domain.vo.QcInspectionMainVo; + +/** + * QMS 回调 WMS 服务接口 + *

+ * 专门负责 QMS 质检完成后回调 WMS 的业务逻辑 + * 独立抽离便于维护和调试,可复用现有服务方法 + *

+ * 说明:此接口为独立抽离的新文件,不修改现有文件(如 QcPDAServiceImpl) + * + * @author zch + * @date 2026-01-15 + */ +public interface IQcWmsCallbackService { + + /** + * 质检完成时回调 WMS(合格场景) + *

+ * 业务流程: + * 1. 检查是否有合格数量 + * 2. 构建 InspectionCompleteNotification 通知参数 + * 3. 调用 WMS Dubbo 接口更新质检状态 + * 4. 只更新 inspection_type 状态,不创建入库记录 + *

+ * 调用时机: + * - PDA 提交质检结果后(QcPDAServiceImpl.submitInspection) + * - 让步接收评审完成后(QcUnqualifiedReviewServiceImpl.completeTask) + *

+ * 说明:调用方需要添加 @GlobalTransactional 注解 + * + * @param main 质检主表信息 + * @return true=回调成功,false=回调失败 + */ + boolean notifyWmsForQualified(QcInspectionMainVo main); + + /** + * 让步接收完成时回调 WMS + *

+ * 业务流程: + * 1. 从质检单号获取质检主表信息 + * 2. 构建通知参数(让步接收数量作为合格数量) + * 3. 调用 WMS Dubbo 接口更新质检状态为"合格" + * 4. 保持批次号一致,支持累计入库 + *

+ * 调用时机: + * - 不合格品评审完成,评审结果为"让步接收"(reviewResult='4') + *

+ * 说明:调用方需要添加 @GlobalTransactional 注解 + * + * @param inspectionNo 质检单号 + * @param concessionQty 让步接收数量 + * @param batchCode 批次号 + * @return true=回调成功,false=回调失败 + */ + boolean notifyWmsForConcession(String inspectionNo, java.math.BigDecimal concessionQty, String batchCode); + + /** + * 构建质检完成通知参数 + *

+ * 从 QcInspectionMainVo 转换为 InspectionCompleteNotification + * + * @param main 质检主表信息 + * @param concessionQty 让步接收数量(可选,null表示正常质检合格) + * @param isConcession 是否为让步接收 + * @return 质检完成通知参数 + */ + Object buildNotification(QcInspectionMainVo main, java.math.BigDecimal concessionQty, boolean isConcession); + + /** + * 检查质检主表是否来自 WMS 入库 + *

+ * 判断依据:质检类型为"入库检"(typeCode='7') + * + * @param main 质检主表信息 + * @return true=来自WMS入库,false=不是 + */ + boolean isFromWmsInspection(QcInspectionMainVo main); +} diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsService.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsService.java new file mode 100644 index 00000000..4b12c535 --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsService.java @@ -0,0 +1,34 @@ +package org.dromara.qms.service; + +import org.dromara.qms.api.dto.WmsInspectionTaskRequest; + +/** + * WMS仓储质检Service接口 + *

+ * 为 WMS 入库提供质检任务创建和管理功能 + * + * @author zch + * @date 2026-01-14 + */ +public interface IQcWmsService { + + /** + * 为 WMS 入库单创建质检任务 + *

+ * 业务流程: + * 1. 参数校验(入库单号、物料编码、质检数量、检验类型必填) + * 2. 匹配质检模板(8级降级匹配策略) + * 3. 生成质检单号(调用编码规则服务) + * 4. 构建并保存质检主表 + * 5. 根据模板生成质检结果子表 + * 6. 返回质检单号 + *

+ * 说明: + * - WMS 入库固定使用检验类型 "7"(入库检) + * - 租户ID和用户ID由调用方(Dubbo上下文)传递 + * + * @param request WMS 入库质检请求参数 + * @return 质检单号 + */ + String createInspectionTask(WmsInspectionTaskRequest request); +} diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcWmsCallbackServiceImpl.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcWmsCallbackServiceImpl.java new file mode 100644 index 00000000..44de2151 --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcWmsCallbackServiceImpl.java @@ -0,0 +1,230 @@ +package org.dromara.qms.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.dubbo.config.annotation.DubboReference; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.qms.api.dto.InspectionCompleteNotification; +import org.dromara.qms.domain.bo.QcInspectionMainBo; +import org.dromara.qms.domain.vo.QcInspectionMainVo; +import org.dromara.qms.domain.vo.QcInspectionTypeVo; +import org.dromara.qms.service.IQcInspectionMainService; +import org.dromara.qms.service.IQcInspectionTypeService; +import org.dromara.qms.service.IQcWmsCallbackService; +import org.dromara.wms.api.RemoteWmsInstockService; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * QMS 回调 WMS 服务实现 + *

+ * 负责 QMS 质检完成后回调 WMS 更新状态的完整业务流程 + *

+ * 说明: + * 1. 此服务为独立抽离的新文件,不修改现有文件(如 QcPDAServiceImpl) + * 2. 可复用现有服务方法(如 qcInspectionMainService) + * 3. 便于维护和调试,支持后续扩展其他回调方式 + * + * @author zch + * @date 2026-01-15 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class QcWmsCallbackServiceImpl implements IQcWmsCallbackService { + + /** + * WMS 暴露的 Dubbo 回调服务 + *

+ * 说明:WMS 模块的 RemoteWmsInspectionCallbackServiceImpl 实现此接口 + */ + @DubboReference(timeout = 300000) + private RemoteWmsInstockService remoteWmsInstockService; + + /** + * 复用现有的质检主表服务 + */ + private final IQcInspectionMainService qcInspectionMainService; + + /** + * 复用现有的质检类型服务(用于判断是否为入库检) + */ + private final IQcInspectionTypeService qcInspectionTypeService; + + /** + * 质检完成时回调 WMS(合格场景) + *

+ * 说明:调用方需要添加 @GlobalTransactional 注解开启分布式事务 + */ + @Override + public boolean notifyWmsForQualified(QcInspectionMainVo main) { + // 1. 检查是否来自 WMS 入库 + if (!isFromWmsInspection(main)) { + log.info("质检单 {} 不是来自 WMS 入库,跳过回调", main.getInspectionNo()); + return false; + } + + // 2. 检查是否有合格数量 + if (main.getQualifiedQty() == null || main.getQualifiedQty().compareTo(BigDecimal.ZERO) <= 0) { + log.info("质检单 {} 无合格数量,跳过回调", main.getInspectionNo()); + return false; + } + + try { + // 3. 构建通知参数 + InspectionCompleteNotification notification = (InspectionCompleteNotification) buildNotification( + main, null, false + ); + + // 4. 调用 WMS Dubbo 接口 + R result = remoteWmsInstockService.completeInstockAfterInspection(notification); + if (result == null || result.getCode() != R.SUCCESS) { + log.error("质检单 {} 回调 WMS 失败: {}", main.getInspectionNo(), result != null ? result.getMsg() : "null"); + return false; + } + + log.info("质检单 {} 回调 WMS 成功,合格数量: {}", main.getInspectionNo(), main.getQualifiedQty()); + return true; + + } catch (Exception e) { + log.error("质检单 {} 回调 WMS 失败: {}", main.getInspectionNo(), e.getMessage(), e); + // 根据业务需求决定是否抛出异常 + // 如果不影响主流程,可以只记录日志 + return false; + } + } + + /** + * 让步接收完成时回调 WMS + *

+ * 说明:调用方需要添加 @GlobalTransactional 注解开启分布式事务 + */ + @Override + public boolean notifyWmsForConcession(String inspectionNo, BigDecimal concessionQty, String batchCode) { + try { + // 1. 获取质检主表信息 + QcInspectionMainVo main = queryByInspectionNo(inspectionNo); + if (main == null) { + log.error("质检单不存在: {}", inspectionNo); + return false; + } + + // 2. 检查是否来自 WMS 入库 + if (!isFromWmsInspection(main)) { + log.info("质检单 {} 不是来自 WMS 入库,跳过回调", inspectionNo); + return false; + } + + // 3. 构建通知参数(让步接收视为合格) + InspectionCompleteNotification notification = (InspectionCompleteNotification) buildNotification( + main, concessionQty, true + ); + + // 4. 调用 WMS Dubbo 接口 + R result = remoteWmsInstockService.completeInstockAfterInspection(notification); + if (result == null || result.getCode() != R.SUCCESS) { + log.error("让步接收回调 WMS 失败: {}", result != null ? result.getMsg() : "null"); + return false; + } + + log.info("让步接收回调 WMS 成功,质检单号: {}, 批次号: {}, 数量: {}", + inspectionNo, batchCode, concessionQty); + return true; + + } catch (Exception e) { + log.error("让步接收回调 WMS 失败: {}", e.getMessage(), e); + return false; + } + } + + /** + * 构建质检完成通知参数 + *

+ * 从 QcInspectionMainVo 转换为 InspectionCompleteNotification + */ + @Override + public Object buildNotification(QcInspectionMainVo main, BigDecimal concessionQty, boolean isConcession) { + InspectionCompleteNotification notification = new InspectionCompleteNotification(); + + // 基本信息 + notification.setInspectionNo(main.getInspectionNo()); + notification.setMaterialCode(main.getMaterialCode()); + + // 获取入库单号(优先从 remark 字段获取) + String instockCode = main.getRemark(); + if (StringUtils.isBlank(instockCode)) { + log.warn("质检单 {} 的 remark 字段为空,无法获取入库单号", main.getInspectionNo()); + } + notification.setInstockCode(instockCode); + + // 批次号(保持一致性) + notification.setBatchCode(main.getBatchNo()); + + // 质检结果 + if (isConcession) { + // 让步接收视为合格 + notification.setResult("0"); // 合格 + notification.setQualifiedQty(concessionQty); + notification.setUnqualifiedQty(BigDecimal.ZERO); + } else { + // 正常质检结果 + notification.setResult(main.getResult()); // 0=合格, 1=不合格 + notification.setQualifiedQty(main.getQualifiedQty()); + notification.setUnqualifiedQty(main.getUnqualifiedQty()); + } + + // 质检状态 + notification.setStatus("1"); // 已完成 + + // 质检完成时间(使用标准日期格式) + notification.setInspectionEndTime(main.getInspectionEndTime() != null + ? DateUtils.formatDateTime(main.getInspectionEndTime()) + : DateUtils.getTime()); + + return notification; + } + + /** + * 根据质检单号查询质检主表信息 + *

+ * 说明:通过 queryList 方法实现,因为 IQcInspectionMainService 没有 queryByInspectionNo 方法 + * + * @param inspectionNo 质检单号 + * @return 质检主表信息,不存在则返回 null + */ + private QcInspectionMainVo queryByInspectionNo(String inspectionNo) { + if (StringUtils.isBlank(inspectionNo)) { + return null; + } + QcInspectionMainBo queryBo = new QcInspectionMainBo(); + queryBo.setInspectionNo(inspectionNo); + List list = qcInspectionMainService.queryList(queryBo); + return (list != null && !list.isEmpty()) ? list.get(0) : null; + } + + /** + * 检查质检主表是否来自 WMS 入库 + *

+ * 判断依据:质检类型为"入库检"(typeCode='7') + */ + @Override + public boolean isFromWmsInspection(QcInspectionMainVo main) { + if (main == null || main.getInspectionType() == null) { + return false; + } + + // 查询质检类型信息 + QcInspectionTypeVo typeVo = qcInspectionTypeService.queryById(main.getInspectionType()); + if (typeVo == null) { + return false; + } + + // 判断是否为入库检(typeCode='7') + return "7".equals(typeVo.getTypeCode()); + } +} diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteWmsInstockServiceImpl.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteWmsInstockServiceImpl.java new file mode 100644 index 00000000..d449c9f3 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteWmsInstockServiceImpl.java @@ -0,0 +1,50 @@ +// package org.dromara.wms.dubbo; + +// import lombok.RequiredArgsConstructor; +// import lombok.extern.slf4j.Slf4j; +// import org.dromara.common.core.domain.R; +// import org.dromara.qms.api.dto.InspectionCompleteNotification; +// import org.dromara.wms.api.RemoteWmsInstockService; + +// /** +// * WMS 入库服务备用实现(已弃用) +// *

+// * 说明:实际的 Dubbo 服务由 RemoteWmsInspectionCallbackServiceImpl 提供 +// * 此类仅作为历史保留,不再暴露为 Dubbo 服务 +// * +// * @author zch +// * @date 2026-1-14 +// * @deprecated 请使用 {@link RemoteWmsInspectionCallbackServiceImpl} +// */ +// @Slf4j +// @RequiredArgsConstructor +// @Deprecated +// public class RemoteWmsInstockServiceImpl implements RemoteWmsInstockService { + +// /** +// * 质检完成通知入库(备用接口,暂不实现) +// *

+// * 说明:质检完成回调采用 REST API 方式实现(POST /wsmApi/notifyInspectionComplete) +// * 此 Dubbo 接口作为备用方案,未来如需服务间直接调用可启用 +// *

+// * 说明:租户ID和用户ID从当前调用上下文自动获取 +// * +// * @param notification 质检完成通知参数 +// * @return 处理结果 +// */ +// @Override +// public R completeInstockAfterInspection(InspectionCompleteNotification notification) { +// log.info("收到质检完成通知(Dubbo方式),质检单号: {}, 入库单号: {}, 质检结果: {}", +// notification.getInspectionNo(), notification.getInstockCode(), notification.getResult()); +// log.warn("当前采用 REST API 方式回调,此 Dubbo 接口暂不实现"); + +// // TODO: 未来如需启用此接口,实现以下逻辑 +// // 1. 根据入库单号查询入库记录 +// // 2. 根据质检结果决定是否完成入库 +// // 3. 合格:完成入库,更新库存 +// // 4. 不合格:标记拒收,生成不合格品记录 + +// return R.ok("此接口暂未启用,请使用 REST API 方式回调"); +// } + +// } diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionCallbackService.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionCallbackService.java new file mode 100644 index 00000000..29cb4bf2 --- /dev/null +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInspectionCallbackService.java @@ -0,0 +1,66 @@ +package org.dromara.wms.service; + +import org.dromara.qms.api.dto.InspectionCompleteNotification; +import org.dromara.wms.domain.vo.WmsInstockPrintVo; + +/** + * WMS 质检回调服务接口 + *

+ * 专门负责接收 QMS 质检完成通知的业务逻辑 + * 独立抽离便于维护和调试,可复用现有服务方法 + * + * @author zch + * @date 2026-01-15 + */ +public interface IWmsInspectionCallbackService { + + /** + * 处理质检完成通知 + *

+ * 业务流程: + * 1. 参数校验(质检状态必须为已完成) + * 2. 根据 instockCode + batchCode 精确匹配入库打印记录 + * 3. 根据质检结果更新 inspection_type 状态 + * - 合格(result="0"): inspectionType='2' + * - 不合格(result="1"): inspectionType='3' + * 4. 注意:此方法只更新质检状态,不创建入库记录 + * 入库记录由 PDA 扫码时创建(只处理 inspectionType='2' 的批次) + *

+ * 说明:调用方(QMS)需要添加 @GlobalTransactional 注解 + * + * @param notification 质检完成通知 + * @return true=处理成功,false=处理失败 + */ + boolean handleInspectionComplete(InspectionCompleteNotification notification); + + /** + * 更新批次质检状态为合格 + *

+ * 说明:调用方(QMS)需要添加 @GlobalTransactional 注解 + * + * @param instockCode 入库单号 + * @param batchCode 批次号 + * @return true=更新成功,false=更新失败 + */ + boolean updateToQualified(String instockCode, String batchCode); + + /** + * 更新批次质检状态为不合格 + *

+ * 说明:调用方(QMS)需要添加 @GlobalTransactional 注解 + * + * @param instockCode 入库单号 + * @param batchCode 批次号 + * @return true=更新成功,false=更新失败 + */ + boolean updateToUnqualified(String instockCode, String batchCode); + + /** + * 根据入库单号和批次号精确查询打印记录 + * + * @param instockCode 入库单号 + * @param batchCode 批次号 + * @return 打印记录,如果不存在返回 null + */ + WmsInstockPrintVo queryByInstockAndBatch(String instockCode, String batchCode); +} diff --git a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInstockRecordService.java b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInstockRecordService.java index 7af9b5c9..3d67eb68 100644 --- a/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInstockRecordService.java +++ b/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInstockRecordService.java @@ -73,4 +73,18 @@ public interface IWmsInstockRecordService { * @return 是否成功 */ Boolean completeQualityCheck(String instockCode); + + /** + * PDA 入库提交(带质检判断) + *

+ * 业务流程: + * 1. 查询入库打印记录 + * 2. 判断是否需要质检(是否有物料 inspectionRequest = "0") + * 3. 如果全部是免检物料,直接调用 completeQualityCheck() 完成入库 + * 4. 如果有必检物料,调用 QMS 创建质检任务,更新打印记录状态为"质检中" + * + * @param instockCode 入库单号 + * @return 是否处理成功 + */ + Boolean submitInstockWithQualityCheck(String instockCode); }