先说结论
分包直运场景里,Odoo 看起来最“像 bug”的地方,就是采购单好像总在奇怪地拆开或合并。
但从源码看,这不是随便发生的。mrp_subcontracting_dropshipping 明确告诉采购规则:当目标地是分包位置时,供应商 partner 和目标地址语义必须进 PO 分组条件。
所以这条链不是普通采购补货的简化版,而是:
为谁买、送到哪个分包商、最终服务哪条制造链,都会影响 PO 是否应该复用。
为什么分包直运容易让人误判
因为用户表面上只看到“我要买一个东西给供应商那里加工”。但系统底层其实同时在处理三件事:
- 这是采购动作
- 这是分包补料动作
- 货的物理去向不是自己仓库,而是分包商语义下的目的地
如果还用普通 buy route 那种“同供应商就尽量并 PO”的思路,很容易把本来不该混的需求混到一起。
源码里最关键的两段
1. _prepare_purchase_order
当规则发现:
partner_id还没明确- 目标位置属于分包位置
- 且下游 move 指向的分包 MO 已经知道
subcontractor_id
它会主动把 partner_id 补成该分包商。
这意味着在分包直运链里,供应商不是“采购员随便选的默认供应商”,而是由制造上下文推出来的业务对象。
2. _make_po_get_domain
如果源是 supplier、目标是 subcontract、并且 partner_id 已存在,Odoo 会把:
dest_address_id = partner_id
也并进查找现有 PO 的 domain。
这一步很重要,因为它等于在说:
- 同一个卖方
- 但送往不同分包目的地
- 不应该当成同一张可复用采购单
为什么 dest_address_id 这么关键
很多人把它只理解成“送货地址字段”。在普通采购里,这样理解问题不大;但在分包直运里,它其实是业务责任边界:
- 物料送给哪个分包商
- 属于哪个外协制造语境
- 后续收货、补料、成本归集要跟谁对上
如果忽略这层语义,最常见的后果就是:
- PO 被错误合并
- 行项目属于不同分包目的地却混在一起
- 后续追单与对账非常难做
最常见的误区
1. 以为 partner 只来自采购价目表
在分包直运里,它常常来自下游制造上下文。
2. 以为同供应商就该合单
不一定。目的地址不同,业务上往往就不该合。
3. 以为 dropship 只是物流选项
在这里它还改变了采购单分组语义。
4. 以为系统拆单就是配置错
很多时候恰恰是系统在保护正确边界。
排错顺序
如果你觉得 PO 被“拆错了”或“并错了”,按这个顺序查:
- 目标位置是不是分包位置
- 下游 move 是否带出了正确的
subcontractor_id partner_id是谁补进去的dest_address_id是否因此进入了 PO 查询 domain- 最后再看采购规则和供应商主数据
一句话记忆法
Odoo 分包直运里的采购单,不只是按“向谁买”分组,还按“送去哪个分包语境”分组。
DISCUSSION
评论区