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 @@
+ * 专门负责 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
+ * 说明:调用方需要添加 @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
+ * 从 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
+ * 判断依据:质检类型为"入库检"(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
+ * 专门负责接收 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);
}