多规格商品设计
冷链商品完整逻辑关系文档
四层核心模型:SPU(商城展示) → SKU(交易货品) → Batch(库存批次) → Inventory(库位数量形态)
业务样例:SPU=泰国黑虎虾;基础库存单位:袋;包装换算:1箱=10袋
全局约束
product_sku_spec联合主键:sku_id + spec_key_id,一个SKU同一个规格维度仅允许1个值spec_signature后端生成:按spec_key_id ASC拼接keyId:valueId;;唯一索引spu_id + spec_signature,防重复SKU- 销售规格spec体系 和 包装单位
sku_pack_rule严格隔离,箱/袋属于包装规则,不进spec规格维度
① product_spu 商品主体|商城展示层
聚合SKU公共属性;前端商品详情页渲染;SPU不能直接采购、下单
| id | spu_code | category_id | brand_id | name | subtitle | origin_country | origin_region | storage_type | status |
|---|---|---|---|---|---|---|---|---|---|
| 1001 | SPU‑HX‑001 | 50 | 12 | 泰国黑虎虾 | 冷冻进口海产大虾 | 泰国 | 曼谷 | 冷冻 | 1 |
② product_spec_key 规格维度|SPU下定义有哪些规格
外键:spu_id → product_spu.id
| id | spu_id | spec_name | sort | status |
|---|---|---|---|---|
| 1 | 1001 | 净含量 | 1 | 1 |
| 2 | 1001 | 虾规格 | 2 | 1 |
③ product_spec_value 规格值|每个维度下可选选项
外键:spec_key_id → product_spec_key.id
| id | spec_key_id | spec_value | sort | status |
|---|---|---|---|---|
| 11 | 1 | 1kg | 1 | 1 |
| 12 | 1 | 2kg | 2 | 1 |
| 21 | 2 | 20/30 | 1 | 1 |
| 22 | 2 | 30/40 | 2 | 1 |
维度‑值汇总
| spec_key_id | 维度名称 | 规格值ID | 规格值文本 |
|---|---|---|---|
| 1 | 净含量 | 11 | 1kg |
| 1 | 净含量 | 12 | 2kg |
| 2 | 虾规格 | 21 | 20/30 |
| 2 | 虾规格 | 22 | 30/40 |
运营维护维度选项;系统笛卡尔积批量生成SKU;供给前端渲染规格选择器
④ product_sku SKU主表|交易核心
外键:spu_id → product_spu.id
spec_signature后端内部字段,不展示,用于防重;每条SKU = 独立货品;库存/采购/成本隔离;base_unit_code=bag底层单位为袋
| id | spu_id | sku_code | barcode | sku_name | net_weight | base_unit_code | sale_price | status |
|---|---|---|---|---|---|---|---|---|
| 2001 | 1001 | SKU‑HX‑001 | 690001 | 泰国黑虎虾 1kg 20/30 | 1000 | bag | 89.00 | 1 |
| 2002 | 1001 | SKU‑HX‑002 | 690002 | 泰国黑虎虾 1kg 30/40 | 1000 | bag | 79.00 | 1 |
| 2003 | 1001 | SKU‑HX‑003 | 690003 | 泰国黑虎虾 2kg 20/30 | 2000 | bag | 165.00 | 1 |
| 2004 | 1001 | SKU‑HX‑004 | 690004 | 泰国黑虎虾 2kg 30/40 | 2000 | bag | 145.00 | 1 |
spec_signature:
- 2001:
1:11;2:21 - 2002:
1:11;2:22 - 2003:
1:12;2:21 - 2004:
1:12;2:22
⑤ product_sku_spec SKU‑规格中间表
外键:sku_id / spec_key_id / spec_value_id;联合主键 sku_id + spec_key_id
spec_key_name、spec_value_name为JOIN读出,本表只存ID做数据库约束
| sku_id | spec_key_id | spec_value_id | spec_key_name(联读) | spec_value_name(联读) |
|---|---|---|---|---|
| 2001 | 1 | 11 | 净含量 | 1kg |
| 2001 | 2 | 21 | 虾规格 | 20/30 |
| 2002 | 1 | 11 | 净含量 | 1kg |
| 2002 | 2 | 22 | 虾规格 | 30/40 |
| 2003 | 1 | 12 | 净含量 | 2kg |
| 2003 | 2 | 21 | 虾规格 | 20/30 |
| 2004 | 1 | 12 | 净含量 | 2kg |
| 2004 | 2 | 22 | 虾规格 | 30/40 |
SKU‑签名‑规格核对表
| sku_id | spec_signature | 维度ID:维度名 | 值ID:值文本 | 完整规格 |
|---|---|---|---|---|
| 2001 | 1:11;2:21 | 1:净含量、2:虾规格 | 11:1kg、21:20/30 | 净含量1kg,虾规格20/30 |
| 2002 | 1:11;2:22 | 1:净含量、2:虾规格 | 11:1kg、22:30/40 | 净含量1kg,虾规格30/40 |
| 2003 | 1:12;2:21 | 1:净含量、2:虾规格 | 12:2kg、21:20/30 | 净含量2kg,虾规格20/30 |
| 2004 | 1:12;2:22 | 1:净含量、2:虾规格 | 12:2kg、22:30/40 | 净含量2kg,虾规格30/40 |
⑥ sku_pack_rule SKU包装规则|与销售规格分离
外键:sku_id;base_qty等于多少个基础库存单位(袋);示例 sku_id=2001,每个SKU独立配置
| id | sku_id | unit_code | unit_name | base_qty | is_base_unit | is_sale_unit | is_purchase_unit | status |
|---|---|---|---|---|---|---|---|---|
| 3001 | 2001 | bag | 袋 | 1 | 1 | 1 | 1 | 1 |
| 3002 | 2001 | box | 箱 | 10 | 0 | 1 | 1 | 1 |
业务含义
- 袋:基础库存单位;可采购、可销售;1袋 = 1底层库存
- 箱:业务包装;可采购、可销售;1箱 = 10袋底层库存
用户下单/采购选箱,系统内部换算为基础单位袋操作库存;箱袋不属于spec规格
⑦ sku_batch 库存批次|冷链真相源
外键:sku_id;库存底层单位:袋;出库FIFO
| id | sku_id | batch_no | produce_date | expire_date | available_stock | warehouse_id |
|---|---|---|---|---|---|---|
| 4001 | 2001 | B20260905001 | 2026‑09‑05 | 2027‑09‑05 | 99 | W01冷冻库 |
| 4002 | 2001 | B20260906001 | 2026‑09‑06 | 2027‑09‑06 | 3 | W01冷冻库 |
sku2001总库存 = sum(available_stock)=102袋;采购入库生成批次;出库优先消耗旧批次
ER文字关系图
product_spu[id=1001 泰国黑虎虾]
│
├─ product_spec_key[id=1净含量,id=2虾规格] spu_id=1001
│ │
│ └─ product_spec_value[id11/12/21/22] spec_key_id关联key表
│ │
│ └─ product_sku_spec(中间关联表 sku_id+spec_key_id+spec_value_id)
│
└─ product_sku[id2001‑2004 4个独立货品SKU] spu_id=1001
│
├─ product_sku_spec(回连规格ID)
├─ sku_pack_rule(袋/箱包装换算规则,每个SKU独立)
│
└─ sku_batch(多批次冷链库存,绑定sku_id;库存以基础单位袋计数)外键对照表
| 字段 | 所在表 | 关联目标表.主键 | 示例值 |
|---|---|---|---|
| spu_id | product_spec_key / product_sku | product_spu.id | 1001 |
| spec_key_id | product_spec_value / product_sku_spec | product_spec_key.id | 1、2 |
| spec_value_id | product_sku_spec | product_spec_value.id | 11、12、21、22 |
| sku_id | product_sku_spec / sku_pack_rule / sku_batch | product_sku.id | 2001‑2004 |
核心业务流程
流程1:新建商品(运营)
- 创建
product_spu公共商品信息 - 录入
product_spec_key规格维度、product_spec_value规格选项 - 系统笛卡尔积生成
product_sku,自动生成spec_signature防重,批量写入product_sku_spec - 每个SKU配置
sku_pack_rule包装单位
SPU不改动;新增规格选项自动生成新SKU
流程2:采购入库
- 采购明细绑定
sku_id,业务可选采购单位箱/袋 - 通过
sku_pack_rule.base_qty换算底层基础单位(袋) - 入库新增
sku_batch批次,写入生产日期、效期、可用库存
❗采购不操作spec表;重量、数量读取SKU物理字段,不解析规格字符串
流程3:用户下单销售
- SPU页面通过spec渲染规格选择器,选中得到sku_id
- 用户选择销售单位(箱/袋)换算底层基础单位
- FIFO顺序扣减
sku_batch批次库存
流程4:约束校验
- 相同规格组合SKU:
spu_id + spec_signature唯一索引拦截 product_sku_spec联合主键:防止同一个SKU同一个规格维度绑定多个值
关键边界区分
- SPU:商城聚合展示,不是货品;SKU:真实交易货品,不同规格=不同SKU,库存成本隔离
- spec体系:只用于前端展示、批量生成SKU;不参与库存、采购计算
- 箱/袋包装放在
sku_pack_rule;禁止放入spec规格维度 - 冷链库存真相源是
sku_batch;SKU总库存为批次sum;批次管控效期、生产日期