很多人配置 POS 时,只把“Update quantities in stock”看成一个体验选项:
- 实时更新;
- 关店更新。
但这个选项背后不是刷新频率差异,而是库存语义边界差异。
结论先说:Odoo POS 的 real-time 与 closing 两种库存模式,差别不只是“什么时候扣数量”,还会改变库存动作颗粒度、成本何时可算、关店压力大小,以及门店对可售数量的主观理解。
配置入口很简单,后果却很深
在 res.company 上,point_of_sale_update_stock_quantities 有两个值:
real:每张订单发到服务器时就更新库存;closing:等 session closing 时统一创建 picking。
对应到 session 上,会变成 update_stock_at_closing 布尔值。
这意味着真正的分歧点不是 UI,而是 session 是否承担“延迟出库容器”的角色。
real-time 模式:每单尽快变成库存事实
如果是实时模式,订单一旦被服务器处理,就会尽快创建自身相关的库存动作。
这种模式的核心优点是:
- 理论库存更接近实时;
- 多终端共用库存时,后续单据更早感知数量变化;
- closing 时库存压力更小,因为大部分动作已经在日间分散落地。
但它的代价也很真实:
- 每张单都要更早触发后端库存逻辑;
- 高并发门店会感觉到更多服务器压力;
- 如果网络不稳定,前台对“已卖出但后端未及时反映”的感知会更敏感。
所以 real-time 更像:
把库存真实度优先级提到前台交易当下。
closing 模式:白天先卖,晚上统一把库存说清楚
如果公司配置成 closing 模式,session 会在结束时调用 _create_picking_at_end_of_session(),按目的库位把整个 session 的订单行聚合起来创建 picking。
这个设计的优点很明确:
- 白天前台响应更轻;
- 库存动作数量更集中,适合高频零售场景;
- 网络和服务器压力可以更平滑地推迟到 closing。
但代价是:
- 白天看到的可售数量可能不是刚刚卖完后的即时状态;
- closing 阶段会承担更大库存与成本计算压力;
- 实施时更容易出现“白天没事,晚上一起报错”的错觉。
本质上,closing 模式是在接受一个 trade-off:
营业中更快,日结时更重。
为什么成本计算也会跟着变
这点最容易被忽略。
在 pos.order._compute_total_cost_in_real_time() 里,源码明确提到:如果某些行因为 session_id.update_stock_at_closing 无法即时确定成本,那这些成本会推迟到 session closing 再算。
尤其对 storable + FIFO/AVCO 产品,这不是小事。 它意味着:
- 订单毛利可能白天先算不全;
- 关店后才补齐部分成本;
- 你在报表上看到的 margin timing 会和业务成交时间错开。
所以别把这个配置只理解为“库存数量晚一点更新”,它还会影响成本确认时点。
为什么很多门店会在这里产生认知错位
门店员工通常会用直觉理解系统:
- 卖掉了,就应该立刻少一件;
- 关店了,才盘点,那就应该晚上再统一扣。
Odoo 两种模式都支持,但它要求实施方先统一口径。 否则会出现这种沟通灾难:
- 财务以为库存实时准确;
- 店长以为白天允许暂时不准;
- 顾问却不知道系统当前到底配的是哪一种。
于是同一个现象,有人说“系统错了”,有人说“这是设计”。
选型边界怎么抓
更适合 real-time 的场景:
- 多门店或多终端共享库存,实时性要求高;
- 高价值商品,不能接受长时间数量滞后;
- 库存 / 订单 / 补货链路对实时可见性敏感。
更适合 closing 的场景:
- 高频小票零售,白天吞吐优先;
- 单店自洽运营,容忍营业时段数量滞后;
- 想把大量库存动作集中在 session 结算阶段。
关键不是哪个“更高级”,而是哪一个和现场经营节奏一致。
实战排错顺序
当用户说“POS 库存不准 / 毛利奇怪 / 白天和晚上结果不一样”,先按这个顺序看:
- 公司级
point_of_sale_update_stock_quantities当前是什么; - session 上的
update_stock_at_closing是否为真; - 库存动作是逐单创建,还是 closing 时统一创建;
- 产品是否为 storable 且采用 FIFO/AVCO;
- 毛利是否在 closing 后才补算;
- 白天看到的数量是不是“opening 时刻视角”而非当前实时视角;
- 用户培训口径是否和系统配置一致。
最后的结论
Odoo POS 的库存更新策略,本质上是在两种目标之间做选择:
- 实时反映库存事实;
- 把前台吞吐放在更高优先级。
real-time 模式更像“让每一单尽快成为库存事实”; closing 模式更像“让 session 成为一个白天暂存、晚上清算的库存容器”。
理解这一点以后,你就不会再把这个设置当成一个无关紧要的小开关,而会把它看成 POS 项目里非常核心的业务边界选择。
DISCUSSION
评论区