You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

38 KiB

WMS-QMS 质检集成需求与方案文档

文档版本历史

版本 日期 修订内容 作者
1.0 2026-01-15 初始版本,完整需求与方案设计 zch
1.1 2026-01-15 新增独立文件实现,添加代码实现章节 zch
1.2 2026-01-15 修复Code Review问题创建独立 Dubbo 实现类、修复状态映射、添加批次号过滤 zch

目录


1. 需求概述

1.1 背景

WMS仓储管理系统与 QMS质量管理系统需要实现质检业务闭环支持以下场景

  1. WMS 主动发起质检:通过前端界面手动选择批次,调用 QMS 创建质检任务
  2. QMS 质检完成回调:质检完成后通知 WMS更新批次质检状态
  3. PDA 扫码入库根据质检状态PDA 扫码完成实际入库操作
  4. 让步接收闭环:不合格品让步接收后,支持 PDA 扫码入库

1.2 核心需求

需求点 说明 优先级
手动发起质检 打印标签后不自动创建质检任务,通过前端界面手动选择批次发起
质检完成通知 QMS 质检完成后回调 WMS更新批次质检状态
合格数量入库 质检合格的批次PDA 扫码完成入库
让步接收入库 不合格品让步接收后PDA 扫码完成入库
批次追溯 全流程保持批次号一致性,确保可追溯

1.3 核心数据表

  • 质检qms模块通用模块版本只关注qc_inspection_item、qc_inspection_item_category、qc_inspection_main、qc_inspection_main_file_relation、qc_inspection_result、qc_inspection_template、qc_template_item、qc_unqualified_record、qc_unqualified_review
  • hwmom-wms核心关注base_measurement_unit_info、base_supplier_info1、base_material_category、base_material_type、base_material_info_copy1 / base_material_info、wms_base_customer、wms_base_area、wms_base_location、wms_base_warehouse、wms_allocate_order、wms_allocate_order_detail、wms_allocate_task、wms_check_task、wms_purchase_order、wms_purchase_order_detail、wms_instock_detail、wms_instock_order、wms_instock_print、wms_instock_record、wms_inventory、wms_inventory_check、wms_inventory_check_record、wms_outstock_detail、wms_outstock_order、wms_outstock_record

2. 业务流程

2.1 整体业务流程图

┌─────────────────────────────────────────────────────────────────┐
│                   WMS-QMS 质检闭环完整流程                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  【步骤1】打印标签                                               │
│  ├─ 生成 wms_instock_print 记录                                │
│  ├─ inspection_type='0'(未发起)                               │
│  └─ inspection_request='0/1'(必检/免检)                       │
│                                                                  │
│  【步骤2】前端发起质检新功能                                  │
│  ├─ qc.vue 界面选择批次                                         │
│  ├─ 过滤inspection_request='0'且 inspection_type='0'            │
│  ├─ 点击"发起质检"按钮                                           │
│  └─ POST /wms/instockPrint/createInspection                     │
│                                                                  │
│  【步骤3】WMS 调用 QMS 创建质检任务                              │
│  ├─ @GlobalTransactional调用方加注解                         │
│  ├─ remoteQmsInspectionService.createInspectionTaskForWMS()      │
│  └─ 更新打印记录inspection_type='1'(质检中)                   │
│                                                                  │
│  【步骤4】PDA 质检执行                                           │
│  ├─ 质检员填写检测结果                                           │
│  ├─ 保存到 qc_inspection_result                                  │
│  └─ 更新 qc_inspection_mainstatus='1', result='0/1'            │
│     qualifiedQty=?, unqualifiedQty=?                             │
│                                                                  │
│  【步骤5】QMS 回调 WMS质检完成                               │
│  ├─ @GlobalTransactional调用方加注解                         │
│  ├─ remoteWmsInspectionService.notifyInspectionComplete()       │
│  ├─ 传递批次号和合格/不合格数量                                  │
│  └─ 只更新质检状态,❌ 不创建入库记录                            │
│     ├─ 合格inspection_type='2'                                │
│     └─ 不合格inspection_type='3'                               │
│                                                                  │
│  【步骤6】PDA 扫码入库(合格批次)                                │
│  ├─ POST /pda/instock/submit                                     │
│  ├─ 过滤inspection_type='2'(合格)                            │
│  ├─ 创建 wms_instock_record 记录                                 │
│  ├─ 更新库存 wms_inventory                                       │
│  └─ 更新打印记录inbound_status='1'(已入库)                    │
│                                                                  │
│  【步骤7】让步接收待讨论                                      │
│  ├─ 不合格品评审 → 让步接收                                       │
│  ├─ QMS 回调 WMS与步骤5类似                                  │
│  ├─ 更新质检状态inspection_type='2'(合格)                     │
│  └─ PDA 扫码入库与步骤6类似                                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2.2 状态流转说明

inspection_type质检状态字段

说明 触发条件 后续操作
0 未发起 打印标签后默认 前端发起质检
1 质检中 WMS 调用 QMS 创建质检任务后 PDA 质检执行
2 合格 QMS 回调 WMS 更新状态后 PDA 扫码入库
3 不合格 QMS 回调 WMS 更新状态后 不合格品评审

inbound_status入库状态字段

说明 触发条件
0 待入库 打印标签后默认
1 已入库 PDA 扫码入库成功
2 入库中 预留,当前未使用
3 拒收 预留,当前未使用

3. 数据模型

3.1 核心数据表

wms_instock_print入库打印记录表

字段 类型 说明 示例
instock_print_id bigint 主键 123
instock_code varchar(64) 入库单号 RK202501150001
batch_code varchar(64) 批次号 BATCH001
material_code varchar(64) 物料编码 MAT001
material_name varchar(128) 物料名称 橡胶
apportion_qty decimal(16,2) 条码数量(分包数量) 100.00
inspection_request char(1) 质检要求0=必检1=免检) 0
inspection_type char(1) 质检状态0未发起1质检中2合格3不合格 1
inbound_status char(1) 入库状态0待入库1已入库 0
actual_inbound_time datetime 实际入库时间 2026-01-15 10:00:00

wms_instock_record入库记录表

字段 类型 说明 示例
instock_record_id bigint 主键 456
instock_code varchar(64) 入库单号 RK202501150001
batch_code varchar(64) 批次号 BATCH001
material_code varchar(64) 物料编码 MAT001
instock_qty decimal(16,2) 入库数量 100.00
instock_time datetime 入库时间 2026-01-15 10:00:00

wms_inventory库存表

字段 类型 说明
inventory_id bigint 主键
batch_code varchar(64) 批次号
material_id bigint 物料ID
store_id bigint 仓库ID
location_code varchar(64) 库位编码
inventory_qty decimal(16,2) 库存数量
lock_state char(1) 锁定状态0未锁定1锁定
inventory_status char(1) 库存状态0归零1正常

qc_inspection_main质检主表

字段 类型 说明 关联关系
inspection_id bigint 质检主键 -
inspection_no varchar(64) 质检单号 -
template_id bigint 模板ID -
material_code varchar(64) 物料编码 关联 wms_instock_print
inspection_qty decimal(16,2) 质检数量 -
qualified_qty decimal(16,2) 合格数量 -
unqualified_qty decimal(16,2) 不合格数量 -
result char(1) 质检结果0合格1不合格 -
status char(1) 单据状态0未处理1完成 -
batch_no varchar(64) 批次号 关联 wms_instock_print.batch_code
production_order varchar(64) 生产订单号/业务来源单号 可存储入库单号
remark varchar(512) 备注 可存储入库单号

4. 接口设计

4.1 WMS 发起质检接口

接口定义

/**
 * 批量发起质检任务
 * 前端选择批次后调用此接口创建质检任务
 *
 * @param prints 选中的打印记录列表
 * @return Map<批次号, 质检单号或错误信息>
 */
@PostMapping("/createInspection")
public R<Map<String, String>> createInspection(@RequestBody List<WmsInstockPrintBo> prints)

请求参数

[
  {
    "instockPrintId": 123,
    "instockCode": "RK202501150001",
    "batchCode": "BATCH001",
    "materialCode": "MAT001",
    "materialName": "橡胶",
    "apportionQty": 100.00,
    "inspectionRequest": "0"
  },
  {
    "instockPrintId": 124,
    "instockCode": "RK202501150001",
    "batchCode": "BATCH002",
    "materialCode": "MAT001",
    "materialName": "橡胶",
    "apportionQty": 50.00,
    "inspectionRequest": "0"
  }
]

响应结果

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "BATCH001": "QC202501150001",
    "BATCH002": "QC202501150002"
  }
}

4.2 QMS 质检完成回调接口WMS 暴露给 QMS

Dubbo 接口定义

/**
 * WMS 暴露给 QMS 的质检完成回调接口
 * QMS 质检完成后调用此接口通知 WMS
 */
public interface RemoteWmsInspectionService {
    /**
     * 质检完成回调
     * @param notification 质检完成通知
     */
    void notifyInspectionComplete(InspectionCompleteNotification notification);
}

回调参数

public class InspectionCompleteNotification implements Serializable {
    private String inspectionNo;          // 质检单号(必填)
    private String instockCode;           // 入库单号(必填)
    private String batchCode;             // 批次号(必填,精确匹配)
    private String result;                // 质检结果0=合格1=不合格(必填)
    private String status;                // 质检状态0=未处理1=已完成(必填)
    private BigDecimal qualifiedQty;     // 合格数量(必填)
    private BigDecimal unqualifiedQty;   // 不合格数量(必填)
    private String materialCode;          // 物料编码(可选)
    private String inspectionEndTime;   // 质检完成时间(可选)
}

5. 新增文件清单

5.1 设计原则

核心原则独立新建Java文件不修改现有文件便于查看和调试

  1. 模块化设计将WMS-QMS集成相关的业务逻辑抽离到独立的服务类
  2. 复用现有服务:新文件可调用现有服务方法,避免重复代码
  3. 便于维护:独立文件便于定位问题、调试和后续扩展
  4. 职责清晰每个文件职责单一符合SOLID原则

5.2 WMS模块新增文件

文件路径 类型 说明
service/IWmsInspectionInitiationService.java 接口 WMS发起质检服务接口
service/impl/WmsInspectionInitiationServiceImpl.java 实现 WMS发起质检服务实现
service/IWmsInspectionCallbackService.java 接口 WMS接收QMS回调服务接口
service/impl/WmsInspectionCallbackServiceImpl.java 实现 WMS接收QMS回调服务实现本地服务
dubbo/RemoteWmsInspectionCallbackServiceImpl.java 实现 WMS Dubbo服务实现实现RemoteWmsInstockService
controller/api/apiController.java 修改 REST API回调接口添加@Transactional、批次号过滤、状态映射
controller/WmsInstockPrintController.java 修改 添加createInspection端点

5.3 QMS模块新增文件

文件路径 类型 说明
service/IQcWmsCallbackService.java 接口 QMS回调WMS服务接口
service/impl/QcWmsCallbackServiceImpl.java 实现 QMS回调WMS服务实现

5.4 API模块修改文件

文件路径 类型 说明
hwmom-api-qms/src/main/java/org/dromara/qms/api/dto/InspectionCompleteNotification.java 修改 添加batchCode字段

5.5 文件依赖关系图

┌─────────────────────────────────────────────────────────────────┐
│                    新增文件依赖关系                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  【WMS模块】                                                     │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ WmsInstockPrintController                              │   │
│  │   └── @PostMapping("/createInspection")                 │   │
│  │       └── IWmsInspectionInitiationService              │   │
│  └──────────────────────────────────────────────────────────┘   │
│                      ↓                                           │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ WmsInspectionInitiationServiceImpl                      │   │
│  │   ├── @DubboReference RemoteQmsInspectionService        │   │
│  │   └── 复用 IWmsInstockPrintService                     │   │
│  └──────────────────────────────────────────────────────────┘   │
│                      ↓                                           │
│                  【调用QMS Dubbo】                                │
│                                                                  │
│  【QMS模块】                                                     │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ QcPDAServiceImpl (现有文件,复用)                         │   │
│  │   └── submitInspection()                                 │   │
│  │       └── 调用 IQcWmsCallbackService.notifyWmsForQualified│ │  │
│  └──────────────────────────────────────────────────────────┘   │
│                      ↓                                           │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ QcWmsCallbackServiceImpl (新增)                          │   │
│  │   ├── @DubboReference RemoteWmsInspectionService        │   │
│  │   └── 复用 IQcInspectionMainService                    │   │
│  └──────────────────────────────────────────────────────────┘   │
│                      ↓                                           │
│                  【回调WMS Dubbo】                                │
│                                                                  │
│  【WMS模块】                                                     │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ WmsInspectionCallbackServiceImpl (@DubboService)         │   │
│  │   └── handleInspectionComplete()                         │   │
│  │       └── 复用 IWmsInstockPrintService.updateByBo()     │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

5.6 关键代码示例

WMS发起质检服务实现

// WmsInspectionInitiationServiceImpl.java
@Service
public class WmsInspectionInitiationServiceImpl implements IWmsInspectionInitiationService {

    @DubboReference(timeout = 300000)
    private RemoteQmsInspectionService remoteQmsInspectionService;

    private final IWmsInstockPrintService instockPrintService;

    @Override
    public Map<String, String> createInspection(List<WmsInstockPrintBo> prints) {
        Map<String, String> result = new LinkedHashMap<>();
        for (WmsInstockPrintBo print : prints) {
            // 1. 校验是否可以发起质检
            String reason = getCannotInitiateReason(print);
            if (reason != null) {
                result.put(print.getBatchCode(), "跳过: " + reason);
                continue;
            }
            // 2. 调用 QMS Dubbo 接口
            String inspectionNo = remoteQmsInspectionService.createInspectionTaskForWMS(request);
            // 3. 更新本地状态
            updateInspectionType(print.getInstockPrintId(), "1");
            result.put(print.getBatchCode(), inspectionNo);
        }
        return result;
    }
}

QMS回调WMS服务实现

// QcWmsCallbackServiceImpl.java
@Service
public class QcWmsCallbackServiceImpl implements IQcWmsCallbackService {

    @DubboReference(timeout = 300000)
    private RemoteWmsInstockService remoteWmsInstockService;

    private final IQcInspectionMainService qcInspectionMainService;

    @Override
    public boolean notifyWmsForQualified(QcInspectionMainVo main) {
        // 1. 检查是否来自WMS入库
        if (!isFromWmsInspection(main)) {
            return false;
        }
        // 2. 构建通知参数
        InspectionCompleteNotification notification = buildNotification(main, null, false);
        // 3. 调用 WMS Dubbo 接口
        R<Void> result = remoteWmsInstockService.completeInstockAfterInspection(notification);
        return result != null && result.getCode() == R.SUCCESS;
    }
}

WMS接收QMS回调服务实现本地服务

// WmsInspectionCallbackServiceImpl.java
@Service
public class WmsInspectionCallbackServiceImpl implements IWmsInspectionCallbackService {

    private final IWmsInstockPrintService instockPrintService;

    @Override
    public boolean handleInspectionComplete(InspectionCompleteNotification notification) {
        // 1. 精确查询打印记录instockCode + batchCode
        WmsInstockPrintVo printVo = queryByInstockAndBatch(
            notification.getInstockCode(),
            notification.getBatchCode()
        );
        // 2. 根据质检结果更新状态inspectionType: 2=合格, 3=不合格)
        if ("0".equals(notification.getResult())) {
            return updateToQualified(notification.getInstockCode(), notification.getBatchCode());
        } else {
            return updateToUnqualified(notification.getInstockCode(), notification.getBatchCode());
        }
    }
}

WMS Dubbo服务实现独立类

// RemoteWmsInspectionCallbackServiceImpl.java
@Service
@DubboService
public class RemoteWmsInspectionCallbackServiceImpl implements RemoteWmsInstockService {

    private final IWmsInspectionCallbackService wmsInspectionCallbackService;

    @Override
    public R<Void> completeInstockAfterInspection(InspectionCompleteNotification notification) {
        // 委托给本地服务处理
        boolean success = wmsInspectionCallbackService.handleInspectionComplete(notification);
        return success ? R.ok("质检回调处理成功") : R.fail("质检回调处理失败");
    }
}

6. 技术实现方案

6.1 模块依赖关系

┌─────────────────────────────────────────────────────────────────┐
│                      模块依赖关系                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────┐         ┌─────────┐         ┌─────────┐           │
│  │   WMS   │────────>│   QMS   │<────────│   PDA   │           │
│  │ 模块    │  Dubbo  │ 模块    │  Dubbo  │ 扫码入库 │           │
│  └─────────┘         └─────────┘         └─────────┘           │
│       ▲                                            ▲              │
│       │ HTTP                                      │              │
│  ┌────┴────┐                                 ┌────┴────┐          │
│  │前端 qc.vue│                                 │  PDA设备 │          │
│  └─────────┘                                 └─────────┘          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

6.2 技术栈

技术点 使用方式 说明
微服务框架 Spring Cloud Alibaba + Dubbo 3.x 服务间 RPC 调用
分布式事务 Seata @GlobalTransactional 跨服务数据一致性
认证授权 Sa-Token 用户身份验证
多租户 TenantHelper 租户隔离

6.3 核心代码结构

WMS 模块

hwmom/ruoyi-modules/hwmom-wms/
├── controller/
│   └── api/
│       ├── WmsPdaApiController.java         # PDA 入库接口
│       └── WmsInstockPrintController.java   # 打印记录管理接口
├── service/
│   ├── IWmsInstockPrintService.java        # 打印记录服务接口
│   └── impl/
│       └── WmsInstockPrintServiceImpl.java # 打印记录服务实现
└── dubbo/
    └── RemoteQmsInspectionService.java     # QMS Dubbo 接口引用

QMS 模块

hwmom/ruoyi-modules/hwmom-qms/
├── controller/
│   └── QcPDAController.java               # PDA 质检接口
├── service/
│   ├── IQcPDAService.java                  # PDA 质检服务接口
│   ├── IQcWmsService.java                  # WMS 仓储质检服务接口
│   └── impl/
│       ├── QcPDAServiceImpl.java           # PDA 质检服务实现
│       └── QcWmsServiceImpl.java           # WMS 仓储质检服务实现
└── dubbo/
    └── RemoteQmsInspectionServiceImpl.java # QMS Dubbo 服务实现

7. 前端改造

7.1 界面文件

文件路径hwmom-ui/src/views/wms/instockPrint/qc.vue

7.2 新增按钮

<!-- 在工具栏添加"发起质检"按钮 -->
<el-row :gutter="10" class="mb8">
  <el-col :span="1.5">
    <el-button
      type="primary"
      plain
      icon="VideoPlay"
      :disabled="multiple"
      @click="handleCreateInspection"
      v-hasPermi="['wms:instockPrint:createInspection']">
      发起质检
    </el-button>
  </el-col>
</el-row>

7.3 按钮点击处理

/** 发起质检按钮操作 */
const handleCreateInspection = async () => {
  // 1. 过滤:只处理必检(inspectionRequest='0')且未发起(inspectionType='0'或null)的批次
  const validRecords = vos.value.filter(item =>
    item.inspectionRequest === '0' &&
    (!item.inspectionType || item.inspectionType === '0')
  );

  if (validRecords.length === 0) {
    proxy?.$modal.msgWarning("请选择需要发起质检的批次(必检且未发起)");
    return;
  }

  // 2. 确认提示
  await proxy?.$modal.confirm(
    `确认为选中的 ${validRecords.length} 个批次发起质检吗?`
  );

  // 3. 调用接口
  loading.value = true;
  try {
    const res = await createInspection(validRecords);
    proxy?.$modal.msgSuccess("质检任务创建成功");
    await getList();
  } catch (error) {
    console.error("发起质检失败", error);
  } finally {
    loading.value = false;
  }
};

7.4 API 定义

// api/wms/instockPrint/index.ts

/**
 * 批量发起质检任务
 * @param prints 选中的打印记录列表
 */
export const createInspection = (prints: InstockPrintVO[]) => {
  return request({
    url: '/wms/instockPrint/createInspection',
    method: 'post',
    data: prints
  });
};

8. 分布式事务处理

8.1 Dubbo 调用事务规范

重要原则:调用方(发起方)需要添加 @GlobalTransactional 注解

场景1WMS 调用 QMS 创建质检任务

// WMS 模块
@Service
public class WmsInstockPrintServiceImpl {

    @DubboReference
    private RemoteQmsInspectionService remoteQmsInspectionService;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)  // ← 调用方加注解
    public Map<String, String> createInspection(List<WmsInstockPrintBo> prints) {
        Map<String, String> result = new LinkedHashMap<>();

        for (WmsInstockPrintBo print : prints) {
            try {
                // 1. 构建请求参数
                WmsInspectionTaskRequest request = new WmsInspectionTaskRequest();
                request.setInstockCode(print.getInstockCode());
                request.setMaterialCode(print.getMaterialCode());
                request.setInspectionQty(print.getApportionQty());
                request.setBatchCode(print.getBatchCode());
                request.setInspectionType("7"); // 入库检

                // 2. 调用 QMS Dubbo 接口(远程事务)
                String inspectionNo = remoteQmsInspectionService.createInspectionTaskForWMS(request);

                log.info("批次 {} 质检任务创建成功,质检单号: {}", print.getBatchCode(), inspectionNo);

                // 3. 更新本地状态(只有远程调用成功才更新)
                WmsInstockPrintBo updateBo = new WmsInstockPrintBo();
                updateBo.setInstockPrintId(print.getInstockPrintId());
                updateBo.setInspectionType("1"); // 质检中
                instockPrintService.updateByBo(updateBo);

                result.put(print.getBatchCode(), inspectionNo);

            } catch (Exception e) {
                log.error("批次 {} 创建质检任务失败: {}", print.getBatchCode(), e.getMessage(), e);
                result.put(print.getBatchCode(), "失败: " + e.getMessage());
                // 全局事务会自动回滚
                throw new ServiceException("创建质检任务失败: " + e.getMessage());
            }
        }

        return result;
    }
}

场景2QMS 调用 WMS 质检完成回调

// QMS 模块
@Service
public class QcPDAServiceImpl {

    @DubboReference
    private RemoteWmsInspectionService remoteWmsInspectionService;

    /**
     * 质检完成后的回调方法(抽离独立方法)
     */
    private void notifyWmsForQualified(QcInspectionMainVo main) {
        // 如果没有合格数量,不回调
        if (main.getQualifiedQty().compareTo(BigDecimal.ZERO) <= 0) {
            log.info("质检单 {} 无合格数量,跳过回调", main.getInspectionNo());
            return;
        }

        try {
            // 1. 构建回调参数
            InspectionCompleteNotification notification = buildNotification(main);

            // 2. 调用 WMS Dubbo 接口(远程事务)
            remoteWmsInspectionService.notifyInspectionComplete(notification);

            log.info("质检单 {} 回调 WMS 成功", main.getInspectionNo());

        } catch (Exception e) {
            log.error("质检单 {} 回调 WMS 失败: {}", main.getInspectionNo(), e.getMessage(), e);
            // 根据业务需求决定是否抛出异常
            // 如果不影响主流程,可以只记录日志
        }
    }

    /**
     * 构建回调通知参数
     */
    private InspectionCompleteNotification buildNotification(QcInspectionMainVo main) {
        InspectionCompleteNotification notification = new InspectionCompleteNotification();
        notification.setInspectionNo(main.getInspectionNo());
        notification.setInstockCode(main.getRemark()); // remark 字段存储入库单号
        notification.setBatchCode(main.getBatchNo());   // 批次号
        notification.setQualifiedQty(main.getQualifiedQty());
        notification.setUnqualifiedQty(main.getUnqualifiedQty());
        notification.setMaterialCode(main.getMaterialCode());
        notification.setResult("0"); // 合格
        notification.setStatus("1"); // 已完成
        notification.setInspectionEndTime(new Date());
        return notification;
    }
}

7.2 事务回滚场景

场景 回滚范围 说明
QMS 创建质检任务失败 WMS 本地状态不更新 @GlobalTransactional 保证
WMS 接收回调失败 不影响 QMS 主流程 捕获异常,记录日志
网络超时 Seata 自动重试 配置超时时间和重试次数

7.3 Seata 配置

# application.yml
seata:
  enabled: true
  application-id: hwmom-wms
  tx-service-group: default_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: public
      group: SEATA_GROUP
      username: nacos
      password: nacos
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: public
      group: SEATA_GROUP
      username: nacos
      password: nacos

9. 让步接收方案(待讨论)

9.1 业务场景

批次 BATCH001总数100
├─ 质检完成80合格 + 20不合格
│   ├─ 合格80 → QMS 回调 WMS → inspection_type='2'
│   └─ 不合格20 → 创建不合格品评审
│
└─ 不合格品评审 → 让步接收reviewResult='4'
    └─ QMS 回调 WMS → inspection_type='2'(让步接收视为合格)
       └─ PDA 扫码入库 20 件

9.2 技术方案(待讨论)

方案A让步接收时单独回调推荐

// QMS 模块 - 不合格品评审服务
@Service
public class QcUnqualifiedReviewServiceImpl {

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Boolean completeTask(QcUnqualifiedReviewBo bo) {
        QcUnqualifiedReview review = baseMapper.selectById(bo.getReviewId());

        // 1. 完成工作流审批
        // ... 现有逻辑 ...

        // 2. 【新增】让步接收回调 WMS
        if ("4".equals(review.getReviewResult())) {
            notifyWmsForConcession(review);
        }

        return baseMapper.updateById(review) > 0;
    }

    /**
     * 让步接收完成后回调 WMS单独抽离的方法
     * 后续可改为其他实现方式REST API / 消息队列)
     */
    private void notifyWmsForConcession(QcUnqualifiedReview review) {
        // 从质检单号获取质检主表信息
        QcInspectionMainVo inspectionMain = qcInspectionMainService.queryByInspectionNo(review.getInspectionNo());

        // 构建回调参数
        InspectionCompleteNotification notification = new InspectionCompleteNotification();
        notification.setInspectionNo(review.getInspectionNo());
        notification.setInstockCode(inspectionMain.getRemark()); // remark 存储入库单号
        notification.setBatchCode(review.getBatchNo()); // 批次号
        notification.setQualifiedQty(review.getInspectionQty()); // 让步接收数量
        notification.setUnqualifiedQty(BigDecimal.ZERO);
        notification.setResult("0"); // 让步接收视为合格
        notification.setStatus("1"); // 已完成

        // 调用 WMS Dubbo 接口
        remoteWmsInspectionService.notifyInspectionComplete(notification);

        log.info("让步接收回调 WMS 成功,批次号: {}, 数量: {}", review.getBatchNo(), review.getInspectionQty());
    }
}

方案B与合格数量回调合并

将让步接收也调用 notifyWmsForQualified() 方法,统一处理。

9.3 数据一致性保证

场景 合格数量 让步接收数量 累计入库 最终状态
场景1 80 20 100 已入库
场景2 100 0 100 已入库
场景3 0 100 100 已入库

10. 附录

10.1 字典值定义

wms_inspection_type质检状态

字典值 字典标签 说明
0 未发起 打印后默认状态
1 质检中 已创建质检任务,等待执行
2 合格 质检合格
3 不合格 质检不合格

inspection_request质检要求

字典值 字典标签 说明
0 必检 需要质检
1 免检 不需要质检

wms_inbound_status入库状态

字典值 字典标签 说明
0 待入库 初始状态
1 已入库 PDA 扫码入库成功
2 入库中 预留,当前未使用
3 拒收 预留,当前未使用

10.2 关键文件路径清单

模块 文件路径 说明
WMS hwmom/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/controller/api/WmsInstockPrintController.java 打印记录控制器
WMS hwmom/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/IWmsInstockPrintService.java 打印记录服务接口
WMS hwmom/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/service/impl/WmsInstockPrintServiceImpl.java 打印记录服务实现
WMS hwmom/ruoyi-modules/hwmom-wms/src/main/java/org/dromara/wms/dubbo/RemoteWmsInspectionService.java WMS 暴露给 QMS 的接口(新增)
QMS hwmom/ruoyi-api/hwmom-api-qms/src/main/java/org/dromara/qms/api/RemoteQmsInspectionService.java QMS Dubbo 接口定义
QMS hwmom/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/dubbo/RemoteQmsInspectionServiceImpl.java QMS Dubbo 服务实现
QMS hwmom/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcWmsService.java WMS 仓储质检服务接口
QMS hwmom/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcWmsServiceImpl.java WMS 仓储质检服务实现
QMS hwmom/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcPDAServiceImpl.java PDA 质检服务实现
API hwmom/ruoyi-api/hwmom-api-qms/src/main/java/org/dromara/qms/api/dto/InspectionCompleteNotification.java 质检完成通知 DTO
API hwmom/ruoyi-api/hwmom-api-qms/src/main/java/org/dromara/qms/api/dto/WmsInspectionTaskRequest.java WMS 入库质检请求 DTO
前端 hwmom-ui/src/views/wms/instockPrint/qc.vue 质检入库任务界面
前端 hwmom-ui/src/api/wms/instockPrint/index.ts 打印记录前端 API

11. 待确认事项

  1. 批次号传递方式 ✓ 已确认:必须传递 batchCode
  2. 入库时机 ✓ 已确认:由 PDA 扫码入库,回调只更新状态
  3. 分布式事务 ✓ 已确认:调用方加 @GlobalTransactional
  4. 让步接收具体实现方式(待讨论)
  5. 是否需要新增 WMS 暴露给 QMS 的 Dubbo 接口(待确认)

文档结束