项目深度

Odoo 制造项目为什么不只是“工单上选个项目”:BOM、MO、工单工时与项目分析成本到底怎么耦合

Odoo 把项目和制造打通后,并不是简单让 MO 多一个项目字段。源码里 BOM、制造单、原料 move、工单工时都会沿着项目分析分摊进入项目成本体系。本文把 `project_mrp` 与 `project_mrp_account` 的设计讲透。

项目
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

很多人理解 Odoo 的“项目 + 制造”联动时,会以为它只是:

  • BOM 上能填项目
  • 制造单上能看到项目
  • 项目页多两个按钮看 BOM 和 MO

但如果你读 /home/ubuntu/odoo-temp/addons/project_mrp/project_mrp_account/,会发现官方做的是更完整的一条分析成本链:

  • BOM 可以挂项目
  • MO 会默认吃 BOM 上的项目
  • 从项目页创建 MO 时又会反向把项目上下文传进去
  • 原料 move 会继承项目分析分摊并生成制造类分析行
  • 工单工时也能按照项目分析分摊写入 analytic entries

所以项目制造联动的真正重点不是“项目能打开制造单”,而是:

制造活动如何被正式纳入项目成本与分析维度。


第一层:BOM 与 MO 上的项目字段为什么都要存在

project_mrp 里:

  • mrp.bom 新增 project_id
  • mrp.production 新增 project_id
  • mrp.production._compute_project_id() 会在通常场景下从 BOM 带入项目

这说明官方不想把项目字段只放在一个位置。

因为制造链条里有两个不同阶段:

1. 设计/准备阶段

BOM 表示“这套物料/工艺结构属于哪个项目背景”。

2. 执行阶段

MO 表示“这次实际生产执行归属于哪个项目”。

如果只有 BOM 有项目,执行单据层不够好用;如果只有 MO 有项目,很多默认继承和统计入口又不好做。

所以两边同时挂项目,是为了让模板侧与执行侧都能保留项目语义。


第二层:为什么从项目页发起和从 BOM 发起都能成立

mrp.production._compute_project_id() 在非 from_project_action 场景下,会默认让 MO 继承 BOM 的项目。

而从项目页进入制造动作时,context 又会带:

  • default_project_id
  • from_project_action

这背后的设计很细:

  • 如果你是从 BOM/制造流过来,项目应该从 BOM 继承
  • 如果你是从项目视角主动发起,项目应该以当前项目为准

也就是说,官方并没有硬写一种唯一来源,而是根据入口不同决定优先权。

这正是成熟业务系统的做法:

同一个字段的默认值,取决于操作上下文,而不是单纯依赖某一个上游单据。


第三层:原料 move 为什么也要吃项目分析分摊

project_mrp_account/models/stock_move.py 里,raw_material_production_id.project_id 会参与:

  • _get_analytic_distribution()
  • _prepare_analytic_line_values()
  • _prepare_analytic_lines()

意思是只要库存移动属于某张制造单,而那张制造单又归属于项目,那么原料消耗就能按项目分析分摊进入分析账。

而且源码同样会校验制造业务域下必填的分析计划是否齐全,不齐全就拦截。

这说明项目制造成本并不是“MO 页面上有个项目字段”那么浅,而是会一直下沉到:

  • 原料领用
  • 分析分摊
  • 成本分析行

这才是项目制造成本真正可算的基础。


第四层:工单工时为什么也会写到项目分析里

project_mrp_account/models/mrp_workorder.py 扩展了:

  • _create_or_update_analytic_entry_for_record()

在标准工单工时分析行之外,它还会基于项目的 _get_analytic_distribution() 再生成 / 更新 mo_analytic_account_line_ids

这一步很关键,因为制造项目的成本不只是原料,还包括:

  • 人工工时
  • 机台 / 工序执行时间所代表的成本

所以如果你只把库存消耗进项目,不把工单工时也进项目,那项目制造成本仍然是不完整的。

官方这里等于是在说:

制造项目的分析成本,必须同时覆盖材料消耗和执行工时。


第五层:项目页上 BOM / MO 按钮的真正意义

project_mrp/models/project_project.py 里,项目会显示:

  • BOM 数量
  • Manufacturing Orders 数量
  • 打开相关列表/表单的动作

很多人会把这些按钮当成“方便跳转”。

但真正的含义其实是:

  • BOM 与 MO 已被承认为项目上下文中的一等对象
  • 项目不是只跟任务和工时相关
  • 对某些交付型制造业务,项目可以成为计划、执行、成本回看的统一入口

这意味着项目在 Odoo 里正在从任务容器演化成跨模块交付容器。


新手最容易误解的 4 件事

1. 以为制造项目联动就是 MO 上多一个项目字段

不对,真正关键是分析成本链路也跟着打通。

2. 以为 BOM 上有项目就够了

不对,MO、raw material move、workorder 都会继续吃这个项目语义。

3. 以为项目制造成本只包含原料领用

不对,工单工时也会写入项目分析行。

4. 以为从不同入口创建 MO,项目默认逻辑都一样

不对,源码会根据 context 区分优先来源。


实战里最该注意什么

1. 客户说“制造成本没进项目”,不要只查 MO 表头

至少要继续查:

  • raw material move 的 analytic distribution
  • manufacturing_order 域下的 mandatory plans
  • workorder analytic entries 是否生成

2. 多项目、多 BOM 共享环境里,要特别留意项目默认值来源

从 BOM 发起和从项目发起,默认逻辑可能不同。

3. 如果项目利润只看到了材料、没看到人工,不一定是报表问题

也可能是工单工时分析行根本没按项目分摊出去。


一句话记忆法

Odoo 制造项目联动不是给 BOM / MO 多一个项目字段,而是把 BOM、制造单、原料消耗和工单工时一起拉进项目分析成本体系。

DISCUSSION

评论区

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