共享挂单

Odoo POS 跨收银台共享挂单为什么不是“大家都能看到同一张草稿”:trusted config、currency 校验与 open orders 同步边界讲透

很多人把 Odoo POS 的共享挂单理解成“把草稿单广播给别的收银台”,但 point_of_sale 实际把 trusted config 关系、币种一致性、动态拉单 domain、删除回收和前端 open orders 同步做成了一条完整链路。

POS
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 4 阅读

先说结论

Odoo POS 的“共享挂单”不是一句“让几个收银台看到同一批草稿单”就能讲完。

point_of_sale 里,这件事至少包含四层约束:

  1. 哪些收银配置之间允许互信;
  2. 这些配置是否使用同一种货币;
  3. 前端到底该拉哪些 draft pos.order
  4. 已取消、已变化、已不存在的挂单如何从界面回收。

所以它的本质不是简单广播,而是:

在多个 POS 配置之间,建立一条可控的草稿订单共享通道。

一、为什么共享关系不是“全店自动可见”

源码里关键字段是 trusted_config_ids

对应的方法 _add_trusted_config_id() / _remove_trusted_config_id() 看起来很朴素,但设计意图很明确:

  • 共享不是全局开关;
  • 它是配置与配置之间的显式互信关系;
  • 只有被纳入 trusted 集合的配置,才会进入开放订单同步范围。

这背后其实是在解决一个现实问题:

  • 同一家门店里可能有多个收银台;
  • 但不是所有收银台都应该共享所有挂单;
  • 有的前台是堂食,有的是自助机,有的是外带窗口;
  • 如果无差别互通,收银员会在界面里看到一堆不属于自己业务语境的草稿单。

所以 Odoo 不是默认“越共享越方便”,而是先问:

  • 这两个配置之间有没有业务上的互信关系?

二、为什么源码一定要做币种一致性校验

_check_trusted_config_ids_currency() 是这条链里最值得重视的约束之一。

它会直接阻止:

  • 被互信的两个 POS 配置使用不同币种。

报错也很直接:

  • 不能和使用不同货币的配置共享 open orders。

这个限制非常合理。因为挂单共享看起来只是“订单换个前台继续结账”,但订单里其实已经带着:

  • 商品单价;
  • 税;
  • 折扣;
  • 支付预期;
  • 小票展示语义。

如果 A 配置是人民币,B 配置是美元,你把一张 draft 单直接共享过去,前端就会立刻碰上很多不一致:

  • 显示货币不一致;
  • 付款方式金额语义不一致;
  • rounding / 收款差额边界不一致;
  • 客户看到的小票金额上下文混乱。

所以这不是“保守限制”,而是为了避免把一张订单从一套价格语境硬塞进另一套语境。

三、前端为什么不是“把所有 draft 单都拉下来”

devices_synchronisation.js 里,constructOrdersDomain() 会专门给 pos.order 组装 domain。

它不是简单查:

  • state = draft

而是把条件做成:

  • 当前已同步记录如果 write_date 更新了,要重新拉;
  • 当前记录如果状态变了,也要重新拉;
  • 对于新增 draft 单,还要求 config_id[当前配置, ...trusted_config_ids] 里。

这说明前端同步解决的是两个问题:

  1. 旧记录有没有变化;
  2. 有没有新的共享草稿单进入视野。

如果只做第二件事,前端会看不到已存在挂单的状态变化; 如果只做第一件事,新开出的共享挂单又不会出现。

Odoo 把两者并在一个 domain 里,就是为了让 open orders 既能增量更新,也能补收新增记录。

四、为什么服务端还要返回 deleted_record_ids

read_config_open_orders() 不只返回 dynamic_records,还会回传:

  • deleted_record_ids

而且对 pos.order 有特殊处理:

  • 已取消订单必须强制从前端删除。

这非常关键,因为共享挂单最大的风险,不是“看不到新单”,而是:

  • 继续看到本该消失的旧单。

一旦取消单、失效单、或已经不存在的记录仍残留在界面里,收银员就可能:

  • 错误接手;
  • 误以为还能继续支付;
  • 在高峰时段重复操作。

所以 Odoo 同步的不只是“新增/更新”,还同步“应该消失的东西”。

五、为什么这套机制更像“共享工作台”,而不是“订单转移”

很多人会把共享挂单理解成“把订单从 A 收银台转移到 B 收银台”。

但从源码看,它更接近:

  • 多终端共同观察同一批开放草稿单;
  • 谁来接手结账,取决于后续操作;
  • 订单本身仍保留自己的业务状态,不因为被别人看见就立刻迁移。

也就是说,Odoo 设计的不是一个“强转单”模型,而是一个:

在受控配置集合里共享可继续处理的 draft 订单池。

这比“订单归属硬切换”灵活得多,也更适合多设备门店场景。

六、最容易误解的几个点

误解 1:共享挂单就是多端实时广播

不完全对。它背后还有 trusted config 关系、domain 约束和回收机制。

误解 2:只要看得到挂单,就能安全接手

不对。币种一致性就是第一道硬边界。

误解 3:同步只关心新增记录

不对。写入时间变化、状态变化、取消删除都必须同步。

误解 4:共享挂单等于转单

不对。更准确地说,它是一个多终端共享开放草稿池的机制。

七、做定制时最该保留什么

如果你要扩展 POS 共享挂单,最值得保留的是这三件事:

  1. 继续用 trusted config 显式表达共享关系;
  2. 继续保留币种一致性这种硬约束;
  3. 继续把前端同步做成“新增 + 变更 + 删除回收”三件事一起处理。

很多粗暴定制会直接去掉这些限制,短期看像是更灵活,长期就会变成:

  • 草稿池越来越脏;
  • 不同收银语境混在一起;
  • 收银员界面信息污染越来越严重。

最后一句

理解 Odoo POS 的共享挂单,重点不是“几台机器能不能互相看单”,而是看懂这条主链:

trusted config 建立共享范围 → currency 校验建立价格边界 → open orders domain 拉取新增与变更 → deleted ids 回收失效记录。

看懂以后你就会明白,Odoo 保护的不是“共享”本身,而是共享之后仍然不乱。

DISCUSSION

评论区

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