库位容量

Odoo 库位容量为什么不是“给库位写个最大数”:storage category、容量规则和混放边界讲透

很多人第一次接触 Odoo storage category,会把它理解成“给库位加一个容量限制”。但官方源码里的设计更细:它同时约束重量、产品容量、包裹类型容量,以及是否允许空位外的新产品进入。本文把这套逻辑讲透。

库存
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

Odoo 的 storage category,不是“给库位写个最大容量”这么简单。

更准确地说,它是在回答一个更完整的问题:

这个库位允许放什么、能放多少、按什么维度计算容量,以及新货进入时能不能和现有货混放。

所以它不是单纯的“上限值”,而是一套库位接纳规则

这也是为什么你只用“最大件数”去理解 storage category,往往会越配越乱。


为什么很多人第一次会配错

因为从业务语言上看,大家最容易想到的只有一句话:

  • 这个货架最多放 100 件

但仓库现实里真正会卡住的,往往不是一个简单数字,而是:

  • 重量有没有超
  • 同一库位能不能混不同产品
  • 同种产品最多允许放多少
  • 某种包裹类型最多允许堆几个
  • 库位不是空的情况下,能不能再塞新货

Odoo 在 storage category 里,其实是在把这些限制结构化。

所以它的设计重点不是“记录一个容量”,而是:

把库位约束从“经验口头规则”变成系统可判断的规则对象。


源码抓手:addons/stock/models/stock_storage_category.py

核心模型主要有两个:

  • stock.storage.category
  • stock.storage.category.capacity

只要看懂这两个模型,你就能明白它不是一个平面配置表,而是分了几层:

  1. 类别本身的总规则
  2. 具体容量规则条目
  3. 按产品与按包裹类型的不同容量语义

第一层:storage category 是一组“接纳原则”

stock.storage.category 上,最值得注意的字段有:

  • max_weight
  • capacity_ids
  • allow_new_product
  • location_ids
  • company_id

这里的结构已经说明了很多东西。

max_weight

不是数量上限,而是重量上限。

capacity_ids

说明容量规则不是只有一种,可能是一组细项。

allow_new_product

这特别关键,它不是在问“最多放多少”,而是在问:

  • 空位时才能放新产品?
  • 只有现有货和新货相同才能放?
  • 还是允许混放?

这已经不是容量计数,而是混放策略了。

所以 storage category 的真实角色更像:

库位准入政策 + 容量政策的组合。


第二层:为什么产品容量和包裹容量要分开

源码里 capacity_ids 会通过 _compute_storage_capacity_ids 分拆成:

  • product_capacity_ids
  • package_capacity_ids

这设计非常值得注意。

因为仓库里“容量”不是只有一种度量法。

按产品容量理解

更像:

  • 这个库位最多放某产品多少件
  • 某个 SKU 在这个区域只能容纳到什么程度

按包裹类型容量理解

更像:

  • 这个货位最多能塞几个托盘 / 周转箱 / 某类包装单元

这两个问题在业务上完全不是一回事。

如果混成一个字段,系统就很难表达真实仓储规则。

所以 Odoo 才会把两类 capacity 分开,但底层仍归在同一组 capacity_ids 里统一管理。


allow_new_product 才是很多项目里最容易被低估的字段

它有三个值:

  • empty:库位为空时才允许新产品进入
  • same:只有现有产品和新产品相同时才允许
  • mixed:允许混放

这说明 Odoo 并没有把库位容量理解成“只要没超量就能塞”。

它还在判断:

这个库位在语义上是否允许引入新的产品组合。

这很重要,因为很多仓库问题不是“放不下”,而是“原则上不该混”。

例如:

  • 同一货位只允许一个 SKU
  • 空位才能重新分配给新产品
  • 混放会影响盘点与拣货效率

如果你忽略这个字段,只盯着数量上限,最后系统经常会表现得“明明还有空间,为什么不能放”。

其实它卡的是准入策略,不是空间本身。


第三层:stock.storage.category.capacity 不是备注表,而是精确规则表

这个模型里最关键的字段有:

  • storage_category_id
  • product_id
  • package_type_id
  • quantity

这意味着每一条 capacity 规则,都是在回答:

  • 针对某个 storage category
  • 对某个产品,或某个 package type
  • 最多允许多少数量

重点是“产品”和“包裹类型”通常二选一,而不是随便都填。

这让容量规则从一句模糊的话,变成了真正可判断的数据项。


约束设计也很说明问题:Odoo 不允许你把规则配成一团糊

源码里有几条很有代表性的约束:

max_weight >= 0

重量上限不能是负数。

quantity > 0

容量条目必须是正数。

同一 storage category 下,product_id 唯一

不能给同一个产品配置多条冲突容量规则。

同一 storage category 下,package_type_id 唯一

不能给同一个包裹类型重复配置容量。

这几条看似简单,其实是在保护系统可解释性。

否则你很容易出现:

  • 同一产品两条不同容量规则到底听谁的?
  • 同一包裹类型一会儿最多 4 个、一会儿最多 6 个

所以 Odoo 的意思很明确:

容量规则可以丰富,但不能暧昧。


为什么它要同时支持 product 和 package type

因为真实仓库里,有两种常见管理粒度:

粒度 1:按货品本身

适合散货、零件、箱内件数管控。

粒度 2:按包装单元

适合托盘位、整箱位、笼车位、周转箱位。

如果你的仓库是“按托盘位管理”,那真正该限制的常常不是产品件数,而是:

  • 这个货位最多几个托盘
  • 这种托盘能不能进这个货位

这就是为什么 storage category 很适合和 package 场景一起理解,而不是只拿它去套传统件数仓。


它解决的其实不是“库存多少”,而是“库位能不能接货”

这一点很关键。

stock.quant 更像回答:

  • 现在这里有多少货

而 storage category 更像回答:

  • 这类货 / 这类包,按当前规则,允不允许继续放进来

所以它偏向仓位治理,不是库存余额展示。

这也是为什么很多项目上线后才发现:

  • 数量逻辑没错
  • 但上架行为总不符合现场预期

根因往往不是 quant 问题,而是库位接纳策略没设计清楚。


实战里最常见的 4 个误区

1)把 storage category 当成“最大容量数字”

这样会忽略重量、混放策略、包裹类型等关键维度。

2)只按产品数量设计,不考虑包裹单位

结果托盘位、整箱位、笼车位等场景会很别扭。

3)忽略 allow_new_product

然后发现系统“不让放”,却以为是容量算法坏了。

4)同一种业务规则想用多条重复 capacity 硬拼

这通常会和唯一约束打架,也说明你的规则粒度设计不干净。


项目里更实用的落地方式

如果你要设计 storage category,我建议先别急着配字段,先问现场 3 个问题:

  1. 这个库位限制的是重量件数,还是包装单元数
  2. 这个库位允许混放吗?允许到什么程度?
  3. 现场是按 SKU 管理,还是按 托盘 / 箱 / 包裹类型 管理?

把这 3 个问题答清楚,再去配:

  • max_weight
  • product capacity
  • package capacity
  • allow_new_product

会顺得多。


小结

官方源码把 storage category 设计成今天这个样子,其实很有代表性:

它不想只做一个“库位最多放多少”的小字段,而是想把仓位规则表达清楚。

所以最实用的一句话总结是:

Odoo 的 storage category,不是容量数字,而是库位接纳策略。容量只是这套策略里的一个维度。

一旦你这样理解,很多上架、混放、包裹位设计问题都会顺很多。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。