POS 预约时段

Odoo POS 预约单为什么不是“选个时间就行”:preset、time slot 与容量控制边界讲透

很多人把 Odoo POS 的 preset 当成前台快捷按钮,但源码里的 pos.preset 其实能同时携带价目表、税制、身份要求、退货模式以及按时间管理订单的容量规则。本文结合 point_of_sale 源码讲清:time slot 如何计算、为什么满额判断不是建一张“时段表”、以及遇到同一时段超卖或不可取消时应如何排查。

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

很多人第一次看到 Odoo POS 的 preset,会把它理解成“前台几个彩色快捷按钮”。

这理解只对了一半。源码里的 pos.preset 不只是 UI 标签,它本质上是一组可直接落到订单上的运营规则包。 它可以决定价格、税制、退货模式、身份要求,甚至可以把订单变成一个有容量上限的时间段预约单。

先说结论:Odoo POS 的时段预约不是靠后台维护一张静态“时间表”,而是由 preset 动态计算可选 slot,再根据最近已开的订单占用量判断是否已满。 所以它看起来轻,但边界其实很硬:规则配错,不是“多一个按钮”,而是整套接单逻辑都会变。

preset 到底承载了什么

models/pos_preset.py 里,preset 至少承载了这些关键字段:

  • pricelist_id:进入该模式后的定价规则;
  • fiscal_position_id:税制映射;
  • identification:是否要求姓名/地址;
  • is_return:是否进入退货模式,购物车默认负数;
  • use_timing:是否按时间管理订单;
  • slots_per_interval:每个时段最大容量;
  • interval_time:时段粒度。

也就是说,preset 其实是“订单模式模板”,不是皮肤。

为什么 Odoo 没有单独建一张 slot 模型

源码里有一句注释很关键:slot 直接按日期时间算出来,而不是专门建一个模型,目的是避免污染数据库。

这代表 Odoo 的设计思想是:

  • 时段不是主数据;
  • 时段是由营业日历、时长粒度、当前订单占用量实时推导出来的;
  • 你真正维护的是规则,不是每一个“10:20、10:40、11:00”的静态记录。

这套设计的好处是轻,坏处是也更容易被误会成“系统会自动替我兜一切容量问题”。实际上不会,系统只会按你给的规则算。

满额判断,看的不是订单总数,而是“某个 preset 的某个 UTC 时点”

get_available_slots() 最终调用 _compute_slots_usage(),它会找出:

  • 该 preset 下;
  • session 仍处于 opened
  • preset_time 不为空;
  • 订单状态在 draft / paid
  • 且创建时间在最近一天内;

的订单,然后按时间点归集。

这说明三个很现实的边界:

  1. 它不是跨天无限统计,而是有时间窗口;
  2. 它主要关心当前还活着的经营现场,不是历史档案;
  3. 它按 preset 自己统计容量,不是全门店所有单一起算。

因此“门店今天明明还有名额,为什么这个按钮下单不了”,往往不是总单量问题,而是该 preset 某一时点已经满了。

preset_time 不是备注,而是后续约束条件

前端 pos_store.js 里,如果选了 use_timing 的 preset,而订单还没有 preset_time,会强制弹 slot 选择。也就是说,有 timing 的 preset 不是“可选填时间”,而是“没时间就不算完整订单”。

这也是为什么很多门店会感觉“自提/预约模式特别容易卡流程”——不是前端故意多一步,而是系统从模型层面就把时间点当成订单约束的一部分。

为什么未来订单不能随便取消

pos_order.py 里有一个很容易被忽略的保护:如果订单交付/自提时间在未来,取消会被拦住。

这背后的逻辑很经营化:

  • 未来订单往往已经占了 slot;
  • 可能已经通知后厨、出餐、备货或配送;
  • 随意在错误时机取消,影响的不只是收银记录。

所以你看到的“不能取消”,本质上不是按钮权限,而是订单生命周期已经进入另一套承诺边界。

最容易踩的几个误区

误区一:preset 只是前台分类入口

不对。它可能同时改变价格、税、身份校验和订单符号。

误区二:slot 满额一定是数据库里有重复时段

不对。Odoo 本来就不是靠静态 slot 表工作,而是实时汇总 usage。

误区三:把 interval_time 调小,容量就更精细更安全

不一定。粒度更细只会让运维复杂度更高,如果 attendance、营业资源和备货节拍没同步,反而更容易形成“纸面可接、现场接不住”。

排错顺序,建议从规则往下看

时段/预约类 POS 问题,建议按这个顺序排:

  1. 先看 preset 本身:是否启用了 use_timing,容量与间隔设置是否合理;
  2. 再看 resource calendar / attendance:营业时段有没有跨天、有没有脏配置;
  3. 再看订单占用:未来/草稿/已支付订单是否仍占着 slot;
  4. 再看前端流程:是否要求先选 preset,再选时间;
  5. 最后看取消与改期规则:是不是未来单被生命周期保护拦住了。

真正难的不是“做预约”,而是让预约和收银共存

Odoo POS 的 preset/time slot 设计厉害的地方,在于它没有把预约单单独做成另一套系统,而是让预约、价格、税制、退货、身份校验都落在同一张 POS 订单上。

但这也意味着,一旦你把 preset 当成“给前台做几个按钮”,就会低估它的力量。它不是界面装饰,而是门店运营策略进入 POS 订单模型的入口。

所以如果你的 POS 已经开始做自提、预约、分时取餐或容量控制,真正该管的不是按钮排版,而是:

  • 不同 preset 对应什么业务承诺;
  • 每个时段真实可承接多少单;
  • 哪些订单会持续占着名额;
  • 哪些取消、改期、切模式动作必须受控。

把这些边界讲清楚,preset 才是效率工具;讲不清楚,它就会变成门店现场最难解释的“彩色陷阱”。

DISCUSSION

评论区

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