导读:掌握产品变体的核心数据模型
在 Odoo 中,模型决定了数据如何被组织与存储。从销售单到库存、从供应商到产品信息,所有业务记录都以模型的形式存在数据库里。理解模型就是知道数据的“户口本”长什么样。
无论你是实施顾问还是开发工程师,弄清 Odoo 的模型设计至关重要。模型定义了字段结构、记录间关系以及嵌入的业务规则,构成了系统的数据骨架。
本文聚焦于 Odoo 中极为关键的一个模型:product.product。无论是做自定义模块、连接第三方系统,还是搭建商品目录,这个模型都会频繁出现。
什么是 product.product 模型
product.product 用来表示系统里的具体产品变体——即那些可以下单、可以收发货、可以计库存的实际商品条目。它是销售单、采购单、库存移动等业务记录中直接引用的“货品”对象。
这个模型与 product.template 的分工很明确:template 保存同一类产品共享的属性,而 product.product 则代表具体的变体。对于无可选属性的单一商品,一个 template 对应一个 product.product;对于有颜色、尺码等属性的商品,每一种组合都会生成一个单独的 product.product 记录。
product.product 定义在 Odoo 的 product 应用模块中,销售、采购、库存和电商等功能模块都会引用它。无论是添加报价行、生成收货单,还是在网站上展示商品,幕后都在操作 product.product 记录。
product.product 通过委托继承(delegation inheritance)与 product.template 联动。大量通用字段放在 template 上,由变体继承;而变体可以覆盖或扩展这些属性,从而既保证共享数据的一致性,也允许单品差异化。
模型中需要重点关注的字段
下面列出在日常配置与开发中最常用的字段,理解它们能帮助你高效处理变体层面的需求与集成。
1. name
类型:字符。记录变体的名称,通常在列表、表单与单据中直接显示。对于不分变体的商品,name 与模板名相同;有变体时通常会把属性值拼接入名称以便识别(例如“短袖 - 蓝 / M”)。
2. product_tmpl_id
类型:Many2one(product.template)。指向父模板的外键。每个变体都属于唯一的模板,这是建立模板—变体关系的核心链接,也是扩展或继承逻辑时必须参考的字段。
3. default_code
类型:字符。内部编号或 SKU,用于内部识别、条码匹配以及与外部系统对接。每个变体都可以拥有自己独立的默认编码。
4. barcode
类型:字符。产品条码(如 EAN/UPC)。在 POS、仓库和库存盘点中用于扫码识别。设置后应保证唯一性以免冲突。
5. create_date
类型:日期时间。记录创建时间,由 Odoo 自动维护。对于审计与变更追踪很有帮助。
6. write_date
类型:日期时间。记录最后一次修改时间,也由系统自动维护,有助于判断数据的时效性。
7. active
类型:布尔。软删除/归档标志。设为 False 可以在默认视图中隐藏记录,但保留历史数据以便查询与对账。
8. type
类型:选择。产品类型:Consumable(消耗品)、Service(服务)、Storable Product(可存货)。不同类型决定了是否参与库存管理、是否出现在某些工作流中。
9. categ_id
类型:Many2one(product.category)。产品类别,用于统计、价格规则与目录组织。类别支持父子层级,方便做报表或按类过滤。
10. list_price
类型:浮点。销售价格,通常在报价和网店展示时作为默认值,价格策略可通过价目表覆盖。
11. standard_price
类型:浮点。成本价,用于库存估值与毛利计算。通常由采购、生产或人工录入更新。
12. uom_id
类型:Many2one(uom.uom)。销售与库存使用的计量单位(件、公斤、升等),决定数量如何表达与计算。
13. uom_po_id
类型:Many2one(uom.uom)。采购计量单位,可以与销售单位不同(例如按箱采购、按件销售),系统会处理单位换算。
14. description_sale
类型:Html。销售描述,用于报价、订单与发票上展示,可以包含格式化文本和产品详情,提升对客户的说明性。
15. description_purchase
类型:Html。采购描述,出现在采购单与供应商账单上,便于与供应商沟通规格与交付要求。
16. sale_ok
类型:布尔。是否可销售。若为 False,商品不会出现在销售界面或电商目录,适用于仅内用或仅采购的物料。
17. purchase_ok
类型:布尔。是否可采购。若为 False,商品不会出现在采购流程,适用于自制或仅销售的项目。
18. image_1920
类型:二进制。高分辨率商品图片。Odoo 会衍生多种尺寸(如 image_512、image_256)以适配不同展示场景,用于表单、网店与报表。
19. weight
类型:浮点。产品重量,用于物流与运费计算。单位由公司设置决定(公斤/克等)。
20. volume
类型:浮点。体积信息,用于运输费用估算和仓储容量管理,尤其对需要按体积计费或仓库布局的企业很关键。
21. company_id
类型:Many2one(res.company)。在多公司环境下,标识该产品归属的公司,影响可见性与库存归属等。
22. currency_id
类型:Many2one(res.currency)。list_price 与 standard_price 对应的货币,通常与公司货币一致,但价目表可作货币转换。
23. qty_available
类型:浮点。可用库存(实物库存),由底层的 stock.quant 计算得出,只读字段。仅对可存货类型有效,用于可用性检查与下单决策。
24. virtual_available
类型:浮点。预测可用量(当前库存 + 已入库 - 已出库),用于补货与采购建议,亦为只读计算字段。
25. product_template_attribute_value_ids
类型:Many2many。连接到定义变体的属性值(例如颜色=蓝、尺码=M),用于变体配置与筛选。
26. sequence
类型:整数。显示顺序控制字段,用于列表、配置器或展示时的排序,数值越小越靠前。
27. display_name
类型:字符。计算字段,用于生成带属性的展示名称,常用于 many2one 下拉和搜索结果显示,只读。
28. responsible_id
类型:Many2one(res.users)。产品负责人,用于补货规则、任务分配与内部追踪,可选字段。
产品模型在业务流程中的作用
销售与报价的使用场景
销售人员在创建报价单时直接选择 product.product 变体;该变体的 list_price、description_sale 与 uom_id 会自动带入到订单行。价目表可能会替换默认价格;只有 sale_ok 为 True 的商品才会在销售界面列出。
采购与供应商的使用场景
采购单与供应商发票同样引用 product.product,采购价通常会更新 standard_price。只有 purchase_ok 为 True 的商品才可被选为采购对象;uom_po_id 决定采购数量的单位(例如按箱采购)。
库存与仓储的使用场景
库存移动、拣货单与库存量计算都以 product.product 为基础。qty_available 与 virtual_available 决定能否拣货与补货;仅对可存货类型进行跟踪。扫码作业依赖 barcode 字段以提高仓库作业效率。
电商与网站的使用场景
网店页面展示的是 product.product 记录,变体作为可选项(如尺码、颜色)呈现。图片、描述与价格均来自这些字段,sale_ok 控制是否在前端可见。
制造与生产的使用场景
物料清单(BOM)既可引用组件的 product.product,也可指向成品。产品类型决定是否纳入生产计划;库存水平则影响排产与采购建议。
开发者如何扩展这个模型
开发者扩展的常用路径
模型继承机制
通过 _inherit = 'product.product' 拓展模型。你可以新增字段、重载方法或增加约束。把扩展放在独立模块内可以降低升级风险:若字段或逻辑是变体级别的,就放在 product.product;若是整个产品家族共享的属性,优先考虑放在 product.template。
新增字段的策略
在继承模型中定义新字段时,要选对字段类型(Char、Many2one、Boolean、Integer、Text、Selection 等),并判断该字段更适合放在模板层还是变体层。像 SKU、变体级条码这类属于单品的数据,应放在 product.product。
在 Python 层的扩展方式
可重载 create、write、unlink 等方法以加入自定义逻辑,记得调用 super() 保留原有行为。注意计算字段的依赖关系与缓存机制,product.product 上有大量由库存与销售模块驱动的计算字段,改动时需谨慎处理。
Odoo Studio 的使用场景
Odoo Studio 能让业务人员无代码添加字段,适合快速定制。但涉及复杂逻辑或需要长期维护的功能,建议走标准模块开发路线。product.product 的 API 在 XML-RPC/JSON-RPC 下是完全可用的,便于第三方集成。
实践中的最佳做法
- 在外部系统映射时,优先使用 default_code 或 barcode,这两个字段便于在接口中定位商品,务必保持唯一性与稳定性。
- 务必为每个商品设置正确的 type(Consumable/Service/Storable),因为类型会直接影响库存追踪、会计与业务流程。
- 在构建 API 或对接时,订单行与交易层面请引用 product.product;若是目录级别的批量操作或导入,优先操作 product.template。
- 为自定义字段命名时,使用 x_ 前缀或模块前缀以避免与未来 Odoo 版本冲突,降低升级风险。
- 若字段适用于同一模板下所有变体(例如品牌、长期关联分类),应将字段放在 product.template;只有在确有变体差异时,才放在 product.product。
常见误区与陷阱
- 在需要实现变体级别的逻辑时,优先继承 product.product;若逻辑本质是模板级别(即适用于所有变体),则继承 product.template 更合适。
- 避免直接在数据库手工创建变体记录。针对有属性组合的商品,应通过产品配置器或模板流程创建,以保证属性关系、属性值与计价规则的一致性。
- 典型错误一:忘记设置 sale_ok 或 purchase_ok,导致商品在销售或采购界面不可见。注意某些系统配置下默认值可能非预期。
- 典型错误二:重写核心方法却未调用 super(),这会破坏原有逻辑并影响其他模块或未来升级。始终保留对父类方法的调用。
- 典型错误三:在筛选或域(domain)中错误地使用 product.product,而应该基于 product.template(例如按类别过滤时),会导致查询不准确或性能问题。
总结:为什么要重视这个模型
小结:product.product 在 Odoo 的产品架构中占据核心地位。它承载了可售可购的实际商品记录。理解它与 product.template 的关系、关键字段及在各业务流程中的角色,将帮助你更稳健地配置、定制与对接 Odoo。
无论你是负责产品目录映射的顾问,还是做 Odoo 功能扩展的开发者,熟练掌握 product.product 都能显著降低实施风险并提升效率。
需要帮助实施 Odoo?
Dasolo 提供 Odoo 实施、定制与优化服务,专长包括 API 集成与 Odoo 开发。我们的团队对 Odoo 的数据架构与核心模型(如 product.product)有深入的实战经验。
如果你在 Odoo 实施、定制模块或系统集成上需要支持,我们可以提供专业协助。 预约示范演示 与我们讨论你的项目需求。