企业 采购 / 跨公司

Odoo 企业版跨公司采购单审批后为什么会在对方公司长出销售单:审批触发、公司切换与直运地址边界

基于 sale_purchase_inter_company_rules 源码与测试,讲清采购单审批后如何切到对方公司身份生成销售单,以及 partner、币种、地址和自动确认为什么都不是简单镜像。

企业 采购
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 3 阅读

很多人第一次看到企业版跨公司采购,会以为逻辑很简单:A 公司下采购单,B 公司自动收到一张销售单。

sale_purchase_inter_company_rules 的实现比“自动抄一份单据”严格得多。主入口在 button_approve():只有采购单真正审批通过后,系统才会根据供应商 partner 反查对应公司,再判断对方公司是否启用了 intercompany_generate_sales_orders,并且当前采购单不能是 auto_generated,这样才能避免来回互生死循环。

这条链最关键的一步不是创建 SO,而是切身份、切公司、切上下文。源码用 with_user(company_rec.intercompany_user_id).with_context(default_company_id=company_rec.id).with_company(company_rec) 去执行 inter_company_create_sale_order()。这说明触发用户不一定拥有对方公司的销售权限,真正落单的是跨公司专用用户;如果这个用户没配置,或者没有 sale.order 的创建权限,系统会直接抛错,而不是悄悄失败。

进入 inter_company_create_sale_order() 后,Odoo 还会做一个容易被忽略的硬校验:对方公司 partner 的销售价目表币种,必须和当前采购单币种一致。也就是说,跨公司单据不是“先建出来再慢慢修”,而是先守住定价语义一致,防止采购价和销售价在货币层面错位。

_prepare_sale_order_data() 则说明这张 SO 并非采购单字段原样搬运:client_order_ref 用原采购参考,partner_shipping_id 优先取 direct_delivery_address,没有才回退到 partner 默认收货地址,commitment_date 则来自采购侧的 date_planned。这就是为什么直运场景里,地址问题常常比价格问题更早暴露——系统优先保的是履约目的地,而不是页面看起来像不像同一张单。

行数据也不是简单复制。_prepare_sale_order_line_data() 会把采购行数量和价格换算到产品主单位,再带上折扣和 display_type。新手最容易犯的错误,是以为 UoM 只影响显示;但跨公司单据一旦两边单位体系不完全一致,不做换算就会出现“数量差一点、金额差很多”的假异常。

实施时建议按这个顺序排查:先看 partner 能否反查到目标公司;再看 intercompany user 与销售权限;接着核对价目表币种;最后再看 shipping address 和行单位换算。很多所谓“自动生成失灵”,根因都不是按钮没触发,而是企业版刻意在更前面把不安全的单据挡住了。

结论很简单:企业版跨公司采购审批的价值,不在于“自动建一张销售单”,而在于它把审批、权限、公司边界、地址语义和币种一致性绑成了一条受控链路。

DISCUSSION

评论区

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