4. 召回批次库存锁定业务逻辑

召回批次库存锁定是召回管理的核心环节,其目标是在WMS系统中将指定批次的库存从“可售/可用”状态转变为“锁定/冻结”状态,防止这些库存被正常订单出库。本章详细阐述锁定策略的三种维度以及锁定状态机的完整设计。

4.1 锁定策略:三种核心维度

在实际业务中,召回操作并非总是针对整个批次。系统需要提供灵活的锁定策略,以应对不同的召回原因和范围。以下是三种最常用的锁定策略:

策略维度 适用场景 锁定粒度 示例
按批次锁定 供应商或质检发现整批次存在系统性缺陷(如原材料问题)。 批次号(Lot No.) 锁定批次号 BATCH-2024-001 下的所有库存。
按生产日期锁定 产品保质期问题或特定时间段内的生产缺陷。 生产日期(Prod Date) 锁定所有生产日期在 2024-01-01 至 2024-01-15 之间的库存。
按供应商锁定 特定供应商提供的原材料或成品出现质量问题。 供应商编码(Supplier Code) 锁定供应商 SUPPLIER-A 提供的所有批次库存。
设计要点: 锁定策略应支持组合使用。例如,可以同时指定“供应商A”且“生产日期在2024-01-01之后”的库存进行锁定。API接口设计时,应将这些策略作为可选参数传入。

4.2 锁定策略执行流程

当接收到锁定请求时,系统会根据指定的策略,在WMS库存表中检索符合条件的库存记录,并执行锁定操作。以下流程图展示了按批次锁定的典型执行路径:

按批次锁定策略执行流程 接收锁定请求 解析锁定策略(批次号) 查询库存表(Lot No.) 库存充足? 执行库存锁定 否 返回锁定失败

4.3 锁定状态机设计

库存锁定不是单一状态,而是一个包含多个阶段的生命周期。设计清晰的状态机,可以确保锁定操作的幂等性、可追溯性和安全性。以下是召回批次库存锁定的核心状态定义:

状态编码 状态名称 状态说明 可触发操作
FREE 自由库存 库存未被锁定,可正常参与出库、移库等作业。 锁定(Lock)
LOCKED 已锁定 库存已被召回指令锁定,不可用于正常出库,但尚未进行物理隔离。 隔离(Isolate)、解锁(Unlock)
ISOLATED 已隔离 库存已从正常存储位移动到隔离区,物理上不可用。 解锁(Unlock)、报废(Scrap)
SCRAPPED 已报废 库存已完成报废处理,从库存账目中移除。 无(终态)
UNLOCKED 已解锁 库存解除锁定,恢复为自由库存状态。 无(终态)

4.4 状态转换图

下图展示了库存锁定状态机的完整转换路径,以及触发状态变更的关键操作:

召回批次库存锁定状态机 FREE LOCKED ISOLATED SCRAPPED UNLOCKED Lock() Isolate() Unlock() Scrap() Unlock()
状态机设计注意事项:
  • 幂等性: 对已处于 LOCKED 状态的库存再次执行 Lock() 操作,应返回成功,但不应产生重复的锁定记录。
  • 逆向操作: Unlock() 操作应允许从 LOCKED 和 ISOLATED 状态直接回到 FREE 状态,但需要记录解锁原因和操作人。
  • 终态不可逆: SCRAPPED 和 UNLOCKED 为终态,不允许再转换到其他状态。

4.5 锁定记录数据结构

为了支持上述策略和状态机,数据库中的锁定记录表应包含以下核心字段:

-- 召回库存锁定记录表 (recall_stock_lock)
CREATE TABLE recall_stock_lock (
    id              BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
    lock_no         VARCHAR(64) NOT NULL COMMENT '锁定单号,全局唯一',
    recall_order_id BIGINT NOT NULL COMMENT '关联的召回单ID',
    sku_code        VARCHAR(64) NOT NULL COMMENT '商品编码',
    lot_no          VARCHAR(64) COMMENT '批次号(按批次锁定)',
    prod_date       DATE COMMENT '生产日期(按生产日期锁定)',
    supplier_code   VARCHAR(64) COMMENT '供应商编码(按供应商锁定)',
    lock_qty        DECIMAL(18,2) NOT NULL COMMENT '锁定数量',
    lock_status     VARCHAR(20) NOT NULL DEFAULT 'LOCKED' COMMENT '锁定状态:FREE/LOCKED/ISOLATED/SCRAPPED/UNLOCKED',
    lock_reason     VARCHAR(255) COMMENT '锁定原因',
    created_by      VARCHAR(64) COMMENT '创建人',
    created_at      DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at      DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    INDEX idx_recall_order (recall_order_id),
    INDEX idx_lot_no (lot_no),
    INDEX idx_lock_status (lock_status)
) COMMENT='召回库存锁定记录表';
关键设计决策: 锁定记录表通过 lot_no、prod_date、supplier_code 三个字段来支持不同的锁定策略。当按批次锁定时,仅填充 lot_no;按生产日期锁定时,填充 prod_date 范围;按供应商锁定时,填充 supplier_code。这种设计避免了为每种策略创建独立的锁定表,简化了查询逻辑。