第三方外卖平台接入的难点不在“收到一张订单”,而在 Odoo 内部如何保证它既能进后厨、又不能被误删,还能把平台配送语义保留下来。
核心链路
pos_urban_piper/models/pos_order.py给pos.order补了delivery_status、delivery_provider_id、delivery_identifier、delivery_json、delivery_rider_json、prep_time等字段。也就是说,平台单不是普通 POS 单多一个备注,而是整套配送语义都被落进订单模型。_unlink_except_online_order()明确禁止删除带delivery_identifier的线上单。企业版不允许店员把平台单当本地误单直接删掉,因为这会破坏与平台的对账和状态同步。mark_urbanpiper_prep_order_as_printed()先执行SELECT ... FOR UPDATE NOWAIT锁定订单,再检查last_order_preparation_change里的urbanpiper_printed标记,只允许自动打印一次。这个细节解决的是多终端、多线程下的重复出单。- 在
pos_prep_order.py里,_compute_order_otp()会从delivery_json.order.details.ext_platforms里抽取平台侧 OTP,同时标记是否为测试订单。于是备餐/交付流程看到的不只是订单号,而是可核销的取餐凭证。 - 因此 UrbanPiper 集成的主链路是:平台字段入单 -> 后厨打印防重 -> 配送状态与 OTP 进入履约流程,而不是“第三方把 JSON 扔给 POS 就结束”。
关键源码位置
/home/ubuntu/odoo-temp/enterprise/pos_urban_piper/models/pos_order.py/home/ubuntu/odoo-temp/enterprise/pos_urban_piper/models/pos_prep_order.py
容易误解的地方
- 误区一:外卖单导入后就和本地单一样。实际上它带着专门的 delivery 状态和 provider 语义。
- 误区二:自动打印重复几次无所谓。线上聚合场景里重复打印往往意味着重复制作。
- 误区三:OTP 只是展示字段。对某些平台场景,它直接影响骑手/顾客交付核验。
实战注意事项
- 若门店反馈“平台单消失了”,先看是不是有人尝试删除线上单而被逻辑拒绝。
- 排查重复厨打时,重点查看
last_order_preparation_change中的urbanpiper_printed标记和数据库锁冲突。 - 接更多聚合平台时,尽量把平台识别、配送状态、OTP 都收敛在统一字段结构里,避免前后厨各解析一套 JSON。
结语
企业版这些代码共同说明一件事:真正可上线的业务流程,靠的不是“页面上看起来能点通”,而是权限、状态、时机、对账口径和跨模块回写都被收紧。理解这些边界,实施和二开时就不容易走进“功能演示能跑、真实业务一用就散”的坑。
DISCUSSION
评论区