feat(wms): 添加入库质检集成功能

- 在 IWmsInstockRecordService 中新增 submitInstockWithQualityCheck 方法处理PDA入库质检流程
- 添加 hwmom-api-qms 依赖支持WMS与QMS模块集成
- 新增 IWmsInspectionCallbackService 接口处理QMS质检完成回调逻辑
- 实现 QcWmsCallbackService 和 QcWmsService 接口提供质检任务创建和回调功能
- 添加 RemoteWmsInstockService Dubbo服务接口用于跨模块通信
- 实现完整的入库质检业务流程包括免检物料直接完成和必检物料创建质检任务
master
zangch@mesnac.com 5 days ago
parent 0df438dfa9
commit 61bbadae25

@ -118,6 +118,14 @@
<scope>compile</scope>
</dependency>
<!-- QMS API 模块WMS 集成使用)-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>hwmom-api-qms</artifactId>
<version>2.2.2</version>
<scope>compile</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.microsoft.sqlserver</groupId>-->
<!-- <artifactId>mssql-jdbc</artifactId>-->
@ -150,6 +158,12 @@
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.4</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>hwmom-api-wms</artifactId>
<version>2.2.2</version>
<scope>compile</scope>
</dependency>
</dependencies>

@ -0,0 +1,80 @@
package org.dromara.qms.service;
import org.dromara.qms.domain.vo.QcInspectionMainVo;
/**
* QMS WMS
* <p>
* QMS WMS
* 便
* <p>
* QcPDAServiceImpl
*
* @author zch
* @date 2026-01-15
*/
public interface IQcWmsCallbackService {
/**
* WMS
* <p>
*
* 1.
* 2. InspectionCompleteNotification
* 3. WMS Dubbo
* 4. inspection_type
* <p>
*
* - PDA QcPDAServiceImpl.submitInspection
* - QcUnqualifiedReviewServiceImpl.completeTask
* <p>
* @GlobalTransactional
*
* @param main
* @return true=false=
*/
boolean notifyWmsForQualified(QcInspectionMainVo main);
/**
* WMS
* <p>
*
* 1.
* 2.
* 3. WMS Dubbo "合格"
* 4.
* <p>
*
* - "让步接收"reviewResult='4'
* <p>
* @GlobalTransactional
*
* @param inspectionNo
* @param concessionQty
* @param batchCode
* @return true=false=
*/
boolean notifyWmsForConcession(String inspectionNo, java.math.BigDecimal concessionQty, String batchCode);
/**
*
* <p>
* QcInspectionMainVo InspectionCompleteNotification
*
* @param main
* @param concessionQty null
* @param isConcession
* @return
*/
Object buildNotification(QcInspectionMainVo main, java.math.BigDecimal concessionQty, boolean isConcession);
/**
* WMS
* <p>
* "入库检"typeCode='7'
*
* @param main
* @return true=WMSfalse=
*/
boolean isFromWmsInspection(QcInspectionMainVo main);
}

@ -0,0 +1,34 @@
package org.dromara.qms.service;
import org.dromara.qms.api.dto.WmsInspectionTaskRequest;
/**
* WMSService
* <p>
* WMS
*
* @author zch
* @date 2026-01-14
*/
public interface IQcWmsService {
/**
* WMS
* <p>
*
* 1.
* 2. 8
* 3.
* 4.
* 5.
* 6.
* <p>
*
* - WMS 使 "7"
* - IDIDDubbo
*
* @param request WMS
* @return
*/
String createInspectionTask(WmsInspectionTaskRequest request);
}

@ -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
* <p>
* QMS WMS
* <p>
*
* 1. QcPDAServiceImpl
* 2. qcInspectionMainService
* 3. 便
*
* @author zch
* @date 2026-01-15
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class QcWmsCallbackServiceImpl implements IQcWmsCallbackService {
/**
* WMS Dubbo
* <p>
* WMS RemoteWmsInspectionCallbackServiceImpl
*/
@DubboReference(timeout = 300000)
private RemoteWmsInstockService remoteWmsInstockService;
/**
*
*/
private final IQcInspectionMainService qcInspectionMainService;
/**
*
*/
private final IQcInspectionTypeService qcInspectionTypeService;
/**
* WMS
* <p>
* @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<Void> 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
* <p>
* @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<Void> 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;
}
}
/**
*
* <p>
* 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;
}
/**
*
* <p>
* 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<QcInspectionMainVo> list = qcInspectionMainService.queryList(queryBo);
return (list != null && !list.isEmpty()) ? list.get(0) : null;
}
/**
* WMS
* <p>
* "入库检"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());
}
}

@ -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 入库服务备用实现(已弃用)
// * <p>
// * 说明:实际的 Dubbo 服务由 RemoteWmsInspectionCallbackServiceImpl 提供
// * 此类仅作为历史保留,不再暴露为 Dubbo 服务
// *
// * @author zch
// * @date 2026-1-14
// * @deprecated 请使用 {@link RemoteWmsInspectionCallbackServiceImpl}
// */
// @Slf4j
// @RequiredArgsConstructor
// @Deprecated
// public class RemoteWmsInstockServiceImpl implements RemoteWmsInstockService {
// /**
// * 质检完成通知入库(备用接口,暂不实现)
// * <p>
// * 说明:质检完成回调采用 REST API 方式实现POST /wsmApi/notifyInspectionComplete
// * 此 Dubbo 接口作为备用方案,未来如需服务间直接调用可启用
// * <p>
// * 说明租户ID和用户ID从当前调用上下文自动获取
// *
// * @param notification 质检完成通知参数
// * @return 处理结果
// */
// @Override
// public R<Void> 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 方式回调");
// }
// }

@ -0,0 +1,66 @@
package org.dromara.wms.service;
import org.dromara.qms.api.dto.InspectionCompleteNotification;
import org.dromara.wms.domain.vo.WmsInstockPrintVo;
/**
* WMS
* <p>
* QMS
* 便
*
* @author zch
* @date 2026-01-15
*/
public interface IWmsInspectionCallbackService {
/**
*
* <p>
*
* 1.
* 2. instockCode + batchCode
* 3. inspection_type
* - result="0": inspectionType='2'
* - result="1": inspectionType='3'
* 4.
* PDA inspectionType='2'
* <p>
* QMS @GlobalTransactional
*
* @param notification
* @return true=false=
*/
boolean handleInspectionComplete(InspectionCompleteNotification notification);
/**
*
* <p>
* QMS @GlobalTransactional
*
* @param instockCode
* @param batchCode
* @return true=false=
*/
boolean updateToQualified(String instockCode, String batchCode);
/**
*
* <p>
* 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);
}

@ -73,4 +73,18 @@ public interface IWmsInstockRecordService {
* @return
*/
Boolean completeQualityCheck(String instockCode);
/**
* PDA
* <p>
*
* 1.
* 2. inspectionRequest = "0"
* 3. completeQualityCheck()
* 4. QMS "质检中"
*
* @param instockCode
* @return
*/
Boolean submitInstockWithQualityCheck(String instockCode);
}

Loading…
Cancel
Save