把客服工单接到库存,看起来像“多一个退货按钮”。但 /home/ubuntu/odoo-temp/enterprise/helpdesk_stock 真正要解决的是:这个客户到底买过什么、送过什么、这次工单应当从哪张交货或销售单继续往下走。
参考入口:
enterprise/helpdesk_stock/models/helpdesk_ticket.pyenterprise/helpdesk_stock/models/stock_picking.pyenterprise/helpdesk_stock/wizard/stock_picking_return.pyenterprise/helpdesk_stock/tests/test_helpdesk_stock.py
一、工单上的可选产品不是商品主数据全集
_compute_suitable_product_ids() 会同时看两类来源:
- 已确认销售订单行里的产品;
- 已完成出库单 move line 里的产品。
而且它是按 commercial_partner_id 展开伙伴集合,再 _read_group 聚合。换句话说,客服工单里的产品域不是商品目录,而是这个客户系真实买过或收过的东西。
二、为什么要同时看 sale order 和 outgoing picking
如果只看销售单,你可能会错过交付层真正发出去的序列号/批次;如果只看出库,又可能丢掉还没完全发货但已售出的业务上下文。官方把两者合起来,就是为了让客服入口既接住“卖了什么”,也接住“送了什么”。
三、lot/serial 不是孤立字段,它跟产品选择强绑定
lot_id 的 domain 直接依赖 product_id。这说明序列号不是后补说明,而是围绕当前问题产品去限定。对于售后来说,这一步很关键,因为你真正要退换修的,通常不是抽象 SKU,而是某个具体批次或序列号实例。
四、退货向导为什么要反推 suitable sale orders / pickings
stock_picking_return 扩展向导后,会根据 ticket 的客户、产品、已完成出库和可用销售单,自动收窄候选来源。尤其在:
- 已选 sale order 时,只看该订单相关 pickings;
- 已选 ticket 产品时,只看包含该产品的出库;
- 没选 sale order 时,仍能按客户与产品去找最近可退的 picking。
这不是为了省点击,而是为了减少“退错单、退错货”的事故。
五、replacement 为什么要单独走一条统计线
replacement_count 与 pickings_count 的计算明确把 is_replacement 单独拆出来。因为 replacement delivery 和 return order 虽然都跟售后相关,但业务语义完全不同:一个是把货收回来,一个是重新发出去补货。
如果把这两类单据混成同一计数,客服就很难判断当前工单到底停在回收阶段还是补发阶段。
六、消息流回写意味着客服与仓库共享同一事实
测试里会检查 return 创建后,ticket 消息里是否写入对应信息。官方显然不希望 Helpdesk 只是一张“链接到库存”的外壳,而是要让工单本身成为客服与仓库共用的事件时间线。
七、结论
helpdesk_stock 的重点不是给工单挂库存对象,而是收紧售后动作的来源边界:只能围绕真实卖出/发出的产品操作,退货来源要可追,replacement 要单独识别,所有动作还得回写到同一张工单叙事里。
DISCUSSION
评论区