导读
在 Odoo 中,‘模型’就是数据库里记录的“蓝图”。每一类业务数据——从客户订单到发票再到商品——都由模型来定义字段、关系和存储方式,决定数据如何被检索、显示与处理。
无论是负责配置的业务顾问,还是编写模块的开发者,理解 Odoo 的模型至关重要。模型构成了 Odoo 的数据骨架:字段类型、关联关系和内置逻辑都由模型规定,且各个模型遵循一致的设计模式与生命周期。
本文聚焦在 Odoo 中非常关键的一个模型:product.template。无论你是在定制模块、对接外部系统,还是管理商品目录,都会频繁与该模型打交道。
什么是 product.template 模型?
简单来说,product.template 用来表示一类相似商品的共性信息——那些只在尺寸、颜色等少数属性上不同的商品会作为变体存在。把共有属性放在模板上,个别差异放在变体上,能避免大量重复数据并简化管理。
product.template 在销售、采购、仓库、电商和生产等模块中广泛被引用。你在商品目录里新建的一条记录,实际上是一个模板;在下单时,前端通常让用户在模板下选择某个具体变体来完成购买或出库。
这个模型定义在 product 模块内,其他功能模块通过 Odoo 的模型继承机制在此基础上扩展功能:销售模块增加定价与开票字段,采购模块增加供应商相关字段,库存模块增加库存追踪字段。各模块只补充所需功能,而不重复修改核心结构,便于维护与升级。
弄清 product.template 和 product.product 的区别很重要:模板保留通用信息,变体(product.product)承载条形码、SKU、特定成本等专属数据。正确划分有助于库存追踪、定价和报表的一致性。
模型中的核心字段
下面罗列出 product.template 中常用且影响业务的字段,熟悉它们能让你在配置、开发和集成时少走弯路。
1. name
类型:Char。商品模板的名称,是界面中最直观的标识,常出现在列表、搜索和报表里,便于员工与客户识别商品。
2. create_date
类型:Datetime。记录创建时间,Odoo 自动维护。用于审计、变更跟踪与历史分析。
3. write_date
类型:Datetime。最后一次修改时间,同样由系统管理,帮助判断记录是否需要复核或同步。
4. active
类型:Boolean。软删除标志;将其设为 False 可将记录归档并从默认视图中隐藏,但数据仍保留以供报表或历史查询。
5. sequence
类型:Integer。用于列表或下拉的显示顺序,数值越小越靠前,常用于优先级或可视化排序。
6. type
类型:Selection。商品类型:消耗品、服务或可存储商品。不同类型决定是否参与库存管理与会计处理。
7. categ_id
类型:Many2one(product.category)。商品类别,会影响默认路线、计费规则和统计口径,类别支持层级组织便于目录管理。
8. list_price
类型:Float。销售价格,通常作为报价单的默认值,可被价格表或变体价格覆盖。
9. standard_price
类型:Float。成本价,参与毛利核算与库存估值,直接影响利润报表的计算结果。
10. currency_id
类型:Many2one(res.currency)。用于 list_price 与 standard_price 的货币,通常与公司货币或交易货币一致。
11. uom_id
类型:Many2one(uom.uom)。销售计量单位(如 件、千克、升),定义数量显示与转换规则。
12. uom_po_id
类型:Many2one(uom.uom)。采购用的计量单位,可能与销售单位不同,系统负责单位换算以保持一致性。
13. default_code
类型:Char。内部参考码或 SKU,用于对接外部系统、条码体系或自定义编号策略,建议保持唯一性以便匹配。
14. barcode
类型:Char。条形码字段,常用于 POS、仓库拣货与盘点;变体层面(product.product)通常才会有独立条码。
15. description
类型:Char。内部描述,仅供公司内部使用,用于补充说明或操作备注,不展示给最终客户。
16. description_sale
类型:Text。销售描述,会显示在报价单与发票上,支持富文本(HTML)以便美化商品展示。
17. description_purchase
类型:Text。采购描述,显示在采购单与供应商账单上,帮助采购员与供应商沟通细节。
18. sale_ok
类型:Boolean。是否可售标志;若为 False,商品不会出现在销售或报价界面中。
19. purchase_ok
类型:Boolean。是否可购标志;若为 False,商品不会出现在采购流程中。
20. weight
类型:Float。商品重量,用于物流和运费计算,单位依公司 UoM 设置而定。
21. volume
类型:Float。体积数据,常用于仓储布局与货位容量规划。
22. product_variant_ids
类型:One2many(product.product)。模板下的变体列表,变体继承模板的共性并添加差异化字段。
23. product_variant_count
类型:Integer。变体数量(由 product_variant_ids 计算),用于界面显示与筛选。
24. image_1920
类型:Binary。商品图片,Odoo 会存储不同分辨率用于表单、报表与电商页面展示。
25. responsible_id
类型:Many2one(res.users)。商品负责人,用于任务分配、审批流与管理责任追踪。
26. company_id
类型:Many2one(res.company)。在多公司环境中标识此商品属于哪个公司,影响会计与库存分离。
27. tax_ids
类型:Many2many(account.tax)。销售税规则,结算与发票时会应用这些税目。
28. supplier_tax_id
类型:Many2many(account.tax)。采购税规则,适用于供应商账单。
29. attribute_line_ids
类型:One2many。用于定义会生成变体的属性行(如尺寸、颜色),决定变体的组合逻辑。
30. route_ids
类型:Many2many(stock.route)。商品的物流路线配置(比如采购入库、按单生产、直发),直接影响仓储与补货策略。
31. property_stock_production
类型:Many2one(stock.location)。制造类商品的生产位置,用于生产单与领料管理。
32. property_stock_inventory
类型:Many2one(stock.location)。盘点或库存调整时的默认位置,便于标准化操作。
33. property_valuation
类型:Selection。库存估值方式(自动或手动),决定成本变动如何记账。
34. property_cost_method
类型:Selection。成本计算方法(标准价或先进先出 FIFO),影响库存价值与利润计算。
35. property_account_income_id
类型:Many2one(account.account)。销售收入科目,开票时默认使用该科目。
36. property_account_expense_id
类型:Many2one(account.account)。采购费用科目,用于入账供应商费用。
37. invoice_policy
类型:Selection。开票策略(按订购数量或按交付数量),影响收入确认时点。
38. expense_policy
类型:Selection。费用确认策略(按订单或按交付),影响成本确认时间。
39. service_type
类型:Selection。服务类商品的计费方式(手动、按工时、里程碑),决定服务记录与计费流程。
40. optional_product_ids
类型:Many2many(product.template)。可选搭售商品,用于提升销售单的推荐位或促销展示。
该模型在业务流程中的角色
1. 销售与报价流程
销售人员在创建报价时从商品目录选择商品:模板提供共性信息,若商品有属性(如颜色/尺寸),系统会提示选择具体变体来确定最终销售项。
2. 电商展示
在官网或商城页面,顾客先看到模板级别的商品卡片;点开后再在该模板下挑选不同变体,模板负责展示统一的描述与图片资源。
3. 采购与供应商管理
采购单和供应商账单会关联商品模板或其变体。purchase_ok 控制商品在采购流程中的可见性,supplier_tax_id 与 uom_po_id 决定采购时的税务与计量行为。
4. 仓储与生产
出入库单与生产单通常以变体为核心进行库存数量变动;模板则定义路线、估值策略与成本计算方式,实际库存按变体粒度跟踪。
5. 开票与会计处理
发票/账单行会引用商品记录,模板提供默认的税务与会计科目;invoice_policy 决定收入确认的时间点,从而影响会计报表。
开发者如何扩展这个模型
开发者常用几种方式对 product.template 进行扩展与定制,Odoo 的模型继承是最主要的手段。
模型继承概述
在自定义模块中通过 _inherit = 'product.template' 来扩展原模型:新增字段、覆盖方法或加入约束。采用继承不会修改核心模块代码,便于模块独立升级;覆盖方法时应当调用 super() 以保持兼容性。
新增字段
在继承模型中声明新字段,选择合适的字段类型(Char、Many2one、Boolean、Integer、Text、Selection 等)。若涉及多家公司,应考虑字段是否为公司依赖以保证数据隔离。
Python 层面的扩展
可重写 create、write、unlink 等方法来注入业务逻辑,记得使用 super() 调用父实现;处理计算字段时要注意依赖关系与自动重计算的代价。
Odoo Studio 的快速定制
Odoo Studio 允许无需编码的字段添加与界面调整,适合快速测试或小范围配置。但对复杂业务或需长期维护的场景,建议通过自定义模块实现以便版本控制与可移植性。
最佳实践建议
- 把共享数据放在模板,把与变体相关的字段放到 product.product,以免混淆库存与定价逻辑。
- 为商品设置合适的类别(categ_id),这会影响默认路线、会计映射和统计分析的分类口径。
- 使用 default_code 作为外部映射键,与第三方系统对接时能显著简化 SKU 对齐与数据同步。
- 做 API 对接时优先使用 XML-RPC 或 JSON-RPC,与 product.template 对应的模型在 API 层完全可访问。注意外部 ID 与 Odoo 内部 ID 的映射策略,避免因主键差异导致重复或错配。
- 为自定义字段加上 x_ 或模块前缀命名,以降低与未来 Odoo 内置字段冲突的风险。
常见错误与陷阱
- 把应该做成变体的商品拆分成模板+属性组合,而不是重复创建大量相似模板。attribute_line_ids 是生成变体的正确入口。
- 别把 product.template 与 product.product 混用:需要变体专属属性(如 SKU、条码、库存)时应在 product.product 层面处理。
- 注意设置 sale_ok 与 purchase_ok,否则商品可能在对应模块界面中看不到,导致业务人员误以为商品丢失。
- 覆盖核心方法却不调用 super() 会破坏其他模块的预期行为,甚至影响系统升级时的兼容性。
- 给已有记录增加必填自定义字段但没有默认值,会导致旧数据在升级或模块安装时校验失败,务必设计回溯兼容策略。
总结
总结来说,product.template 是 Odoo 中商品定义的中枢,承担共享属性、定价基准与流程配置的职责。掌握其关键字段与扩展方式,能让你在配置、二次开发与系统集成时更加高效与稳健。
无论你是负责商品目录的功能顾问,还是负责模块开发的工程师,理解 product.template 的设计理念都能减少错误、节省开发时间并提升运营效率。
开始使用 Dasolo
Dasolo 专注于帮助企业实施与定制 Odoo,尤其擅长 API 对接与复杂模块开发。我们在 Odoo 数据架构与像 product.template 这样的核心模型上拥有丰富实践经验,能帮助你把系统搭得更稳、更灵活。
如果你在 Odoo 实施、模块定制或系统对接上需要支持,我们可以提供咨询与交付服务。 预约演示 与我们讨论你的项目需求。