导读:打开订单系统的黑匣子
在 Odoo 中,模型就是数据在数据库里的“表与规则”。每一类业务信息——从客户到发票、从报价到交付——都以模型的形式定义,模型决定了这些信息怎么保存、怎么关联、哪些操作合法。
不论是业务顾问还是开发人员,理解模型是使用 Odoo 的第一步。模型不仅定义字段,还规定了数据之间的关系与业务逻辑,是整个系统数据架构的基石。
本文聚焦一个常被触及的关键模型:sales.order。无论你是在搭建模块、对接外部系统,还是配置销售流程,这个模型几乎不可避免地会成为你的工作中心。
什么是 sales.order 模型
sales.order 表示系统中的报价与销售订单——所有销售相关的交易、价格明细与客户信息都会先记录到这里,随后再根据状态生成发票或发运单。
这个模型属于 Odoo 的销售(Sales)模块,是销售流程的核心数据结构。
典型流程是:业务员在系统中创建报价(draft),填写明细并发送给客户;客户确认后,记录状态切换为已确认(sale),随后触发开票与发货流程。草稿与已确认的订单都保存在同一个模型中,通过 state 字段区分生命周期阶段。
Odoo 的模块化设计允许其他应用对 sales.order 进行扩展:CRM 会把商机与订单关联,财务模块会增加发票相关字段,库存模块会加入交付与承诺时间等。各模块通过继承共同使用同一套核心结构,避免重复建模。
模型中的核心字段一览
下面列出在实际工作中最常用、最值得熟悉的字段。掌握这些字段能让你更准确地配置报表、进行系统集成和排查问题。
1. 订单编号(name)
类型:字符。保存订单或报价的唯一参考编号(如S00042),通常由系统自动生成。它是用户识别与打印文件时最直观的标识。
2. 状态(state)
类型:选项。记录订单所处阶段:draft(草稿)、sent(已发送)、sale(已确认)、done(已完成)、cancel(已取消)等。状态决定了用户可执行的后续操作与流程走向。
3. 客户(partner_id)
类型:Many2one(res.partner)。主客户或联系人,必填。几乎所有与客户相关的规则、价格和报表都会基于该字段展开。
4. 发票抬头(partner_invoice_id)
类型:Many2one(res.partner)。账单地址。如果不填写,默认使用 partner_id。用于结算方与寄账单地址与主客户不一致的场景。
5. 收货地址(partner_shipping_id)
类型:Many2one(res.partner)。发货地址。不填写时同样回退到 partner_id。用于配送单与运费计算。
6. 负责人(user_id)
类型:Many2one(res.users)。负责跟进的业务员或用户。常用于业绩统计、佣金计算与日程分配。
7. 销售团队(team_id)
类型:Many2one(crm.team)。用于将业务员归组,驱动团队报表与配额管理。
8. 订单日期(date_order)
类型:Datetime。草稿阶段为创建时间,确认后为确认时间。常用于报表的时间维度和列表排序。
9. 报价有效期(validity_date)
类型:Date。报价到期日,过期后通常需要重新确认或重新报价,适用于有限期促销的管理。
10. 承诺交期(commitment_date)
类型:Datetime。客户承诺的交货时间点。当设置后,系统会以此为基准安排发运,而非仅依赖物料提前期。对客户承诺管理尤为重要。
11. 订单行(order_line)
类型:One2many(sale.order.line)。订单的明细行:包含商品、数量、单价与税项,是订单的核心数据单元。
12. 不含税金额(amount_untaxed)
类型:Float。订单行合计的税前小计,自动计算并用于显示与报表。
13. 税额(amount_tax)
类型:Float。按税码与配置计算出的总税额,显示在订单和发票上。
14. 含税总额(amount_total)
类型:Float。含税后的最终金额,是开票与财务核算的关键数值。
15. 币种(currency_id)
类型:Many2one(res.currency)。通常继承公司或价格表设置。所有货币字段以该币种计价,跨币种对接时需注意换算。
16. 价格表(pricelist_id)
类型:Many2one(product.pricelist)。决定行项目单价的定价策略,可由客户默认或手工选择。
17. 付款条件(payment_term_id)
类型:Many2one(account.payment.term)。例如“票期30天”或“预付50%”,影响生成发票时的到期日计算。
18. 税务规则(fiscal_position_id)
类型:Many2one(account.fiscal.position)。用于税率映射,跨境或特殊税制客户时需配置正确的财务规则。
19. 客户订单号(client_order_ref)
类型:字符。客户方给出的采购单号或参考号,常印在单据上以便对账。
20. 来源(origin)
类型:字符。记录订单来源(例如来自某个商机或交互),便于事后追溯与报表聚合。
21. 创建时间(create_date)
类型:Datetime。记录记录被创建的时间,由系统自动管理,常用于审计与统计。
22. 最后修改时间(write_date)
类型:Datetime。记录最后一次变更时间,便于追踪数据更新时间点。
23. 备注(note)
类型:Text。用于写入合同条款、内部说明或特殊交付要求,可选择显示在报价或发票上。
24. 是否需要签名(require_signature)
类型:Boolean。启用后客户需在线签署才能确认订单,常见于电商或客户门户场景。
25. 是否需付款(require_payment)
类型:Boolean。为 True 时要求客户先付款才能确认订单,适用于订金或预付模式。
26. 开票状态(invoice_status)
类型:选项。显示开票进度:no(无需开票 / 未开票)、to invoice(待开票)、invoiced(已完全开票)等,便于财务跟进。
27. 锁定标记(locked)
类型:Boolean。被锁定的订单不可修改,通常在确认、记账或关联凭证生成后设为真,防止越权更改。
28. 公司(company_id)
类型:Many2one(res.company)。多公司环境下标识此订单所属公司,影响可见性与会计科目等。
29. 标签(tag_ids)
类型:Many2many(crm.tag)。用于灵活分类与筛选,便于运营与销售分群管理。
30. 签署人(signed_by)
类型:字符。当启用签名时保存签署人的姓名,用于审计记录。
31. 签署时间(signed_on)
类型:Datetime。保存实际签署的时间戳,作为确认交接的凭证。
32. 定金比例(prepayment_percent)
类型:Float。表示需预付的百分比,配合 require_payment 实现分期或订金逻辑。
在实际业务流程中的使用场景
流程示例一:从报价到订单的标准路径
业务员先建报价:填明细、套价格、发给客户;客户确认后报价转为订单(state 从 draft 变为 sale),随后可生成发票与发货单完成履约。
场景示例二:电商与客户门户下单
网站下的订单直接写入 sales.order,系统可通过 require_payment 或 require_signature 强制在线付款或签名后才完成确认。
场景示例三:CRM 到销售的闭环
赢单后的商机可一键生成报价,origin 字段记录来源,user_id 与 team_id 则帮助归因与业绩拆分。
场景示例四:从订单到财务开票
确认后的订单用于生成发票;发票行会拉取订单行数据,付款条件与税务设置随订单传递,invoice_status 用于跟踪开票进度。
场景示例五:交付安排与承诺日管理
使用 commitment_date 来规划发运优先级与排产,当客户有特定交期要求时,应在订单上明确该字段并据此调度库存与物流。
开发者如何在此模型上扩展功能
开发扩展的总体思路
Odoo 主要通过模型继承来扩展已有模型:在你自己的模块中继承 sales.order,添加字段或覆盖方法,而不会直接改写核心代码。
模型继承实操要点
通过设置 _inherit = 'sale.order' 在自定义模块中添加字段与约束,或对已有方法进行增强。这样做能把自定义改动封装到独立模块,便于升级与维护。
新增字段的建议
在继承模型里声明新字段,选择合适的数据类型(Char、Many2one、Boolean、Integer、Text、Selection 等)。多公司环境下注意是否需要 company-dependent 设置。
Python 层面的扩展策略
如需改写业务逻辑,可重载 action_confirm、create、write 等方法,并在适当位置调用 super() 保留原有行为。对计算字段尤其要注意依赖关系与缓存问题。
使用 Odoo Studio 的利弊
实施与定制时的最佳实践
- Odoo Studio 可无代码快速添加字段与视图,适合小改动或试验。但对复杂逻辑、长期维护或多实例升级,自建模块更稳妥。
- 遵循流程状态,别跳过必要步骤
- 不要跳过确认或直接修改状态以绕过验证。正确使用 state 与相应动作能避免数据不一致与流程异常。
- 设定承诺交期以改善交付管理
- 当客户要求明确交期时务必填写 commitment_date,它将影响发运计划并提升客户满意度。
常见错误与陷阱(以及如何避免)
- 在需要归并企业主体时用 commercial_partner_id
- 如果公司存在子公司/分支结构,使用 commercial_partner_id 可按顶层客户聚合信用与报表数据。
- 外部系统对接时使用官方 API 并管理外部 ID
- 通过 XML-RPC 或 JSON-RPC 与 Odoo 交互,sales.order 在 API 层可完整操作。对接时务必维护外部系统的唯一标识(external id)以便双向同步。
- 自定义字段命名要有前缀以避免冲突
总结:把握订单模型,减少变更风险
给自定义字段加模块前缀或使用 x_ 前缀(例如 x_my_field 或 mymodule_x_field),能降低与未来 Odoo 版本字段命名冲突的风险。
不要直接改动已确认且被锁定的订单
需要 Odoo 实施支持?
被标记为 locked 的订单不能直接编辑。若需变更,应走修订流程或通过官方支持的解锁机制,避免数据完整性问题。
常见错误 1:混淆不同地址字段的用途 把 partner_id、partner_invoice_id 与 partner_shipping_id 搞混会导致发票或物流单据寄错人。客户地址不同请同时设置三者。 常见错误 2:覆盖关键方法却不调用 super()