WMS仓储系统(五)—— 入库流程面试题精讲(项目实战篇)

接上一篇:WMS仓储系统(四)—— 库存模块面试题与项目亮点(面试必看) :我们系统总结了库存模块的简历亮点与高频面试题。本文基于项目真实源码,深入拆解入库流程的完整实现,包含到货通知、质检、待上架、上架、库存更新、事务控制等核心环节,并整理15道高频面试题与标准答案。


快速回顾

文章 核心内容
第一篇 WMS整体业务流程、技术栈、项目定位
第二篇 20+张核心业务表设计、库存模型、核心业务SQL
第三篇 高并发库存扣减、三种锁方案、面试并发难题解决
第四篇 库存模块面试题与项目亮点总结
第五篇(本文) 入库流程源码级面试题精讲

一、入库流程整体回顾

基于项目源码,入库流程是WMS最核心的基础流程,支撑采购入库、退货入库、调拨入库等场景,整体分为四大核心阶段,全程事务可控、支持分批作业、状态全自动流转:

  1. 创建入库单:生成 WmsOrderHeader(入库单头)和 WmsOrderLine(入库单明细),初始化待质检状态;

  2. 质检与收货:调用 qualityInspec 方法完成货物验收,生成待上架任务记录 WmsAuditIn

  3. 上架入库:调用 onShelf 方法执行库位上架,新增/更新即时库存,生成上架流水;

  4. 状态闭环:根据收货、上架完成情况,自动更新单据行、单据头的完整业务状态。


二、入库流程核心面试题(15道完整版)

Q1:请结合项目源码,描述WMS中完整的入库业务流程。

参考答案:

基于项目源码,完整入库流程由三个核心Service方法串联实现,全程基于Spring事务保障数据一致性,无数据脏读、数据错乱问题。

① 创建入库单(WmsOrderHeaderServiceImpl.saveWmsOrderHeader)

// 生成唯一入库单号:类型编码 + 年月日 + 当日自增序号
wmsOrderHeader.setOrderNum(orderTypeCode + yyyyMMdd + "-" + String.format("%04d", count + 1));
// 初始化单据状态:待质检
wmsOrderHeader.setOrderStatus(CommonWms.WAIT_FOR_CHECK);
// 保存入库单头 & 批量保存入库明细行

② 质检收货、生成待上架数据(WmsOrderLineServiceImpl.qualityInspec)

// 1. 前置校验:防止重复收货、超量收货
// 2. 生成待上架任务记录
auditIn.setAuditCount(验收数量);
auditIn.setShelfSyCount(验收数量); // 初始化剩余上架数量
auditIn.setShelfStatus(CommonWms.WAIT_FOR_SHELF);
wmsAuditInMapper.insert(auditIn);
// 3. 更新订单行已收数量、剩余数量
// 4. 驱动单据状态流转

③ 库位上架、更新库存(WmsAuditInServiceImpl.onShelf)

@Transactional(rollbackFor = Exception.class)
public void onShelf(WmsAuditIn wmsAuditInvo) {
    // 1. 校验上架记录合法性、上架数量不超限
    // 2. 更新待上架表:累加已上架、扣减剩余上架数量
    // 3. 插入已上架流水记录 WmsStockIn
    // 4. 悲观锁更新/新增即时库存
    updateInventoryWithLock(auditIn, wmsAuditInvo, ciAuditCount);
    // 5. 最终更新单据完成状态
}

Q2:入库单号如何生成?为什么要这样设计?

参考答案:

源码生成规则

wmsOrderHeader.setOrderNum(
    orderTypeCode + DateUtils.date2Str(new SimpleDateFormat("yyyyMMdd")) 
    + "-" + String.format("%04d", count + 1)
);
// 示例:RK20240515-0001(RK代表入库单)

设计优势

  1. 高可读性:通过单号可直接识别单据类型、业务日期、流水序号;

  2. 方便检索:支持按日期、单据类型快速筛选数据;

  3. 全局唯一:同日期同类型自增序号,彻底避免单号重复;

  4. 易于扩展:自带日期维度,后续可无缝实现按月分表、数据归档。

Q3:质检环节如何防止重复收货、超量收货?源码如何实现?

参考答案:

项目通过双重字段校验杜绝重复收货和超收问题:

// 1. 整单收完拦截,禁止重复收货
if (wmsOrderLinevo.getGoodsCount().equals(wmsOrderLine.getGoodsDjCount())) {
    throw new JeecgBootException("物料已收完,不允许再次收货");
}

// 2. 校验本次验收数量不能大于剩余可收数量
if (Convert.toInt(NumberUtil.sub(goodsYsCount, wmsOrderLinevo.getGoodsSyCount())) > 0) {
    throw new JeecgBootException("验收数量不能大于剩余数量");
}

核心设计:通过 goodsDjCount(已收数量)、goodsSyCount(剩余待收数量)双字段动态校验,每一次收货都做幂等校验,保证数据严谨。

Q4:待上架表为什么同时设计已上架、剩余上架两个数量字段?

参考答案:

核心目的是支持分批上架,适配仓库真实作业场景:

  1. shelfDjCount(已上架数量):记录累计上架总量,用于数据追溯、对账统计、进度展示;

  2. shelfSyCount(剩余上架数量):记录未完成上架数量,用于判断是否存在待作业任务、控制单据状态流转。

核心更新逻辑

String newShelfDjCount = NumberUtil.add(ciAuditCount, auditIn.getShelfDjCount());
String newShelfSyCount = NumberUtil.sub(auditIn.getAuditCount(), newShelfDjCount);

当剩余上架数量为0时,系统自动将单据状态更新为「已上架完成」。

Q5:上架环节如何保证库存数据一致性?结合源码说明

参考答案:

项目通过事务+悲观锁双重机制保障库存强一致性:

  1. 核心上架方法添加 @Transactional 全局事务,待上架更新、上架流水新增、库存变更、单据状态更新,多表操作原子执行,异常自动回滚;

  2. 库存查询使用 selectForUpdate 行级悲观锁,锁定库存维度数据,杜绝并发上架导致的数据覆盖、库存错乱;

  3. 库存更新后校验SQL影响行数,更新失败主动抛异常回滚。

Q6:上架时库存存在则更新、不存在则新增,源码如何实现?有什么优化方案?

参考答案:

原生实现逻辑:先锁查询、再判断新增或更新

// 悲观锁锁定当前维度库存
WmsInventory inventory = wmsInventoryMapper.selectForUpdate(...);
if (inventory != null) {
    // 库存存在:数量累加更新
    inventory.setBaseCount(NumberUtil.add(inventory.getBaseCount(), ciAuditCount));
    wmsInventoryMapper.updateById(inventory);
} else {
    // 库存不存在:新建库存记录
    wmsInventoryMapper.insert(newInventory);
}

优化方案:使用 ON DUPLICATE KEY UPDATE 语法,单SQL实现存在更新、不存在新增,减少一次数据库查询,提升并发性能。

Q7:入库单完整状态有哪些?业务状态如何流转?

参考答案:

状态常量 状态含义 触发时机
WAIT_FOR_CHECK 待质检 入库单创建完成
BEGIN_FOR_CHECK 质检中 任意明细行开始收货质检
END_FOR_CHECK 质检完成 所有明细行收货完毕
WAIT_FOR_SHELF 待上架 生成待上架任务
BEGIN_FOR_SHELF 上架中 开始执行库位上架
END_FOR_SHELF 已完成 所有货物上架完毕

Q8:如何防止上架数量超过剩余待上架数量?

参考答案:

采用业务层校验 + 数据库层兜底双重防护:

1. 业务层前置拦截

private void validateShelfQuantity(WmsAuditIn auditIn, String ciAuditCount) {
    if (Convert.toInt(NumberUtil.sub(ciAuditCount, auditIn.getShelfSyCount())) > 0) {
        throw new JeecgBootException("上架数量不能大于上架剩余数量");
    }
}

2. 数据库更新兜底

UPDATE wms_audit_in 
SET shelf_sy_count = shelf_sy_count - #{qty}, shelf_dj_count = shelf_dj_count + #{qty}
WHERE id = #{id} AND shelf_sy_count >= #{qty}

Q9:如何设计入库API对接上游ERP系统?

参考答案:

系统设计标准化RESTful接口,实现与ERP无缝对接,支持ASN预入库、状态回调、单据查询:

接口地址 请求方式 接口说明
/api/inbound/order/create POST ERP推送预入库单(ASN)
/api/inbound/order/cancel POST 取消未完成入库单
/api/inbound/order/query GET 查询入库单状态
/api/inbound/receive/confirm POST 收货结果回调
/api/inbound/shelf/confirm POST 上架完成回调
核心设计:支持单号幂等、批量操作、全链路日志、双向回调通知。

Q10:上架遇到库位不足、物料错放如何处理?

参考答案:

1. 库位容量不足

系统校验库位最大存放容量,超限直接拦截;支持手动更换库位、系统智能推荐空闲库位。

2. 物料错放调整

封装库存转移方法,支持库位、箱码、托盘码变更,全程留痕追溯:

@Transactional
public void transferInventory(String inventoryId, String newKwCode, String newBinCode, String newTrayCode) {
    WmsInventory inventory = wmsInventoryMapper.selectForUpdateById(inventoryId);
    saveChangeLog(inventory, newKwCode, newBinCode, newTrayCode);
    inventory.setKwCode(newKwCode);
    inventory.setBinCode(newBinCode);
    inventory.setTrayCode(newTrayCode);
    wmsInventoryMapper.updateById(inventory);
}

Q11:入库流程如何自动生成物料批次、生产日期与有效期?

参考答案:

系统支持三种批次生成策略,适配不同业务场景:

  1. 手动录入:质检环节人工维护生产日期、有效期、批次号;

  2. 扫码解析:PDA扫码自动解析物料条码中的批次、生产日期信息;

  3. 系统默认生成:无数据时,取当前日期为生产日期,根据物料保质期自动推算有效期。

核心存储字段:

goods_pro_date VARCHAR(32) COMMENT '生产日期',
goods_batch VARCHAR(32) COMMENT '批次号'

Q12:如何处理无条码、箱码破损的物料入库场景?

参考答案:

系统做了柔性兼容设计,避免无条码物料无法入库:

  1. 支持手动输入箱码、托盘码,人工补录标签信息;

  2. 支持系统生成临时条码(TEMP+时间戳),后续可补打替换;

  3. 箱码、托盘码字段允许为空,不阻塞正常入库流程。

Q13:质检不良品如何走退货流程?数据如何保证一致?

参考答案:

  1. 质检不合格物料标记 qc_mark=BAD,单独上架至不良品专属库区;

  2. 新建退货出库单,关联原入库单号,实现业务溯源;

  3. 从不良品库区下架扣减库存,生成退货流水记录;

  4. 退货全程开启事务,保证库存扣减、单据更新、流水记录原子性,数据可回滚。

Q14:如何通过锁机制防止入库单并发重复操作?

参考答案:

项目采用多层锁机制保障并发安全:

  1. 库存更新使用数据库悲观锁,锁定库存维度行数据;

  2. 待上架表引入乐观锁version,防止重复上架、重复更新;

  3. 分布式场景使用Redis分布式锁,锁定单号维度,防止多端并发操作。

UPDATE wms_audit_in 
SET shelf_dj_count = shelf_dj_count + #{qty}, version = version + 1
WHERE id = #{id} AND version = #{oldVersion}

Q15:评价当前入库源码优缺点,并给出优化方案

参考答案:

✅ 优点

  1. 流程完整闭环:覆盖建单、质检、待上架、上架、库存更新全链路;

  2. 事务机制完善,杜绝多表数据不一致;

  3. 原生支持分批收货、分批上架,适配真实仓储作业;

  4. 状态机流转清晰,业务可追溯、可排查。

❌ 现存不足

  1. 待上架更新缺少数量条件兜底,极端场景存在超上架风险;

  2. 悲观锁未做超时、死锁规避策略;

  3. 缺少通用库存流水表,变更追溯能力弱;

  4. 核心业务方法臃肿,硬编码过多,可维护性差。

💡 优化方案

// 1. 增加数量条件兜底更新
int updated = wmsAuditInMapper.update(null,
    Wrappers.<WmsAuditIn>lambdaUpdate()
        .setSql("shelf_dj_count = shelf_dj_count + " + qty)
        .setSql("shelf_sy_count = shelf_sy_count - " + qty)
        .eq(WmsAuditIn::getId, id)
        .ge(WmsAuditIn::getShelfSyCount, qty));

// 2. 新增库存流水记录,全程追溯
insertInventoryLog(inventoryId, "上架", beforeQty, afterQty, auditIn.getOrderNum());

// 3. 大方法拆分:校验、库存更新、日志记录解耦


三、入库流程核心表结构回顾

表名 核心作用 关键字段
wms_order_header 入库单头信息 order_num、order_status
wms_order_line 入库单明细 goods_count、goods_dj_count、goods_sy_count、line_status
wms_audit_in 待上架任务表 audit_count、shelf_dj_count、shelf_sy_count、shelf_status
wms_stock_in 上架流水表 shelf_dj_count、audit_id、rel_order_num
wms_inventory 即时库存表 base_count、goods_batch、goods_pro_date、kw_code、qc_mark

四、快速上手与项目地址

3分钟快速启动项目

# 克隆开源项目代码
git clone https://gitee.com/jeeslee/wms.git

  1. 执行数据库脚本:docs/sql/wms.sql

  2. 修改 application.yml 数据库、Redis连接配置

  3. 启动项目

mvn spring-boot:run

开源项目地址

⭐ 后端WMS源码:https://gitee.com/jeeslee/wms

⭐ 前端Vue3源码:https://gitee.com/li_tongs/jeecgboot-vue3


📚 上一篇WMS仓储系统(四)—— 库存模块面试题与项目亮点(面试必看)

📚 下一篇预告:WMS仓储系统(六)—— 出库流程面试题精讲(项目实战篇)

本文基于真实开源项目源码,全覆盖讲解入库流程业务、源码逻辑、面试高频考点,适合简历优化、面试突击、项目复盘。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐