先说结论
Odoo 的报价模板,不是“把历史销售单复制一下”。
它真正做的是:
先定义一套可复用的成交脚手架,再把默认行、有效期、签署/付款要求、可选产品,甚至报价 PDF 附件,一起带进新的报价单。
所以 Quotation Template 更像“销售打法模板”,而不是简单的草稿复制器。
这篇文章主要看了哪些官方源码
我这次主要参考了这些实现:
/home/ubuntu/odoo-temp/addons/sale_management/models/sale_order_template.py/home/ubuntu/odoo-temp/addons/sale_pdf_quote_builder/models/sale_order.py/home/ubuntu/odoo-temp/addons/sale_pdf_quote_builder/models/sale_order_template.py/home/ubuntu/odoo-temp/addons/sale/controllers/product_configurator.py/home/ubuntu/odoo-temp/addons/sale/models/product_template.py
其中最关键的信号有三个:
sale.order.template本身就带require_signature、require_payment、prepayment_percent- 模板行里可以出现
is_optional语义,说明“可选项”本来就是模板的一部分 sale_pdf_quote_builder会在切换模板时同步装配quotation_document_ids
这说明模板从一开始就不是单纯的“默认商品清单”。
报价模板到底在替销售团队节省什么
一个成熟销售流程里,重复的通常不是客户,而是:
- 报价有效期规则
- 是否要求在线签字
- 是否要求预付款
- 常见主商品组合
- 常见附加项 / 增购项
- 附带的品牌页、封面、页脚、产品资料 PDF
如果这些每次都靠销售手动拼,系统再强也会退化成“高级 Word”。
Odoo 的做法是把这些重复决策前移到模板层:
- 模板先定义成交规则
- 销售单再承接客户差异
这样新建报价单时,销售不是从零开始写,而是在一条既定成交路径上微调。
模板为什么能影响“签署”和“付款”
在 sale_management/models/sale_order_template.py 里,模板上直接有:
require_signaturerequire_paymentprepayment_percentnumber_of_days
这非常关键。
它说明 Odoo 认为模板不仅决定“卖什么”,还决定:
- 客户是否必须在线签字
- 客户是否必须在线付款
- 需要付多少比例才算确认
- 报价有效期怎么算
也就是说,模板已经部分承载了成交政策。
新手最容易误解的一点是:
以为这些设置应该都在公司级别统一控制。
但源码给出的设计是:
- 公司级设置提供默认值
- 模板级可以按销售场景微调
这就很符合真实业务。
比如:
- 标准小单:只要求签字
- 定制项目:要求 50% 预付款
- 长周期方案:报价有效期更长
如果这些差异不能落到模板层,销售最终只能靠人记忆。
为什么“可选产品”不是普通备注
很多人第一次看到 Optional Products,会觉得这只是个“推荐配件列表”。
但从源码看,它不是备注,而是可被系统理解的增购结构。
在 sale/models/product_template.py 里,optional_product_ids 明确挂在产品模板上;在 sale/controllers/product_configurator.py 里,系统会在主产品配置时同步拉出 optional_products。
这说明 Odoo 处理的不是:
- “下面写一句你也可以买 A、B、C”
而是:
- 当前主商品是什么
- 当前属性组合是什么
- 在这个组合下,哪些可选产品应该展示
- 展示时还要跟着价目表、币种、日期一起算
这就把 Optional Products 从“备注区”抬升成了“可配置加购链路”。
模板里的“可选项区”到底在干什么
在 demo 配置里,Odoo 甚至会主动生成一个 Optional Products Section,后面跟几条数量为 0 的行。
这个设计很有意思。
它不是为了做数学计算,而是为了表达:
这些行不是默认成交内容,而是给客户二次选择的空间。
所以模板里常见会同时存在两种内容:
1)主成交内容
- 默认就带入报价单
- 数量通常大于 0
- 是本次方案的主体
2)可选成交内容
- 默认不一定进入成交金额
- 目的是引导增购、升级、补充方案
- 更像“结构化 upsell”
这比销售在邮件里说“另外你也可以考虑延保服务”要强很多,因为系统可以继续围绕它做:
- 门户展示
- 价格计算
- 客户选择
- 后续转正式订单
PDF Quote Builder 为什么值得和模板一起看
如果只看 sale.order.template,你会以为模板只是“表单默认值集合”。
但 sale_pdf_quote_builder 把这件事又往前推了一层。
在 sale_pdf_quote_builder/models/sale_order.py 里,订单有:
available_quotation_document_idsquotation_document_idscustomizable_pdf_form_fields
并且在 @api.onchange('sale_order_template_id') 中,会根据模板自动补入可用的 quotation_document_ids。
这意味着:
模板不仅决定报价单里有哪些行,也决定这份报价要带哪些“销售材料”。
比如:
- 品牌封面
- 方案介绍页
- 法务页脚
- 产品附件 PDF
这样一来,报价模板就不只是“商品模板”,而是“成交文档包模板”。
为什么这套设计比“复制旧报价单”高级得多
复制旧单当然也能快,但它有三个问题:
1. 容易把历史脏数据一起复制过去
旧客户地址、旧付款条款、旧说明、旧附件,都会被无脑继承。
2. 难以统一销售打法
每个销售都复制自己最顺手的旧单,久了以后公司根本不知道“标准报价长什么样”。
3. 增购逻辑无法沉淀
可选产品、附带文档、默认签字/付款要求,都散在个人经验里,团队无法复用。
而模板的价值就在于:
- 把共性抽成标准
- 把差异留给当前订单
这才像一套可运营的销售系统。
实战里最容易踩的 4 个坑
1. 把模板当“静态商品包”
结果模板只填了几条产品,没配置签署、付款、有效期,也没设计可选项,最后模板价值极低。
2. 可选产品和主产品没有业务边界
如果什么都做成 optional,客户会觉得报价像菜单;如果什么都塞进主行,报价又会显得太重。
3. 模板与文档附件分离维护
销售改了模板,却忘了同步 PDF 封面或产品材料,最终客户看到的前台体验依然割裂。
4. 以为 Optional Products 只在网站商城有用
源码其实表明它和销售配置器、报价前台是打通的,不只是电商推荐。
该怎么设计一套真正好用的报价模板
我的建议是按三层来想:
第一层:成交底盘
- 默认产品行
- 报价有效期
- 是否要求签字
- 是否要求付款
- 预付款比例
第二层:增购结构
- 延保
- 服务包
- 升级版模块
- 安装培训
第三层:文档包装
- 封面 / 页脚
- 产品资料页
- 行业方案页
- 合规说明页
当这三层都放进模板体系后,报价单才真的从“单据”变成“成交工具”。
一句话记忆法
Odoo 的 Quotation Template 不是复制几条默认行,而是在预设成交规则、增购结构和报价文档包装。
DISCUSSION
评论区