招标授标

Odoo Call for Tenders 和 Blanket Order 为什么不能只按“长期/短期”来分:授标、替代 PO 与协议落地边界讲透

很多人把 Call for Tenders 和 Blanket Order 的区别理解成“一个比价、一个长期采购”。这当然没错,但还不够。真正决定两者完全不是一套玩法的,是替代 PO 分组、比较行、确认时的授标提醒,以及 Blanket Order 把协议条件注入 supplierinfo 的方式。

采购
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 4 阅读

先说结论

如果你只用一句话概括:

  • Blanket Order 更像“先谈好一段时间内的采购框架,再按框架分批执行”
  • Call for Tenders 更像“围绕同一批需求,同时放出多个候选 RFQ,再做授标决策”

但源码里两者的差异,远不只是“长期合作”和“竞争比价”的业务口号。

真正的分水岭在于:

  1. Blanket Order 确认时会把协议行落成 supplierinfo
  2. Call for Tenders 更强调 同一采购语义下的多个替代 PO
  3. 招标场景里,系统会把这些 PO 组织进 purchase.order.group
  4. 你确认其中一张单时,Odoo 还会提醒你:其他替代 RFQ 你打算怎么处理

所以更准确的理解是:

Blanket Order 是“协议条件注入采购引擎”,Call for Tenders 是“候选报价并列存在、等待授标决策”。


这篇为什么不是站里已有“采购协议总览”的重复

站里已有一篇文章,重点在讲:

  • Purchase Agreement 不是普通 PO
  • Blanket Order 与招标在产品定位上的分工

那篇偏概念框架。

这篇换成实现落点:

  • Call for Tenders 在系统里为什么更像“替代 PO 组”
  • 为什么它天然适合比较与授标
  • Blanket Order 为什么反而不强调并行候选 PO
  • 这两条链最终如何影响后续采购行为

也就是说,这篇不再停留在“它们都属于 Agreement”,而是往下讲 系统到底如何让两者走成完全不同的采购动作


第一关键点:Blanket Order 在确认时就把“协议结果”灌进采购主数据

/home/ubuntu/odoo-temp/addons/purchase_requisition/models/purchase_requisition.py 里,action_confirm()blanket_order 有非常硬的要求:

  • 每行必须有价格
  • 每行必须有数量
  • 然后逐行执行 _create_supplier_info()

这一步的含义特别重要。

它说明 Blanket Order 的设计重点不是“先挂起多个候选报价”,而是:

  • 先把协议内容定下来
  • 再把它转译成采购系统能消费的供应商条件

所以 Blanket Order 的核心动作,是 沉淀协议条件

这和 Call for Tenders 完全不一样。


第二关键点:Call for Tenders 更强调“同源候选单并存”

/home/ubuntu/odoo-temp/addons/purchase_requisition/models/purchase.py 里,官方专门加了一个技术模型:

  • purchase.order.group

字段帮助文本写得很直白:

  • 这是用来分组 call to tenders 的 PO

purchase.order 上,相关关键字段是:

  • purchase_group_id
  • alternative_po_ids

alternative_po_ids 的帮助说明也非常明确:

  • Other potential purchase orders for purchasing products

这已经把招标的系统语义说透了:

Call for Tenders 的重点不是先生成一个“正式协议”,而是保留多个可竞争、可比较、可淘汰的候选采购单。

也正因为如此,它更像授标机制,而不是价格框架机制。


第三关键点:关联 Agreement 时,PO 行的生成方式也不一样

_onchange_requisition_id() 里有一个很容易被忽略的细节:

  • 如果 requisition_type == 'purchase_template',PO 行会带上协议数量
  • 否则 product_qty = 0

换句话说,在非模板式协议里,系统并不是强迫你一挂协议就把真实执行数量直接灌进订单。

这特别符合招标思路:

  • 先拿到同一需求框架下的多个报价
  • 再在后续比较和谈判中决定最终落多少量、给谁、何时下

而 Blanket Order 则更偏:

  • 协议本身已经在价格和数量边界上较为明确
  • 后面是按框架引用和释放,不是并列授标

所以两者即便都叫 Agreement,PO 生成语义也明显不同。


第四关键点:Call for Tenders 天然带“比较”能力

同一文件里,Odoo 还给出了两组非常招标化的方法:

  • action_compare_alternative_lines()
  • get_tender_best_lines()

它会在一组候选单中按产品比较:

  • 总价更低的行
  • 单价更低的行
  • 到货日期更早的行

这就说明官方对 Call for Tenders 的预期不是:

  • 你自己导 Excel 另算

而是:

  • 系统层面就承认“同一需求下存在多个候选采购单”
  • 并为你准备了比较入口

这跟 Blanket Order 的设计方向再次分道扬镳。

Blanket Order 的问题是:

  • 这份协议如何影响后续采购条件

Call for Tenders 的问题是:

  • 这些候选报价里,谁更值得被授标

第五关键点:确认某张候选 PO 时,系统会逼你面对“其他候选怎么处理”

button_confirm() 在招标场景下还有一个非常像授标关口的行为。

如果这张 PO 还有 alternative_po_ids 处于:

  • draft
  • sent
  • to approve

系统不会直接闷头确认,而是弹出一个警告窗口:

  • What about the alternative Requests for Quotations?

这句话非常有业务味。

它不是在做技术校验,而是在提醒你:

你确认了这一张,就意味着你正在做授标动作;那剩下的替代 RFQ,到底是保留、取消,还是继续谈?

这也就是为什么 Call for Tenders 不能被理解成“多发几张 RFQ 而已”。

它在确认环节就体现出:

  • 候选单并存
  • 授标要做取舍
  • 系统知道这些候选单是同一批采购语义下的竞争者

为什么 Blanket Order 反而不强调这套“替代单决策”

因为 Blanket Order 解决的不是“谁赢得这次竞价”,而是:

  • 某供应商的一段合作条件如何进入后续采购流程

从源码看,它更像:

  1. 协议确认
  2. 生成 supplierinfo
  3. 后续 PO 若带 requisition_id,就在卖方准备与过滤时优先使用该协议上下文
  4. 协议结束或取消时,再把相关 supplierinfo 清掉

所以 Blanket Order 更偏 框架生效 / 生命周期管理

而 Call for Tenders 更偏 候选存在 / 比较 / 授标 / 淘汰


实施里最容易搞混的 5 个点

1. 以为两者差别只是“长期采购”和“一次比价”

这只是业务表象。

源码层真正的差别,是一个强调 supplierinfo 注入,一个强调 alternative_po_ids 并行比较。

2. 以为 Call for Tenders 选中一家后,其他 RFQ 只是普通未用单据

不对。系统明确把它们视为替代候选,并在确认时提醒你处理其他候选单。

3. 以为 Blanket Order 也应该天然带多家供应商横向比较

它主要不是为这个设计的。它更像某家供应商的协议条件载体。

4. 以为 Agreement 一挂上,PO 数量就一定来自协议

源码里并不是所有类型都直接灌数量。招标场景更强调候选结构,而不是立即定量执行。

5. 以为两者都只是采购前置页面

实际上,一个影响后续选价引擎,一个影响授标决策流程,它们都在“改变采购系统语义”。


开发和实施时最该注意什么

如果你的目标是“长期协议价 + 分批释放”

优先理解 Blanket Order:

  • 它会不会生成 supplierinfo
  • 后续 PO 是否必须带 requisition_id
  • 协议结束时相关主数据是否会被清理

如果你的目标是“多供应商竞争 + 明确授标”

优先理解 Call for Tenders:

  • 候选 PO 如何成组
  • 是否需要使用替代 RFQ 比较入口
  • 确认其中一单后,其他候选单由谁来收口

如果客户同时想要“长期协议 + 每次仍多家竞价”

这往往已经超过标准源码直觉。

标准 Odoo 并没有把两套治理模型硬揉成一个对象。实施时最好明确:

  • 哪一步是协议管理
  • 哪一步是竞价管理
  • 哪一步才是真正的执行下单

不然用户会同时期待:

  • 既像合同
  • 又像招标
  • 还像自动授标引擎

最后三边都不满意。


一句话记忆法

Blanket Order 管的是“协议条件如何进入采购引擎”,Call for Tenders 管的是“多个候选报价如何并存、比较并完成授标”。

DISCUSSION

评论区

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