1. 业务的起点为什么“多规格、多单位”会让SCM团队头大我这些年做供应链系统项目被业务方问得最多的一句是“不就是加两个字段的事吗规格、单位各存一列不就行了”说这话的人往往没意识到多规格商品、多单位商品背后牵动的是一整套主数据建模、库存口径、采购销售流程和报表体系。如果只在商品表上加两个字段后面等着你的全是脏数据、错库存和扯皮。先给没接触过这块的朋友解释一下这两个概念到底在说什么。多规格商品指的是同一个商品因为属性不同被拆成多个可单独管理的SKU。典型例子是服装一件T恤颜色有黑、白、灰尺码有S、M、L、XL那么它至少有16个SKU。这些SKU共享同一个商品编码SPU但在库存、采购、销售环节必须分开管理因为客户要的是一件“白色的M码”不是随便一件T恤。多单位商品指的是同一个SKU在采购、销售、库存、财务环节使用不同的计量单位。最经典的例子是瓶装饮料采购时按“箱”跟供应商下单销售终端按“瓶”卖出仓储里可能还要按“托盘”管理库位大客户订单又可能按“车”来发货。如果系统里只有“瓶”这一个单位那么采购下单时“下单1000箱”就得换算成“24000瓶”一旦换算系数录错后面全是窟窿。这两个问题单独看都不难难的是它们会组合出现。一台冰箱有“双门/对开门”的规格差异又有“台/件/车”的单位差异一卷工业膜有“宽幅/厚度”的规格差异又有“米/公斤/卷”的单位差异。规格决定SKU的颗粒度单位决定交易的口径二者叠加之后主数据设计、库存计算、单据流转的复杂度是乘法关系不是加法关系。这篇内容适合正在做SCM、ERP、WMS的产品经理、实施顾问和后端开发看也适合企业里管供应链的运营同学——你不需要亲手写代码但至少要知道系统该怎么设计才能兜住你的业务。下面我按从设计到落地的完整链路把这块掰开揉碎讲清楚。2. 主数据建模先定SKU的颗粒度再定单位的体系2.1 SKU颗粒度规格属性表比枚举字段更抗造很多系统在商品表里直接塞一堆枚举字段什么“颜色”“尺码”“容量”“功率”各来一列然后靠唯一索引去重。这种设计的毛病在于不同品类的规格维度不一样。食品要管“口味/净含量”五金要管“材质/规格尺寸”数码要管“颜色/内存/版本”。如果每种品类都靠加字段解决商品表最终会变成一张满是空列的宽表新品类上线还得改表结构。更稳的做法是拆出“商品表 规格属性表 SKU表”三层结构。商品表SPU负责存这个商品的基础信息品类、品牌、默认单位、采购单位、销售单位、是否启用多规格、成本核算方式等。规格属性表Specification负责定义“这个SPU下有哪些规格维度”。比如服装品类的维度是颜色和尺码那规格属性表里就存两条记录维度代码color、维度代码size。SKU表负责把规格的具体取值组合起来。每一行代表一个可下单、可入库、可发货的独立单品存SKU编码、名称、条码、规格值JSON、关联SPU编码、启用状态。这套结构的好处有两个。第一新品类要加规格维度时不需要动表结构往规格属性表和SKU表里加数据就行。第二将来做商品搜索、库存同步、WMS对接时SKU是唯一的业务主键所有单据只要落到SKU维度就不会串。需要注意一个细节SKU编码一旦生成并用于历史单据就不要允许修改。很多项目在初期没定好编码规则上线半年后才发现SKU编码跟条码对不上改编码又要反写几百张历史单据最后只能留着脏数据。规矩要提前立好编码生成走统一规则禁止人工编辑除非走专门的变更流程。2.2 单位体系基本单位是锚点其他单位都靠换算设计多单位体系时最重要的一条原则是每个SKU必须指定一个“基本单位”其他所有单位都通过换算系数关联到基本单位上。基本单位的选择要按业务实际来定一般选库存盘点时最容易数清楚的单位。饮料用瓶、钢材用公斤、电线用米、整机用品台。单位体系在数据库里的落地方式是“单位表 换算表”。单位表里维护全局的单位字典比如瓶、箱、托盘、件、公斤、吨、米。换算表里维护某个SKU下的单位换算关系字段大致是SKU编码、源单位、目标单位、换算系数、换算方式、精度规则。换算方式这里要特别说明它有三种类型固定换算1箱等于24瓶系数恒为24适用于瓶装饮料、整箱包装这类场景。浮动换算系数不固定比如一卷膜按“米”卖但按“公斤”过秤每公斤对应的米数会随厚度变化又比如按“张”采购的钢板每张的重量取决于规格。这类场景下系统每次单据换算时要按实时参数计算不能只存一个固定系数。不换算两个单位虽然属于同一个SKU但业务上各自独立使用只在报表层做参考不允许单据层直接折算。比如“桶”和“桶”之间就没必要憋着换算。单位换算关系还必须支持“多级换算”。一瓶饮料先从瓶到箱×24再从箱到托盘×36那瓶到托盘就是864。系统里最好把换算路径做成图或链而不是只存瓶到托盘一个系数。否则将来新增一个“板”的中转单位所有涉及换算的地方都要跟着改。顺便提一个经常被踩的坑换算系数一定要限定有效时间。供应商下个季度可能把箱规从24瓶改成12瓶如果你在换算表里直接改系数历史单据的成本核算和库存结存就全部对不上了。正确做法是给换算记录留“生效日期”新单据自动用新系数历史单据还按入库时的系数来算。3. 采购、销售、仓储、生产四个环节的单位口径怎么统一3.1 采购环节“下单一个单位入库另一个单位”是常态采购流程里最典型的多单位场景是采购下单按箱收货入库按瓶。供应商送货单上写的是“100箱”但仓库实际操作时会拆箱清点发现其中3箱缺了2瓶实际合格入库是2394瓶。如果采购订单和入库单各用各的单位不打通关系那系统里就会出现“订单数量100箱、入库数量2394瓶”这种没法对数的局面。时间一长采购、财务、仓库三边数据各说各话对账就会出现大量差异。落地时比较顺的流程是采购订单按采购单位下单同时由系统根据换算系数自动算出基本单位的数量并挂在订单行上到货入库时仓库录入的入库数量以基本单位为准系统反向换算回采购单位在入库单上同时展示“入库2394瓶折合99.75箱”。这样双方都有参照差异一眼就能看出来采购员也不用拿着计算器跟仓库吵。这里还要注意采购价与单位的关系。供应商报价是按箱报的但财务核算成本是按瓶算的。订单行上必须同时保存“含税单价采购单位”和“成本单价基本单位”并且由系统自动按换算系数推算避免手工录入导致的单价错位。如果采购价本身也区分规格而定比如不同尺码的T恤进价不同那价格还要挂到SKU维度不能挂到SPU维度。3.2 销售环节客户要的是“规格单位”的组合销售订单的复杂度在于客户下单描述往往是口语化的比如“来两箱白色M码的T恤外加48瓶那个饮料”。系统内部必须把这句话拆解成两条SKU维度的明细而且要能处理“整箱销售零散销售”并存的情况。一种常见的不合理设计是单品档案里有“箱规”字段销售开单时锁死只能按箱卖。这会导致那些“只要半箱”的客户没法下单逼着业务人员去线下拆箱再手工补单。更合理的方案是销售单位作为单据默认值但允许人工切换。客户要整箱就按箱开单要零散就按瓶开单系统同时按基本单位折算库存。销售环节还有一个多规格相关的陷阱叫“组合购”。比如卖礼品装商品本身是“1瓶洗发水1瓶护发素”的组合但如果把它做成一个独立SKU库存管理就会失控——仓库里明明是单独的洗发水和护发素系统里却看到一个“组合装”的库存数永远对不上。正确的做法是组合装是一个虚拟SKU通过BOM物料清单关联两个实体SKU销售订单下单时系统自动扣减两个子件的库存或者用“组合拆解”功能把虚拟库存同步成实体库存。这块后面讲BOM时会细说。3.3 仓储环节库存只认基本单位库位可以灵活很多企业一开始图省事库存表里直接存“箱”和“瓶”两个字段。这样做短期看起来直观长期就是灾难盘点多出来0.5箱怎么记算库存成本时到底按哪个单位分仓调拨、批次效期、库位管理全都绕不开单位每张表都得加两列越滚越乱。我的建议是全系统的库存事务统一落到基本单位的数量上。库存表、库存流水表、盘点表、调拨单、组装单所有数量字段统一用基本单位单位名称固定不变。其他单位只作为单据的展示单位和换算参考不做库存存储。这样做的好处是口径统一任何报表拉出来都是同一个数不需要反复换算。库位管理上多单位的影响主要在拣货和补货策略。整托盘商品存储在货架高层整箱商品存储在中层零散商品在拣货位。WMS里可以通过“单位层级”来约束商品放在哪个库位类型入库时按整托盘存放出库时按箱或按瓶拣货。如果系统不支持库位类型与单位的关联那仓储员只能靠记忆和经验找货效率大打折扣。盘点环节尤其要小心。盘点单录入时不同库位的盘点单位不同高层托盘区按“托”点中层整箱区按“箱”点拣货位按“件”点。系统必须支持“按库位记录各自的盘点单位”然后自动换算成基本单位参与盈亏计算。如果建筑了“所有库位统一按基本单位盘点”现场人员就得先把托盘拆成箱、箱拆成件再数盘点时间直接翻倍。3.4 生产与组装环节BOM的规格、单位和损耗率多规格多单位在生产和组装环节主要体现在BOM设计上。前面说的礼品装组合就是一个最简单的BOM。更复杂的场景是自制半成品比如“一箱精选苹果礼盒”需要“按规格分拣出的优质苹果×12个包装箱×1个”。苹果可能按“公斤”入库但BOM里的用量按“个”设定那就需要知道“每个苹果的重量参数”或“每公斤大约几个”这种换算关系。BOM表设计时要注意几个字段一定要带上**母件单位与子件单位各自独立。**每个子件的用量按该子件自己的单位填写不允许统一强制成母件单位否则生产领料时还得再换算一道。**损耗率。**生产过程中必然有破损、割错、试制损失BOM里的子件用量要是没考虑损耗系统按BOM算出的领料需求就会偏少车间只能不断手工补领。**版本管理。**产品配料调整是常事BOM必须带版本号和生效日期。新版本BOM发布后未开工的生产订单还在用旧版本这种场景系统必须兼容不能一把梭全部切到新版。生产完工入库时产成品还需要按规格、单位分别入到对应仓库。一块钢板从“吨”投料到“张”入库如果投料单上的单位和完工单上的单位对不上生产成本归集就会差一大截。最好是投料、完工、在制三张单据都同时保留“工艺单位基本单位”两个数量每月结账时拿基本单位做成本还原。4. 实操落地细节从字段设计到初始化顺序4.1 换算精度、四舍五入和尾差处理多单位系统上线后财务经常揪着一个小数点问题不放一张销售单开“5箱24瓶装饮料”折合基本单位是120瓶但对家客户开“99.5箱”折合是2388瓶怎么系统里算出来的库存结存会有0.01瓶的尾差问题出在精度和四舍五入的策略不统一。系统里有三个地方会做舍入单据换算、库存加减、报表汇总。如果单据换算按四舍五入保留2位库存流水按实际精度保存报表汇总又做一次四舍五入误差就会在多次换算中逐渐积累。解决的思路是“两头准、中间稳”换算系数尽量精确比如1箱24瓶这种整数最理想遇到浮动换算参数至少要保留4位小数。所有库存流水不截断小数按计算后的真实值保存。库存结存可以是2399.9996瓶但绝不允许程序把它四舍五入成2400。单据层面的换算结果可以四舍五入但前一步必须用未舍入的数据参与计算。销售开单时“5箱”换算成“119.9999瓶”是可以的但落库数量要用这个未舍入值只有显示层才显示120瓶。这个策略能兜住大多数场景。如果业务要求“换算后数量必须取整”比如一箱24瓶不允许拆出半瓶卖给客户那就要在单据上增加“取整规则”字段并在整单保存前做一次校验发现拆分后不足整瓶的明细直接拒绝开单。这种校验规则的配置位置最好放在单位换算表里而不是写死在代码里否则每家企业都要单独改一套逻辑。4.2 条码、批次效期与多单位的联动多规格多单位的商品条码管理是个说不完的话题。一个SKU可能同时有“箱条码”和“瓶条码”箱条码和瓶条码是一对多的关系。如果仓库入库时扫了瓶条码出库时扫了箱条码系统必须能识别同一商品的两个条码指向同一个SKU并且自动完成单位换算。我见过最离谱的案例是商品条码表里只有一列条码字段把箱条码和瓶条码混在一起存结果扫描枪一识别就乱套。正确的设计是条码表至少包含四列条码值、条码类型单件/箱/托、关联SKU、关联单位。扫描时不仅要对出SKU还要对出当前批次的有效期和单位层级。批次效期和多单位叠加时要格外小心一个场景同一批商品先按箱入库后来拆箱按瓶销售。如果系统里批次的库存数量是按基本单位记的那拆箱操作其实只是库存从“整箱库位”移到“零散库位”批次号不变效期也不变。但如果还有一箱里混了两批商品那拆箱时就要在系统里做“批次拆分”生成两个不同的批次记录并按各自的瓶数扣减原批次库存。这个功能没有做好的话效期追溯基本是摆设。4.3 初始化顺序先品类与单位再商品与SKU最后库存系统上线前的初始化和建档顺序是有讲究的。顺序搞反了后面录入数据会发现单位选项为空、SKU没地方关联、条码没法绑定返工工时会非常重。我建议按这个顺序走先建全局基础数据仓库、库位、供应商、客户、单位字典、币种、税率。再建品类结构和规格属性模板比如服装品类定义“颜色、尺码”两个维度饮料品类定义“口味、净含量”两个维度。接着建商品档案SPU选好品类后系统自动带出该品类的规格维度和默认单位。生成SKU输入每个规格值组合系统按规则生成SKU编码同时录入各SKU的条码和单位换算关系。最后录入期初库存按库位、批次、基本单位逐条录入并保证每个库位的盘点单位和录入单位一致。这五步中第4步是最容易被低估的。如果SKU编码规则在测试阶段没反复验证上线时就会出现“同一规格值在不同商品下编码重复”或“编码中包含中文导致接口报错”之类的问题。编码规则我建议用“品类码规格值编码流水号”全部用大写字母和数字不给中文和特殊符号留空间。5. 常见问题与排查技巧实录下面整理几个我实际遇到过、且大概率会反复出现的问题。这些问题在测试环境里很难暴露往往是在上线运行两三个月后集中爆发。问题一月结时发现“双单位”库存虚高或虚低。表现系统里整箱库存和零散库存各自一个数但财务要求看的是基本单位总库存两边加出来却对不上。原因基本是某个环节如调拨入库只记了箱数没有换算成基本单位或者组装单扣减子件库存时不支持小数导致尾差累积。排查时先看库存流水表找“换算方向反了”的记录比如应该乘24却写成除以24的调拨单。这种问题靠人工盯防不现实建议直接在库存流水表增加“源单位和目标单位”字段方便月底筛选出所有换算过的单据。问题二按箱销售的订单把零散库存扣成了负数。表现仓库明明有300瓶散货但客户下了一单“12箱”系统提示库存不足。原因在于销售订单扣减库存时只扣了“整箱库位”的库存没有联动扣减“散货库位”。解决方案有两种简单粗暴的把同一SKU的所有库位库存加总后统一扣减再由WMS做波次分配精细一点的销售下单时支持库位类型拆单整箱部分优先扣整箱库位不足的自动拆成零散库存扣减。后者对业务更友好但前提是主数据里把每个SKU的“单位-库位类型映射”维护好。问题三BOM带出的领料需求数量跟车间实际领料对不上。表现系统按BOM算出来需要领“200公斤膜”车间实际领了“210公斤”差异10公斤。原因通常是两类一是BOM里的损耗率没有维护二是子件单位“卷”和“公斤”之间的浮动换算系数用了默认值没按当前批次的卷重来算。排查时先看BOM用量和实际领料的差异集中在哪些物料再看这些物料是不是浮动换算类型。对浮动换算物料要么让系统直接按批次的实测参数计算用量要么在BOM里挂“参考换算系数”并定期校准不要指望一个固定系数撑到底。问题四条码解析错乱扫描出“另一个SKU”的库存。表现扫茅台酒箱码系统调出的库存却是单瓶的库存。这类问题绝大多数是条码表没有做“条码类型”区分。扫描解析时不能只看条码值必须把条码类型、容器、库位三个条件一起传进去才能唯一定位到当前的SKU和单位。如果你们是自研WMS扫描接口里的SQL别只写where barcodexxx至少要写成where barcodexxx and unit_typebox。问题五报表里“件数”和“个数”老打架。表现所有部门都在看同一张库存报表但销售说库存有1200瓶仓储说库存只有50箱。这其实不算系统bug而是口径问题。解决方式是在报表层增加一个“基准单位”概念后端库存查询一律按基本单位返回前端展示时由用户选择按“瓶”看还是按“箱”看。报表标题下面明确标注“所有数量已按基准单位折算箱数为展示换算”这样就没人吵了。6. 再说几句做多规格多单位的SCM本质上是在帮企业定一套“通用语言”。SKU编码、基本单位、换算规则这些看起来都是很基础的配置但恰恰是它们决定了后续所有单据能不能对得上、报表能不能统一口径。我见过太多项目在前期为了赶进度跳过了主数据治理后来用两三倍的工时去补历史数据那种痛苦谁做谁知道。最后再分享一个小习惯每次改动单位换算规则、新增SKU或调整规格属性之前先存一份“改动前后对比SQL”把受影响的历史单据都跑一遍检查。哪怕系统里有完整的审计日志也不如你在发布前主动确认一下改动前库存余额等于改动后余额出入库流水总数量一致。这两个数一致了你的多规格多单位模型就不会出大乱子。