
做SCM实施这些年我接过最多的需求就是“把商品管清楚”。多规格、多单位这个事听起来就是商品主数据里的基础功能但真到上线才发现它牵扯的是采购、销售、库存、财务一整条链路的底层逻辑。今天这篇不写空理论就拿我实际跟过的几个项目来说透多规格商品怎么建模、多单位怎么换算、单据和库存怎么联动以及那些不踩一遍根本发现不了的坑。1. 搞清楚多规格和多单位要解决什么问题1.1 多规格商品一个商品还是一堆商品先说规格。客户嘴里说的“我要管理多规格商品”通常指向的是同一类东西在属性上存在差异。最典型的就是衣服同款T恤有黑、白、灰三个颜色每个颜色又有S、M、L、XL四个尺码。再比如食品行业一瓶酱油有500ml、1L、1.5L三种容量五金行业一把螺丝刀有十字、一字之分还有不同长度。这些都属于多规格商品。很多企业早期用Excel表管理这些商品一个品牌下所有款号的变体用一行记录规格值全部塞在一个备注字段里。结果就是录单据时全靠人眼识别销售下单写“黑色L码”仓库发货时根本对不上因为Excel里根本没有一个唯一的编码对应这个组合。所以多规格建模的第一个目标就是给每一个可售、可采、可发的具体单品一个唯一标识。这个唯一标识业内叫SKU而那个更高层级的、统管所有变体的目录叫SPU。这里有个特别关键的认知SCM系统里所有的业务单据采购订单、销售订单、调拨单、出库入库单最终明细行挂的都是SKU而不是SPU。如果你在订单明细行或者出入库单据里还能看到“商品”“规格”这种字段甚至文本备注说明这个系统还没有真正实现多规格管理只是把规格当成了一行文字贴在单据上。这也是我判断一个SCM方案是否成熟最简单的方法。1.2 多单位商品单位不是显示字段是业务语言单位这个东西很多产品经理把它理解成一个“展示属性”觉得单位就是个下拉框选“件”还是“箱”而已。但在真实的供应链业务里单位是业务语言本身。采购跟供应商谈价格用的是“箱”仓库日常盘点用的是“件”或者“瓶”财务结算成本可能又要折回基本单位“个”。不同角色说出来的单位不一样但指的都是同一批货。举一个我实际做过的食品项目。客户做粮油贸易商品SKU是“5L装花生油”基本单位是桶上游供应商出厂发货习惯按“箱”报一箱装4桶仓库内部门店配送又按“托”算一托盘放30箱。采购员下单时问“这个月要50箱”系统如果只有一个桶的单位维度采购单上就没法直接录50箱。那怎么办只能人脑换算出200桶再录入再备注一下原始单位。这一套流程下来错单率极高月底对账时全是扯皮。所以多单位管理的本质不是界面上多一个单位下拉框而是让系统在任意一张业务单据上都能按业务方习惯的“那个单位”来录入和展示数量同时系统内部自动换算成统一的库存计量单位去记账。也就是说单位背后必须挂着一套换算逻辑而不仅仅是显示问题。1.3 两个需求叠加后的复杂度单看多规格或者单看多单位都不算难。真正让项目复杂的是这两件事叠加在一起。还是拿食品项目举例子一个商品“冷榨花生油”有500ml、1L、1.5L三个规格三个SKU基本单位是“瓶”。供应商报价按“箱”500ml规格一箱12瓶1L规格一箱6瓶1.5L规格一箱4瓶。这样的结果是规格和单位的组合产生了大量的“换算关系”每个SKU都有自己的一套单位体系不能全局统一换算率。这种情况下如果系统仅支持“全局统一的单位换算表”那一定会出问题。因为系统会认为“一箱6瓶”那么500ml的12瓶装规格录入12瓶时就会自动换算成2箱业务数据瞬间乱套。设计时必须把单位体系挂到SKU层级而不是商品层级。这个细节我在很多团队的方案评审里反复纠正过属于最常见的建模误区。2. 核心设计思路先定模型再谈功能2.1 SKU粒度怎么定不能太松也不能太死仓库的库位也好采购的采购价也好财务的成本核算也好全部依赖SKU这个粒度来归集数据。所以SKU的粒度定义直接影响后续所有业务模块的准确度。我在一个做建筑五金的企业里遇到过反例。他们把同一型号、不同表面处理工艺镀锌和镀铬的产品合并成一个SKU因为“成本差不多嘛卖价也一样”。表面看起来省事实际跑到第六个月出大问题客户下采购单时根本没说明要哪种工艺仓库按库存余量随机发货财务却要按不同的供应商采购价核算成本。最后账实完全对不上不得不把原商品拆成两个SKU还要倒腾半年的历史单据。反向的极端也有。有些企业把批次号、生产日期直接编入SKU导致一票一发货物料变化。比如一件商品每个月新生产的批次都被建了一个新SKU全公司SKU数量爆炸库存台账上出现了几百个“几乎一样但编码不同”的商品。正确的做法是SKU承载规格属性的唯一组合批次和生产日期用批号字段来管理不进入SKU编码体系。确定SKU粒度时我一般会问业务方一个问题不同组合的采购价、销售价、成本核算中心是否可能不同只要有一项不同就要拆成独立SKU。2.2 规格属性的建模从SPU到SKU的标准路径规格属性建模的核心是把“属性”和“属性值”拆成独立实体然后与SKU建立关联。一套我常用且后端落地维护较友好的设计如下SPU标准产品单元存商品基本信息如商品名、品牌、分类、主图、描述。规格属性组存属性名如“颜色”“尺寸”“容量”。规格属性值存具体属性值如颜色下的“黑色”“白色”尺寸下的“S”“M”“L”。SPU与规格维度关联商品创建时选择都有哪些规格维度。SKU标准库存单元按规格维度做笛卡尔积生成组合每个组合是一个SKU拥有独立编码。举个具体的数据结构例子一件衬衫SPU编码SPU-10001名称就叫“商务免烫衬衫”。规格属性组有两个维度“颜色”和“尺码”。颜色属性值黑色、白色。 尺码属性值M、L、XL。笛卡尔积生成6个SKUSKU-10001-01黑色/MSKU-10001-02黑色/LSKU-10001-03黑色/XLSKU-10001-04白色/MSKU-10001-05白色/LSKU-10001-06白色/XL每个SKU除了规格值组合外还有自己的条码EAN或内部条码、默认采购单位、默认销售单位、重量、体积、采购价、销售价、税率、库存预警值等属性。这里有个实践经验如果某商品只有一个规格维度甚至没有规格维度它也照样有一个SKU只是SKU名称直接等于商品名。不要把有属性和无属性做成两套完全不同的逻辑否则基础数据规则会很割裂。另外规格属性不建议直接挂在SKU表的列上。也就是说不要给SKU表去建“颜色”“尺码”“容量”这种固定字段。因为商品类型多种多样今天加了颜色明天又来一个“口径”属性后天后台又要加“把手材质”固定列会让开发陷入没完没了的表结构变更。用属性值表来维护才是可持续的做法这也是多规格商品能否横向扩展的关键。2.3 单位换算体系固定换算率与浮动换算率单位的建模上我习惯把单位分为两类基本单位和换算单位。基本单位是库存基准所有数量最终都折到这个单位下记账换算单位是业务操作时的便捷单位通过换算率与基本单位关联。单位换算率又分固定和浮动两种。固定换算率比较好理解1箱12瓶1打12件这个比率在业务周期内通常不变。浮动换算率就麻烦一些常见于按重量计价的行业比如水产、水果、钢材。采购入库时按“筐”收不同批次的筐实际重量不同有的筐42kg有的框45kg那么每次入库都要重新维护本批次的换算率。对于这类需求系统里必须在“入库单明细行”上允许覆盖换算率。这个字段如果不在单据层开放后续的库存数量、结算重量全对不上。换算率的严谨设计还涉及精度处理。做SCM开发时我强烈建议所有数量字段统一用decimal而不是float换算和计算都使用高精度类型显示时保留有效位数一般默认2位但计算中间值至少保留4位或更多。这一点在后面“常见问题”里会专门展开因为它是所有单位换算翻车的重灾区。设计单位体系时还有几个必备字段我直接给一个常用的单位定义表结构参考字段说明示例uom_id单位主键UOM-001uom_code单位编码BOXuom_name单位名称箱uom_category单位类型固定换算/浮动换算base_uom_id关联基本单位UOM-002瓶conversion_rate换算率12is_base是否为基本单位否是否默认采购单位采购单据默认单位是备注其他说明每箱12瓶整箱不开拆至于六个SKU之间换算率各不相同的问题——还记得那个食用油项目吗——单位体系必须挂在SKU上也就是每个SKU维护一份自己的单位表。这样500ml规格的“1箱12瓶”、1L规格的“1箱6瓶”就互不干扰。2.4 价格与库存的维度选择多规格多单位直接影响的不只是主数据和单据价格体系也是一大难点。采购价、销售价、成本价这些价格按什么维度维护我在方案里通常建议按“SKU单位层级”来维护价格。比如采购价同类商品可能按基本单位“瓶”来报也可能按“箱”来报如果这个供应商还额外给“整托”优惠又需要维护一个托盘价。销售侧也同样。同一款洗衣液单独的1瓶走零售单价整箱卖走箱价箱价往往比单瓶价乘以瓶数便宜。为了折让、促销、渠道分销这些场景都成立系统需要支持“按单位报价”。也就是说价格表里至少要存下SKU、销售单位、起始数量、终止数量、单价、币种、生效日期、失效日期这些字段。在订单录入时选择了单位之后系统自动带出对应单位的价格。如果按基本单位录入则带出基本单位价格。价格带不出或者带错业务员在录单界面马上就会发现这种反馈机制非常重要。库存维度上库存账必须始终以基本单位存储。不管订单上按箱录还是按托录最终增减库存的时候都要折回基本单位。库存查询界面可以按不同单位展示但数据库账面的字段一定是“基准库存数量”。这个原则我建议写进系统设计文档的强制性约束里因为总有人想省事把单位数量直接存进库存表最后单位一旦调整账目就会彻底无从核对。3. 实操过程从需求到上线的关键环节3.1 商品档案设计实操在设计商品档案页面时我推荐一个实际用过的交互方案。画面左侧是SPU列表展示商品通用信息名称、品牌、分类、状态右侧是规格维度配置区。选择规格维度后系统自动生成规格值录入区域。管理员录入所有可选值点击“生成SKU”系统自动组合。每个生成的SKU自动带一个可编辑的编码和条形码管理员可以再补充采购价、销售价、重量等字段。这个方案看似简单实际做的时候要注意三个细节。一是规格维度顺序的问题。生成SKU编码时建议用固定的维度顺序比如按“颜色尺寸”还是“尺寸颜色”并且在编码规则里展示出来否则同一个商品不同的人看到SKU列表的顺序不同沟通成本很高。我就见过一个客户同一编码规则半年后突然发现同类新商品生成的SKU条码前缀不一致就是因为规格顺序没有锁死。二是“多属性项”的选择。有些场景下某些规格值组合实际不存在。比如一个双开门冰箱的颜色维度有“银色”“白色”但“白色”只对应“对开门”不对应“三门”直接做笛卡尔积生成的某些组合是无效的。系统需要支持对无效组合的禁用。注意禁用的是SKU而不是删除规格值否则历史单据引用会断裂。三是“条码打印”的粒度。所有SKU生成后要能按SKU批量打印条码粘贴到仓库货位或商品包装上。标签打印组件需要支持按“SKU序号”批量生成否则仓库贴标扫码全套流程跑不起来。3.2 采购下单与收货的单位联动采购模块是多单位使用的第一主战场。一套完整的流程是这样的采购员创建采购订单先选供应商然后选择SKU。每个SKU行默认带出“默认采购单位”如果本次采购要用其他单位可以直接切换系统会显示对应换算后的数量。举个例子SKU是“500ml花生油”基本单位瓶默认采购单位箱1箱12瓶。采购员准备下50箱。选择SKU后系统默认单位如果是瓶可能需要采购员手动把数量500改成50再切换单位。这里如果产品没有做好数量字段和单位字段联动时会计算出错。所以我专门强调过一种做法录入顺序应该是先选单位再填数量。当单位从瓶切到箱时如果数量还是之前输入的500系统要自动重新换算为41.67箱并提示不能静默截断。收货环节也一样。仓库收货时单位选择箱录入实收数量。上架确认时系统自动把箱数换算为基本单位增加库存量。如果本次到货发现实际箱规与档案不一致比如供应商这批发的是8瓶/箱就要允许在收货行临时覆盖换算率。覆盖后系统要按新的换算率计算入库数量且这个覆盖仅对当前入库单生效不能同步修改SKU档案里的默认箱规。需要特别注意权限和日志。单位切换、换算率覆盖这两个功能在单据审核通过后都不能允许编辑只能作废重录或者红冲。不然单据已经生效、库存已经变化再把数量单位改掉库存和历史应收应付全都会乱套。3.3 销售下单与出库的镜像操作销售模块的逻辑与采购镜像但更靠近客户体验。销售员在客户面前报价、下单如果单位切换卡顿体验会很糟糕。所以在销售侧我习惯把单位切换连带价格带出的逻辑做重一点。举例来说一个经销商客户习惯按“箱”订货但销售折让政策是按“瓶”算的。销售员在订单行选择SKU系统默认显示基本单位瓶报价也是瓶价。销售员切换为箱时系统要做两件事数量换算和价格自动带出。如果箱价存在就带箱价如果没维护箱价系统要按照“瓶价×换算率×折扣政策”自动算一个参考价并标注一行提示“使用计算价格”。这里最容易出问题的是价格保留小数过多。箱价是按瓶价×12得出的如果瓶价是3.58元箱价就是42.96元。但如果瓶价是3.29元箱价按相互乘算就是39.48元客户去结算时看到多一位小数可能会问。所以价格计算后建议在系统里统一保留2位小数并采用四舍五入同时把“按换算率计算的价格是否自动保存为SKU箱价”做成一个可配置项。默认不自动保存避免管理员偷偷依赖这个计算价格而没有维护正式的箱价后续又出现价格不准的问题。出库侧与收货侧对应。拣货单打印的时候默认按基本单位展示数量。但如果仓库习惯按箱拣可以按“箱瓶”双数量打印比如“4箱2瓶”。这种双单位展示的效果很受仓库欢迎毕竟很少人愿意看着“50瓶”自己去心算4箱零2瓶。3.4 库存台账与报表统计口径库存台账是SCM系统的地基。一个真正能打的多规格多单位系统库存台账里每一行商品都必须有“基准库存数量”字段。至于高级一点的可以增加“辅助库存单位数量”供查询参考但不参与计算。我举个例子说明台账字段的必要性。商品“农夫山泉550ml”基本单位是瓶。台账表里有SKU编码、批次号、库位、数量瓶、锁定数量、可用数量。如果系统只在界面上显示“1000瓶”业务人员需要知道这是多少箱完全可以点开单位切换查询。但报表导出时我一般会引导客户按“基本单位”导出或者按带单位的导出格式“数量单位”避免只看数字不知单位。月末财务对账时成本结转必须用基本单位来算。本月入库了200箱每箱12瓶成本单价3.5元/瓶那么本月入库成本就是200×12×3.58400元。如果让仓库在单据上录成“箱”就直接把箱数存进数量字段那财务按数量×3.5算出的4200元就亏大了。所以“所有账务计算都折回基本单位”不是一条可选项而是必须写在开发规范里的硬性要求。报表统计也要注意口径统一。按SPU维度汇总销售金额可以但千万不要按SPU去汇总库存数量否则不同规格之间的数量直接相加没有意义。库存报表必须至少按SKU粒度才具备后续合并到SPU或其他维度的能力。我接手过一个项目前期报表只做了SPU维度客户看见月报里“库存5000”看得一头雾水后来改成SKU粒度旁加单位列才算真正解决数据可用性的问题。4. 常见问题与排查技巧实录4.1 换算精度翻车1000g不等于1kg做过贸易类项目的都对重量单位有阴影。采购按“吨”进库存按“公斤”存销售按“斤”出。如果换算率按浮点型存储当数量特别大时可能出现“1吨入库库存显示999.999kg”的尴尬结果。这类问题的排查要点有三个确认数据库数量字段类型是不是decimal(18,4)或更高精度而不是float。确认换算时中间结果有没有再次四舍五入比如先算箱数再算瓶数两次舍入误差会积累。确认单位换算是否走了“进位规则”。比如0.5箱按瓶算是6瓶但有的行业规定“不满一箱不开零”那单据上数量要允许按箱取整或者提供“向上取整到箱”的开关。我排查过的案例里绝大多数是中间结果精度不够导致的。后来凡是涉及单位换算的模块我都会定一个规矩数据库所有数量字段至少decimal(18,4)前端所有数量展示至少显示2位小数。财务计算时使用decimal运算禁止将数量转换为浮点数参与乘法。这条规则文章里的代码片段虽短但对维护成本影响巨大。4.2 规格属性变更引发历史单据错乱多规格管理的常见隐患是上线跑了一年后业务说“这个颜色的面料停产了要删掉这个颜色”。如果直接删规格属性值所有引用该颜色的历史SKU、历史单据会全部失去参照查询时一片空白。正确做法是“禁用保留”。属性值表加一个“禁用”标志禁用后新建单据无法选择该颜色但历史单据查询时仍能正常显示旧SKU的名称和属性描述。如果历史单据的SKU关联的是编码而编码不能复用那么即使删掉属性值SKU表的数据也会独立保留不至于丢失。我的经验是给所有涉及规格属性、SKU信息的表设计“软删除”凡是有业务单据引用的主数据一律不允许物理删除。这条规则帮我避开了很多次足以让业务停摆的事故。还有一种情况是规格属性新增维度。比如原来T恤只有颜色和尺码现在要多加一个“版型”维度修身/宽松。新增维度后原有SKU的属性组合必须重新生成吗通常有两种做法一是保留老SKU的旧属性组合如颜色尺码同时对“版型”留空二是强制原有SKU继承新属性并生成新SKU。我建议采用第一种老SKU的历史属性组合不要动新SKU按新维度创建并把老SKU打上“历史商品”标识。这样历史数据不会漂移业务也容易理解。4.3 SKU粒度的历史选择失误如何回补如果前期SKU粒度没有设计好比如前面提到的五金客户把镀锌和镀铬两个工艺合并成了一个SKU那系统上线后想拆分怎么办这种结构性错误没有银弹只能按既有逻辑回补。我的建议路径是先新建两个正确的SKU分别承载镀锌和镀铬的出入库记录然后对原SKU的库存余额做“调整单”把原SKU的存量全部出空再分别做两个入库单把库存调平到新SKU。采购、销售的历史单据如果还要追溯需要做一个“编码映射表”把原SKU编码映射到两个新SKU编码供历史查询使用。成本核算方面原SKU的历史成本平均到两个新SKU上可以由财务给出规则比如按相同成本或按不同工艺的实际采购成本拆分。这个没有标准答案只能双方确定后固化到调整流程里。这类问题的根治办法还是在蓝图阶段把SKU粒度的评审做好但万一漏了按照上述调整路径也能平滑度过。4.4 一个排查工具思路与团队协作建议多规格多单位系统的数据问题往往不是单点问题而是模型问题。排查的时候我建议按下面这个顺序走一遍第一步定位单据。找到出错的那笔业务单据看明细行的SKU、单位、换算率、数量。第二步核对档案。看SKU档案里维护的单位表当前换算率是否和历史一致。第三步核对中间计算。把单据数量按历史换算率手工重算一遍看库存账的增减是否与重算结果一致。第四步核对成本结转。涉及财务的再把数量和单价相乘看金额是否一致。这套“从单据到档案到计算到财务”的排查路径基本能定位九成以上的问题。给团队的协作建议同样习惯用表格沉淀出来主数据维护由谁负责、单位换算调整流程由谁审批、SKU变更涉及的历史单据处理步骤是什么。把流程人员、操作审计、异常预案写进项目上线手册比写几千行技术文档更有用。多规格多单位这套体系复杂在细节但稳定运行靠的是规则和习惯。5. 个人实操总结回想这些项目多规格多单位在SCM里确实是最容易返工的功能模块。很多团队一开始抱着“需求很简单”的心态去做结果到联调阶段才发现采购、销售、仓库、财务四个角色对“单位和规格”的理解各自不同各种边界情况层出不穷。我个人最深的体会是在设计阶段就抓三件事。第一SKU是任何业务单据的基础粒度不在SKU层做的事后面都会变成坑第二单位换算必须放在SKU层级维护避免规格之间互相干扰第三库存和财务计算永远基于基本单位其他单位只是业务表达形式。只要守住这三条底线多规格多单位这个项目就已经成功了一大半。另外想提醒的是等系统上线稳定后最好安排一个月度复盘动作把SKU新增量、无效规格占比、单位换算率变更次数这几个指标拉出来看一看。数值异常往往预示着业务或主数据管理在悄悄发生变化。系统的设计是根基但持续的维护规则才是长期稳定运行的保障。