企业 采购 / 预算

Odoo 企业版采购预算为什么不是“下单金额对预算余额”:analytic distribution、预算归集与超预算提示边界

account_budget_purchase 不是把采购金额直接减预算余额,而是先把 analytic distribution 转成可 join 的结构,再结合日期、计划维度和未开票金额判断是否超预算。

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

采购预算最常见的误解,就是把它想成“采购单金额 > 预算余额”这么直接的一道 if 判断。

account_budget_purchase 明确告诉你不是。采购行先有 analytic_distribution,然后 _compute_analytic_json() 会把它转换成一组结构化记录:每段分摊里既有 rate,也有按根分析计划展开后的列名和值。也就是说,预算匹配的基础并不是一个简单的 analytic account 字段,而是一份能映射到多个分析计划列的 JSON 视图。

接下来 _compute_budget_line_ids() 才会真正去找预算行。这里的条件很严格:预算必须是确认状态、不是 revenue、日期要覆盖采购单日期,而且只有 product_qty - qty_received > 0 时才继续匹配。更关键的是,源码会把当前分摊里没出现的计划列显式补成 False 去查,这意味着“没填某维度”和“填了别的维度”不是一回事。

采购单头上的 _compute_above_budget() 也不是拿整张单金额去撞预算。它先计算 uncommitted_amount,即 price_unit * (product_qty - qty_invoiced);只有单据还没到 purchase/done 完全落稳时,这个未开票敞口才继续影响超预算判断。随后再把这个值叠到已匹配预算行的 committed_amount 上,看是否超过 budget_amount

这就解释了很多新手困惑:为什么已经部分收货、部分开票后,预算提醒还会变?因为企业版关心的不是“你当时下了多少”,而是“这条采购链还剩多少预算承诺尚未结转”。测试里关于多币种、重叠 account、信用单回冲的场景,本质都是在守这个口径。

action_budget() 也很能说明设计意图。它不是跳去看一张抽象总表,而是把采购单里实际用到的分析账户拆出来,直接带域打开预算报表。也就是说,企业版把采购预算设计成“从采购单追到预算语义”,而不是“从预算看板猜这张采购单算哪一笔”。

实施时最容易踩的坑有三个:把 analytic distribution 配得太随意;忽略日期覆盖条件;以及把 qty_received 和 qty_invoiced 的差异当成同一件事。前者会导致预算行根本匹配不上,后两者则会让团队误判“为什么提醒忽隐忽现”。

结论是:企业版采购预算控制的核心,不是金额本身,而是分析维度、预算期间和未结转承诺三者同时成立时,系统才敢说你真的超了。

DISCUSSION

评论区

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