企业 付费预约

Odoo 企业版付费预约为什么不是“付款成功就建日历事件”:booking collision、invoice/make_event 与 gc 清理讲透

基于 appointment_account_payment 源码,讲清付费预约为什么先存 booking、再开票、付款后再成会,并如何处理冲突和过期清理。

企业 其他
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

很多人以为付费预约的逻辑很直白:客户付款,系统立刻建一个 calendar event。可 enterprise/appointment_account_payment/models/calendar_booking.pyaccount_move.py 展示的是一条更谨慎的路径:先生成 booking 暂存,再开票,真正付款后才尝试成会;如果期间可用性发生变化,还要允许 booking 失败并记日志。

一、booking 先占住候选方案,不等于已经成会

calendar_booking.py 里单独存在 booking 模型,就已经说明官方把“预约意图”与“最终会议”拆开了。原因很简单:客户支付、会计过账、资源可用性检查,这三件事未必同一时间完成。

企业场景里最怕的是用户刚下单就看到会议已锁定,但后面支付失败、资源被抢占或配置改变,最终又得人工回滚。

二、付款后才触发 _make_event_from_paid_booking()

account_move.py 里重写 _post(),在发票过账后才调用 posted.calendar_booking_ids._make_event_from_paid_booking()。这一步很关键:业务上的“付款完成”被绑定在会计动作上,而不是绑定在前台支付页面的乐观提示上。

这让付费预约和财务状态保持一致。否则客户以为预约成功、财务却没收到有效凭证,后续纠纷会很难处理。

三、成会前还要再做一次 collision 检查

_make_event_from_paid_booking() 里先对没有 event 的 booking 做 _filter_unavailable_bookings()。后者会按用户和资源两个维度拆时间边界,检查这些 booking 是否真的还能塞进当前可用性里。

这说明系统默认承认一种现实:从用户下单到发票过账这段时间内,排期可能已经变了。哪怕客户已经付钱,也不能盲目建会,否则就会制造双重占用。

四、冲突 booking 不会悄悄消失,而是写回发票日志

_log_booking_collisions() 会在关联发票上 _message_log(),明确指出哪条 booking 因为可用性或配置变化而未被确认。这一点非常企业级:出现问题时,财务和客服需要共享同一份证据,不应只剩一个“系统没建会”的结果。

五、旧 booking 还要定期清理

_gc_calendar_booking() 会删除创建过久或结束时间过久的 booking。原因也很务实:booking 是中间态对象,不应该像正式会议一样长期保留。否则后面查预约失败原因、核对财务与日程时,噪音会越来越大。

实战注意事项

  1. 把 booking 当中间态:它负责衔接支付与排期,不是正式日历对象。
  2. 付款确认要以会计过账为准:不要只依赖支付回调页面。
  3. 允许付款后成会失败:关键是要把失败写清楚,而不是强行成功。
  4. 定期清理历史 booking:避免中间态对象污染运营视图。

新手误区

  • 误以为支付成功就一定能立即建会。
  • 误以为预约冲突只会发生在下单前。
  • 误以为失败 booking 没必要保留痕迹。
  • 误以为 booking 能直接当正式会议用。

主要源码参考

  • enterprise/appointment_account_payment/models/calendar_booking.py
  • enterprise/appointment_account_payment/models/account_move.py

DISCUSSION

评论区

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