【单据】入库

来源:https://cloud.iocoder.cn/wms/order/receipt/

入库单是 WMS 接收物料入库的业务凭证,由主表 + 明细子表两张表实现,通过 type 字段区分 4 种入库场景,所有类型共用同一套状态机与库存事务逻辑(详见 《【库存】库存记录、流水、统计》§3 库存事务)。

入库单模块由 yudao-module-wms 后端模块的 order.receipt 包实现,前端实现在 @/views/wms/order/receipt 目录。

1. 入库单

入库单,由 WmsReceiptOrderController 提供接口(/wms/receipt-order);明细子表由 WmsReceiptOrderDetailController 提供接口。

1.1 主表表结构

省略 creator/create_time/updater/update_time/deleted/tenant_id 等通用字段

CREATE TABLE `wms_receipt_order` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `no` varchar(64) NOT NULL COMMENT '入库单号',

  `type` tinyint NOT NULL COMMENT '入库类型',

  `status` tinyint NOT NULL DEFAULT '0' COMMENT '入库状态',

  `merchant_id` bigint DEFAULT NULL COMMENT '供应商编号',

  `order_time` datetime NOT NULL COMMENT '单据日期',
  `biz_order_no` varchar(64) DEFAULT NULL COMMENT '业务单号',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',

  `warehouse_id` bigint NOT NULL COMMENT '仓库编号',

  `total_quantity` decimal(14,3) DEFAULT NULL COMMENT '总数量',
  `total_price` decimal(14,2) DEFAULT NULL COMMENT '总金额',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_no` (`no`)
) ENGINE=InnoDB COMMENT='WMS 入库单';

no 入库单号,新增时由前端默认按 RK + 月日 + 4 位随机数 生成(详见 《功能开启》 ①),允许手动修改,由后端 validateReceiptOrderNoUnique 校验全局唯一。

② 枚举 type 入库类型(WmsReceiptOrderTypeEnum),4 个值共用同一套状态机与库存事务逻辑:

类型 业务场景
100 生产入库 产线产出半成品 / 成品入库
101 采购入库 从供应商采购物料入库(最常见)
102 退货入库 客户退货回到仓库
103 归还入库 借出 / 暂存物料归还入库

③ 枚举 status 入库状态(WmsOrderStatusEnum:0 = 草稿,4 = 已完成,5 = 已作废)。详见 §1.3 状态流转

merchant_id 关联 wms_merchant 表,可空(如生产入库无供应商)。传入时由 WmsMerchantServiceImpl 的 validateSupplierMerchantExists 校验类型必须为供应商或客户/供应商(详见 《【基础】往来企业》§1.3)。

total_quantity / total_price 总数量与总金额,保存时由后端 fillReceiptOrderTotal 按明细自动汇总写入,不需要前端传入。


该表包含一个子表:

1.2 明细子表结构

CREATE TABLE `wms_receipt_order_detail` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',

  `order_id` bigint NOT NULL COMMENT '入库单编号',
  `sku_id` bigint NOT NULL COMMENT '商品 SKU 编号',

  `warehouse_id` bigint NOT NULL COMMENT '仓库编号',

  `quantity` decimal(14,3) NOT NULL COMMENT '入库数量',
  `price` decimal(14,2) DEFAULT NULL COMMENT '单价',
  `total_price` decimal(14,2) DEFAULT NULL COMMENT '行金额',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='WMS 入库单明细';

order_id 关联主表的 id 字段。

sku_id 入库 SKU,新增时由用户从 SKU 选择器选择(详见 《【基础】商品、SKU、分类、品牌》§1.4),保存时由 WmsItemSkuServiceImpl 校验 SKU 存在。

warehouse_id 仓库编号,从主表继承的冗余字段(保存时由 buildReceiptOrderDetailList 直接取主表 warehouseId 写入),便于按仓库聚合明细查询。

quantity 入库数量,必填且 > 0price 单价、total_price 行金额均可空:若前端未传 total_price,由 fillDetailTotalPrice 自动按 price × quantity 计算填回。

1.3 状态流转

入库单生命周期由 WmsReceiptOrderServiceImpl 控制,所有状态迁移使用乐观锁(updateByIdAndStatus(id, expectedStatus, newStatus))防止并发。状态枚举 WmsOrderStatusEnum

状态值 枚举 说明 可执行操作
0 PREPARE 草稿 编辑、完成入库、作废、删除
4 FINISHED 已完成
5 CANCELED 已作废 删除

状态流转说明

创建 ──→ 草稿(0) ──完成入库──→ 已完成(4)(终态,写库存 + 流水)
              │
              └──作废──→ 已作废(5)(终态,不动库存)

1.4 管理后台

对应 [WMS 系统 -> 入库管理] 菜单,对应 yudao-ui-admin-vue3 项目的 @/views/wms/order/receipt 目录。

列表

支持按入库单号、业务单号、单据状态、仓库、供应商、单据日期、入库类型、数量范围、总金额范围、创建 / 更新人、创建 / 更新时间共 11 类条件筛选。列表展示入库单号、入库类型、单据日期、仓库、供应商、总数量、总金额、状态、创建 / 更新人,以及修改 / 删除 / 打印操作(完成入库 / 作废按钮在编辑弹窗底部,详见下方小节)。

仓库下拉用 WarehouseSelect.vue,供应商下拉用 MerchantSelect.vue supplier(限定为供应商或客户/供应商)。

入库单列表

新增

通过弹窗 ReceiptOrderForm.vue 完成。表单上半部分是单据基础信息(入库单号 + 自动生成、入库类型、单据日期、仓库、供应商、业务单号、备注),下半部分是明细子表(SKU 选择器 + 入库数量 + 单价 + 行金额,可增删行)。保存成功后弹窗自动切换为编辑模式(参考 《功能开启》 ②)。

入库单新增

修改

弹窗结构与新增相同,仅在草稿状态下可打开。提交时仅修改主表的明细 diff,主表通过乐观锁防止并发踩到已完成 / 已作废状态(抛 RECEIPT_ORDER_STATUS_NOT_PREPARE)。

完成入库

编辑弹窗底部的「完成入库」按钮触发(仅草稿状态显示)。前端先做脏检查:若表单有改动则先调 updateReceiptOrder 保存,再调 /wms/receipt-order/complete?id=。后端在同一事务内:① CAS 翻状态为已完成;② 调用 changeInventory 写入库存与流水(详见 《【库存】库存记录、流水、统计》§3.1)。完成后单据进入终态,不能再编辑 / 作废。

作废

编辑弹窗底部的「作废」按钮触发(仅草稿状态显示),二次确认后调 /wms/receipt-order/cancel?id=。作废后单据进入终态,但可被删除。

1.5 库存影响

完成入库时调用 inventoryService.changeInventory 写入库存与流水:

库存事务的并发安全(行锁、按需创建库存行)由库存事务统一处理,本篇不重复说明。

2. 网页打印

ReceiptOrderPrint.vue@/views/wms/order/receipt/ReceiptOrderPrint.vue)通过 v-print 指令将单据渲染为可打印 HTML:

通过列表行 "打印" 按钮触发,仅渲染当前单据,不依赖单据状态。

入库单网页打印