导读:销售行的核心指南
在 Odoo 中,模型相当于数据库里的数据蓝图。每一个业务对象——报价、发票、客户资料——都由对应的模型来定义字段、关系与存储方式,是系统能正确记录和检索信息的基础。
对开发者与功能顾问来说,弄懂模型的设计非常重要。模型不仅仅描述数据结构,还封装了业务规则、计算逻辑和对象之间的关联,是理解 Odoo 数据架构的起点。
本文聚焦销售模块中的核心模型 sale.order.line。无论是做二次开发、打通第三方系统,还是配置价格和发票流程,这个模型都会频繁出现。
什么是 sale.order.line 模型
sale.order.line 用来表示报价或销售订单中的单条明细。每一行通常对应一个被售产品,包含数量、单价、税费等信息,是订单计算与跟踪的基本单位。
该模型属于 Sales 应用,并继承了 analytic.mixin,以支持项目成本和工时的核算。当销售人员在报价里添加商品时,系统就在后台创建相应的 sale.order.line 记录。
模型定义位于 sale 模块,其他模块通过 Odoo 的继承机制对其扩展。比如 sale_stock 会加上与交付相关的字段,sale_margin 会加入毛利计算。各模块只补充所需功能,避免重复定义核心结构。
模型的关键字段一览
下面列出一些在日常工作中最常接触、最关键的字段。掌握这些字段名称与含义,有助于正确配置报价、发货和开票逻辑。
1. order_id
类型:Many2one(sale.order)。必填。指向父订单。这个字段把行项和对应的销售订单关联起来;当父订单删除时,通常会级联删除其行项。
2. sequence
类型:Integer,默认 10。控制行项在订单中的显示顺序,用于排列章节、注释和产品行的展示位置。
3. company_id
类型:Many2one(res.company)。通常从 order_id 关联过来。用于多公司环境下的规则判断和访问控制。
4. currency_id
类型:Many2one(res.currency)。同样来自 order_id,决定该行金额字段使用的币种,保证价格计算一致性。
5. order_partner_id
类型:Many2one(res.partner)。来自订单,代表客户主体。影响价格表、税务与账单规则的匹配。
6. salesman_id
类型:Many2one(res.users)。销售人员,常用于佣金计算与业绩报表。
7. state
类型:Selection。与订单状态关联(如 draft、sent、sale、done、cancel),控制哪些字段可编辑和后续行为。
8. display_type
类型:Selection。取值如 line_section 或 line_note。当设置为这些类型时,该行为章节或注释,不作为产品行参与金额计算。
9. is_downpayment
类型:Boolean。标识是否为预付款行项,预付款通常独立开票处理。
10. is_expense
类型:Boolean。若来源于费用或供应商票据则为真,用于项目成本归集等场景。
11. product_id
类型:Many2one(product.product)。被售产品。对产品行通常为必填,并会受可售商品的域限制。
12. product_template_id
类型:Many2one(product.template)。由 product_id 计算而来,在配置产品变体或产品配置器时使用。
13. name
类型:Text。行描述,由产品、选项或手工备注生成,包含变体信息或自定义说明。
14. product_uom_qty
类型:Float。必填,默认 1.0。订购数量,可被包装规则或单位换算影响。
15. product_uom
类型:Many2one(uom.uom)。计量单位,默认来自产品,决定数量与价格的计算基准。
16. tax_id
类型:Many2many(account.tax)。行适用的税率,通常根据产品与客户的财务位置计算得到。
17. price_unit
类型:Float。必填。每单位的价格,通常由价格表或产品定价计算得出,也可手工覆盖。
18. discount
类型:Float。折扣百分比,在税前对单价进行调整。
19. price_subtotal
类型:Monetary。税前小计,由数量、单价和折扣计算得到,是后续税额与总额计算的基础。
20. price_tax
类型:Float。税额总计,根据 price_subtotal 与适用税率计算得到。
21. price_total
类型:Monetary。含税总额,是用于开票与对账的主要金额字段。
22. product_packaging_id
类型:Many2one(product.packaging)。可选的包装规格(例如 12 片一箱),设置后可影响订购数量和发货单位。
23. customer_lead
类型:Float。交付提前期(天),用于估算确认到发货之间的时间窗口,影响交期承诺。
24. qty_delivered
类型:Float。已交付数量,通常由库存移动更新,也可以手工调整,用于判断可部分开票的数量。
25. qty_invoiced
类型:Float。已开票数量,从发票行汇总计算得出,用于避免重复计费。
26. qty_to_invoice
类型:Float。待开票数量,由已交付与已开票数量推算,用以指导下一步开票动作。
27. invoice_status
类型:Selection。状态例如 to invoice、invoiced、upselling、no,提示该行的开票状态与操作建议。
28. invoice_lines
类型:Many2many(account.move.line)。关联由此销售行产生的发票行,便于追溯与对账。
29. create_date
类型:Datetime。记录创建时间,由 Odoo 自动维护,用于审计与历史追踪。
30. write_date
类型:Datetime。最后修改时间,同样用于审计与变更管理。
在业务流程中的实际应用场景
常见业务场景一:创建报价和订单
销售人员在准备报价时逐行添加商品,每一件商品在系统中表现为一条 sale.order.line,显示数量、单价、折扣与小计。当客户接受报价并确认后,报价转为订单,行项成为后续发货与开票的依据。
常见业务场景二:价格表与折扣策略
每行都会依据客户与价格表规则计算 price_unit 和 discount。价格表能处理阶梯价、客户特价和促销活动,尽量用价格表实现复杂定价,便于管理与追溯。
常见业务场景三:发货与开票节奏
发货发生时系统更新 qty_delivered。可以按交付逐次开票,也可以在全部发货后一次性开票。invoice_status 字段帮助财务和销售团队判断哪些行还需开票。
常见业务场景四:项目类服务与工时关联
对于服务类产品,销售行常与项目任务和工时表关联,analytic.mixin 的继承使得成本与收益可以按项目维度分析,方便项目核算和毛利分析。
常见业务场景五:电商与客户门户
在网站或门户端,访客把商品放入购物车并提交订单时,系统会为每个购物车项生成 sale.order.line。产品配置器根据 product_template_id 和自定义属性生成变体明细。
开发者如何扩展这个模型
开发者扩展 sale.order.line 的常用模式
模型继承是扩展的核心方式,通过继承可以无侵入地增加字段或业务逻辑。
模型继承
在自定义模块中使用 _inherit = 'sale.order.line' 来扩展模型。你可以新增字段、重写方法或添加约束。采用继承可以把变更封装在独立模块中,便于后续升级维护。
增加字段
在继承模型里声明新的 Odoo 字段:Char、Many2one、Boolean、Integer、Text、Selection 等。若涉及多公司环境,考虑使用 company-dependent 字段来避免权限与数据混淆。
Python 层面的扩展
重写或扩展计价相关的方法(如计算单价或小计的方法)、创建或写入逻辑时,应当调用 super() 并正确声明 computed 字段的依赖关系,避免因依赖遗漏导致性能或数据不一致问题。
使用 Odoo Studio
最佳实践与常见建议
- Odoo Studio 能快速添加字段与视图调整,适合低代码需求。但对复杂业务或希望长期维护的功能,建议通过模块化代码实现以便版本控制与升级。
- 实践建议一:用 display_type 管理章节与注释
- 把章节(section)和注释(note)用 display_type 标识,而不要把它们当成空的产品行,这能保持报表、统计和验证规则的清晰。
- 实践建议二:API 与批量创建
- 通过 API 创建行时,优先在订单上下文中创建——例如向 sale.order 的 order_line_ids 传入正确的命令格式,这样 Odoo 的约束与关联会被正确触发。
容易出错的地方与规避方法
- 实践建议三:遵守数据库约束
- 注意数据库与业务约束:产品行通常必须包含 product_id 与 product_uom,而章节或注释则必须设置 display_type,否则会被视为普通产品行而在保存时触发验证错误。
- 实践建议四:优先使用价格表而非直接重写
- 若能用价格表实现定价逻辑就尽量使用它;仅在价格表无法覆盖的特殊逻辑下,才考虑在模型层重写计算方法。
- 实践建议五:为自定义字段加前缀
总结要点
自定义字段请加公司或模块前缀(例如 x_ 或 模块名_)以避免与未来 Odoo 版本或其他模块产生命名冲突。
常见错误一:不在订单上下文创建行
需要我们协助您的 Odoo 项目吗?
order_id 为必填字段。尝试独立创建 sale.order.line 而不关联订单会导致约束失败,应始终在对应的订单里创建或通过订单的 order_line_ids 来添加。
常见错误二:混淆 product_id 与 product_template_id 在明确要销售具体变体时应设置 product_id;在仅需选择模板或在配置器流程中让用户选变体时,可使用 product_template_id 来驱动后续选择。 常见错误三:在已开票后随意改价