【WMS学习笔记系列】03-功能模块设计
功能模块设计3.1 模块总览WMS 功能模块 ├── 基础数据管理 → wms-core ├── 入库管理 → wms-inbound ├── 出库管理 → wms-outbound ├── 库存管理 → wms-inventory ├── 盘点管理 → wms-count └── 报表看板 → wms-report3.2 入库管理流程3.2.1 整体状态机ASN 创建 → 已通知 → 收货中 → 收货完成 → 上架中 → 上架完成 ↓ ↓ 已取消 异常3.2.2 详细流程Step 1: ASN 创建 │ 上游采购系统/ERP推送 ASN 数据 │ 包含ASN 单号、供应商、预计到货时间、商品明细 │ 状态已通知 │ Step 2: 收货 │ 仓库管理员扫描 ASN 单号 │ 逐 SKU 扫描条码 / 输入实收数量 │ 系统校验实收 vs 预计 │ ├── 一致 → 收货完成 │ ├── 少于 → 标记差异部分收货 │ └── 多于 → 标记异常无单收货审批 │ Step 3: 上架 │ 系统根据上架策略推荐库位 │ 管理员扫描库位码确认上架 │ 库存数量 N库位状态更新 │ 状态上架完成3.2.3 上架策略伪代码public ListLocation recommendLocations(Sku sku, int qty) { // 1. 查询该 SKU 已有库存的库位 ListLocation existingLocations inventoryMapper .findLocationsBySkuId(sku.getId()); if (!existingLocations.isEmpty()) { return existingLocations.stream() .filter(loc - loc.getAvailableCapacity() qty) .sorted(Comparator.comparingInt(Location::getAvailableCapacity)) .limit(3) .collect(Collectors.toList()); } // 2. 按 ABC 分类 容量筛选空库位 String abcClass sku.getAbcClass(); // A / B / C return locationMapper.findAvailableByAbcClass(abcClass, qty, 3); }3.3 出库管理流程3.3.1 整体状态机订单接收 → 波次生成 → 分配库存 → 拣货中 → 拣货完成 → 复核中 → 复核完成 → 已发货 ↓ ↓ ↓ ↓ 已取消 缺货异常 缺货标记 差异退回3.3.2 详细流程Step 1: 订单接收 │ OMS 推送出库订单 │ 含订单号、客户、商品明细、期望发货时间、承运商 │ Step 2: 波次生成 │ 根据波次策略将多个订单合并为波次 │ 波次 拣货任务的基本单位 │ Step 3: 库存分配 │ 按 FIFO / 批次优先规则分配库存 │ 锁定库存预占防止被其他订单抢走 │ 生成拣货任务清单 │ Step 4: 拣货 │ 拣货员 PDA 接收任务 │ 系统按库位排序优化拣货路径 │ 扫描库位 → 扫描商品 → 确认数量 │ Step 5: 复核 │ 扫描订单号 → 逐件扫描商品条码 │ 重量校验实际重量 vs 理论重量 │ 差异处理 │ Step 6: 打包发货 │ 打印面单、装箱清单 │ 称重、测量体积 │ 交接承运商 → 扣减库存3.3.3 拣货路径优化仓库库位布局示例数字为库位编号 ┌──────────────────────────────┐ │ 01 02 03 04 │ 21 22 23 │ ← A 区快周转 │ 05 06 07 08 │ 24 25 26 │ │─────────────────────────────│ │ 09 10 11 12 │ 27 28 29 │ ← B 区中周转 │ 13 14 15 16 │ 30 31 32 │ │─────────────────────────────│ │ 17 18 19 20 │ 33 34 35 │ ← C 区慢周转 └──────────────────────────────┘ ↑ 复核区 / 发货区 优化后路径从靠近发货区的库位开始 由近到远排列拣货任务 示例需要拣 03, 18, 25 三个库位 原始顺序03 → 18 → 25 (S型路径效率低) 优化顺序25 → 03 → 18 (由近及远)3.3.4 播种式 vs 摘果式拣货方式描述适用场景摘果式一个拣货员完成一个订单的所有商品订单少、单品多播种式先汇总多个订单的总需求量统一拣货后再按订单分播订单多、SKU 重合度高3.4 库存管理3.4.1 库存维度模型库存 f(仓库, SKU, 库位, 批次, 状态, 货主) 查询示例 查询仓库1中 SKU-1001 在所有库位的可用库存 → SUM(quantity) WHERE warehouse_id1 AND sku_id1001 AND statusAVAILABLE3.4.2 库存状态状态含义是否可分配AVAILABLE可用是LOCKED锁定已被订单预占否FROZEN冻结质检中否DAMAGED残次否EXPIRED过期否3.4.3 库存扣减时序出库订单分配库存的时序防止并发超扣 ┌────────────────┐ │ 开启事务 (BEGIN) │ └───────┬────────┘ ▼ ┌───────────────────────────────────┐ │ SELECT * FROM inventory │ │ WHERE sku_id ? │ │ AND status AVAILABLE │ │ AND quantity 0 │ │ ORDER BY production_date ASC │ ← FIFO: 先过期先出 │ FOR UPDATE │ ← 行锁 └───────┬───────────────────────────┘ ▼ ┌────────────────────────┐ │ 计算扣减量逐行扣减 │ │ 若 quantity need │ │ 扣 need完成 │ │ 若 quantity need │ │ 全扣继续下一行 │ └───────┬────────────────┘ ▼ ┌────────────────────┐ │ 更新库存行 │ │ 插入库存变更流水 │ └───────┬────────────┘ ▼ ┌──────────────────┐ │ 提交事务 (COMMIT) │ └──────────────────┘3.4.4 安全库存预警-- 低库存预警当前可用库存 安全库存阈值 SELECT s.sku_code, s.sku_name, s.safety_stock, COALESCE(SUM(i.quantity), 0) AS current_stock FROM sku s LEFT JOIN inventory i ON s.id i.sku_id AND i.status AVAILABLE GROUP BY s.id HAVING current_stock s.safety_stock;3.5 盘点管理3.5.1 盘点类型类型说明频率动态盘点每日出入库结束后对变动库位复盘每日循环盘点按库区轮转每天盘一个区域按计划全面盘点全仓库所有库位盘点月度/季度随机抽盘随机抽取部分 SKU 或库位盘点按需3.5.2 盘点流程Step 1: 创建盘点计划 │ 选择盘点类型、范围仓库/库区/SKU │ 选择盘点方式明盘显示系统库存/ 盲盘不显示 │ Step 2: 生成盘点任务 │ 按库位/库区拆分任务 │ 分配盘点人员 │ 库位冻结可选盘点期间禁止出入库操作 │ Step 3: 执行盘点 │ 盘点员扫描库位码 │ 逐 SKU 扫描条码录入实际数量 │ 系统对比账面数量 │ Step 4: 差异处理 │ 无差异 → 盘点完成 │ 有差异 → 复盘二次盘点 │ 复盘仍有差异 → 生成差异报告 → 主管审核 │ Step 5: 库存调整 │ 审核通过后调整库存 │ 生成盘盈/盘亏单据 │ 记录操作日志3.5.3 盘点锁定策略盘点锁库策略针对部分盘点 ┌──────────────────────────────────────┐ │ 临时表count_lock │ │ ┌──────────┬──────────┬────────────┐ │ │ │ location │ lock_type │ lock_time │ │ │ ├──────────┼──────────┼────────────┤ │ │ │ A-01-01 │ COUNTING │ 2026-07-30 │ │ │ │ A-01-02 │ COUNTING │ 2026-07-30 │ │ │ └──────────┴──────────┴────────────┘ │ │ │ │ 出入库时检查若库位在 count_lock 中 │ │ 且 lock_typeCOUNTING则拒绝操作 │ └──────────────────────────────────────┘3.6 库位管理3.6.1 库位编码规则推荐编码格式仓库-库区-排-列-层 示例WH01-A-03-05-02 WH01 仓库编号 A 库区A区快周转 / B区中周转 / C区慢周转 03 第 3 排货架 05 第 5 列 02 第 2 层3.6.2 库位属性属性说明库位编码唯一标识库位类型存储位 / 拣货位 / 暂存位 / 退货位 / 残次位容量最大存放数量 / 最大体积 / 最大重量状态空闲 / 占用 / 冻结 / 禁用ABC 分类对应的周转率分类3.7 事件驱动解耦业务模块之间通过 Spring Event / RabbitMQ 解耦入库完成事件 ├── → 库存模块更新库存 ├── → 报表模块更新入库统计 └── → 通知模块发送入库通知 出库完成事件 ├── → 库存模块扣减库存 ├── → 报表模块更新出库统计 └── → OMS回传发货状态 盘点调整事件 ├── → 库存模块调整库存 └── → 审计模块记录调整日志// 事件定义 public class InboundCompletedEvent extends ApplicationEvent { private final Long asnId; private final ListInboundDetail details; // ... } // 事件发布 Transactional public void completeInbound(Long asnId) { // 业务处理... eventPublisher.publishEvent(new InboundCompletedEvent(this, asnId, details)); } // 事件监听 Component public class InventoryEventListener { EventListener Transactional public void handleInboundCompleted(InboundCompletedEvent event) { // 更新库存 } }