Helpdesk 接 Repair,看起来像标准的“升级处理”:问题复杂了,就开一张维修单。但 /home/ubuntu/odoo-temp/enterprise/helpdesk_repair 里最有价值的,不是跳转动作,而是客服叙事和维修叙事如何保持同一条事实链。
参考入口:
enterprise/helpdesk_repair/models/helpdesk_ticket.pyenterprise/helpdesk_repair/models/repair.pyenterprise/helpdesk_repair/tests/test_helpdesk_repair.py
一、repair order 一创建,就要建立双向可追踪关系
RepairOrder.create() 对带 ticket_id 的订单做了两次消息回写:
- 在维修单自己身上记录“从 ticket 来”;
- 在 ticket 上记录“已创建 Repair”。
这很重要,因为客服和维修通常不在同一个团队工作。没有这条双向消息链,后面任何一边都只能看到自己局部流程。
二、状态写回不是全量 chatter,而是有条件地记关键状态
write() 里只有在 state 变化、关联 ticket 开启 use_product_repairs、且新状态进入 done/cancel 时,才往工单消息流写状态事件。说明官方不想把每个维修内部细节都灌进 Helpdesk,而是只把客服真正关心的里程碑同步回去。
三、为什么 _action_repair_confirm() 要主动清掉 default_lot_id
源码注释已经说透:如果 context 里残留 default_lot_id,repair confirm 过程中对 move_ids 的处理可能把同一个 lot 强行带到所有 stock move line 上,导致组件行异常。
这属于非常典型的 Odoo 集成边界问题:上游表单为了方便预填 lot,下游库存动作却不能简单继承这个默认值。官方在确认节点主动 pop 掉,就是为了避免“主件 lot 污染到所有部件”。
四、测试暴露的真实难点不是按钮,而是 lot 与流程并存
test_lot_id、test_helpdesk_repair、test_helpdesk_return_and_repair 说明:售后现场往往不是只有 repair,也可能同时伴随 return。也就是说,这不是单一路径模块,而是工单在售后分支上继续分流。
所以 repair 的价值不在“能开维修单”,而在它能在复杂售后链路里仍然保持 ticket 为主叙事中心。
五、实战建议
- 如果维修确认时报 lot 异常,优先检查上下文残留,尤其是
default_lot_id是否被二次传递。 - 客服只需要关注关键里程碑时,不要把维修所有内部状态都同步回 ticket。
- 同一工单若既有退货又有维修,要把 ticket 当总入口,不要让 repair 与 return 各写各的真相。
六、结论
helpdesk_repair 的重点,不是工单能否转维修单,而是维修动作如何安全承接客服上下文:创建即回链、关键状态才回写、危险的 lot 默认值要在确认前清理。这样客服和维修才能看到同一条售后事实链。
DISCUSSION
评论区