先说结论
当 Odoo 的出库单、内部调拨或收货单一直卡在:
- Waiting Another Operation
- Ready / Available
- Partially Available
- 没有自动 Reserved
很多人第一反应都是:
- 系统没预留
- 仓库没货
- 点一下 Check Availability 就好了
但真正更稳、更不容易误判的排错顺序通常是:
- 先看 scheduled date / deadline 是否合理
- 再看 operation type 的 reservation method
- 再看 move 的 state / availability 语义
- 最后才看 quant 与具体预留细节
因为很多“没预留”“状态不对”的问题,根源根本不在 quant,而在更前面的时间语义。
为什么排错不能一上来就看库存数量
因为 Odoo 里的 availability 不是单纯“仓库里有没有货”。
它还会受到这些因素影响:
- 这张需求是不是已经该轮到它开始抢货
- 它是不是还在等上游 move 完成
- 它属于哪种 reservation method
- 计划日期是不是把 reservation_date 推到了未来
- 当前状态是在表达“业务依赖”,还是“库存短缺”
也就是说,availability 是时间、依赖关系、库存事实三者叠加的结果。
如果一开始就只看 on hand,很容易把问题看窄。
第一步:先看 scheduled date,因为它决定你是不是在“错误时间”排查
这是最容易被忽略、也最容易一眼救命的一步。
如果 move 或 picking 的计划日期本来就还很远,而 operation type 又配置了:
By Date
那系统还没开始预留,可能完全正常。
这时用户肉眼看到的是:
- 明明仓里有货
- 单据却还没 reserved
但系统眼里看到的是:
- 这张需求还没到该入场竞争的时间窗
所以第一步要问的从来不是“有货吗”,而是:
这张单按它的计划日期,现在本来就应该开始预留了吗?
第二步:看 reservation method,因为它决定“何时尝试预留”
同样一张需求,在不同 reservation method 下,系统行为会完全不同:
- At Confirmation:确认后尽快尝试预留
- Manual:默认不自动预留,要人手动推动
- By Date:临近计划日期再尝试预留
这就是为什么排错时不能只盯一张 picking 本身。
很多时候,真正决定行为的是 operation type 上的制度配置。
如果是 Manual,你看到“还没 reserved”,未必是错; 如果是 By Date,你看到“现在没动静”,也可能只是还没到 reservation_date。
第三步:再看 availability state 到底在表达什么
很多团队会把下面这些状态都翻译成“有货 / 没货”,这太粗了。
更好的理解是:
Waiting Another Operation
重点往往不是库存不够,而是:
- 它还依赖上游 move
- 前置动作没 done
- 业务链还没把它推进到可执行阶段
Confirmed
说明需求已经存在,但还没真正分配到库存。
Partially Available
说明系统找到了一部分可分配量,但还不够完整满足。
Assigned / Ready
说明当前所需量已经完成预留,可以进入执行。
也就是说,state 不是单纯数量结论,而是:
这张 move 目前在依赖链和预留链中的位置。
为什么 Waiting Another Operation 经常被误判成库存短缺
这是实战里特别常见的错误。
用户看到 waiting,就以为:
- 库存没到位
但很多 waiting 的根源其实是:
- 上游收货还没完成
- 上一步内部转移还没 done
- pull 规则串出的前序 move 还在路上
- make_to_order / push-pull 链还没推进到这里
这时你去查 quant,往往只会越看越乱。
正确做法是先看:
- 是否有
move_orig_ids - 上游单据是不是 done
- 业务链路是不是本来就要求“前一步先完成”
所以 waiting 更像依赖问题,而不是库存问题。
为什么有货却不 reserved,常常是时间或策略问题
如果 state 不是 waiting,而是 confirmed / partly available,却迟迟不 fully assigned,排查就要回到:
- reservation method
- scheduled date
- reservation_date
- 是否手工触发
_action_assign()/ Check Availability
这时才进一步看:
- 同 location 下是否真有可用 quant
- owner / lot / package 是否把候选 quant 卡窄了
- 之前是否有别的单据已先占掉 free quantity
也就是说,“有货却不 reserved”不一定是 quant 算错,更可能是它现在根本还不该抢,或者它抢的是更严格的那一小撮货。
一个最稳的排错顺序
你可以直接照这个顺序走:
1. 看业务链
- 这是单独 picking,还是依赖上游 move 的链式动作?
- 如果是 waiting,先查上游,不要先查 quant。
2. 看时间
- scheduled date 是什么时候?
- operation type 是 At Confirmation、Manual 还是 By Date?
- reservation_date 是否还在未来?
3. 看状态语义
- 当前是 confirmed、partially_available、assigned,还是 waiting?
- 这表达的是依赖未满足,还是预留未完成?
4. 看库存候选范围
- location 对吗?
- lot / owner / package 条件是否把可用量过滤掉?
- 是否有前序预留已占用 free qty?
5. 最后才看更深层的 quant 异常
- 负库存
- 残留预留
- 数据修复需求
这样排查,命中率会高很多。
为什么 scheduled date 和 availability state 必须一起看
因为 scheduled date 决定的是:
- 这张需求什么时候该进入竞争
availability state 决定的是:
- 它现在在竞争链里的哪一站
两者合起来,你才能判断:
- 是“还没轮到它”
- 还是“轮到它了但上游没放行”
- 还是“轮到它了也开始抢了,但货不够”
这三类问题如果不拆开,排错就会反复误判。
一句话记忆法
先看 scheduled date,判断“现在该不该抢”;再看 reservation method,判断“系统会不会主动抢”;再看 availability state,判断“它卡在依赖、预留,还是数量”;最后才去抠 quant。
这就是 Odoo 库存状态排错最不容易走偏的顺序。
DISCUSSION
评论区