はじめに
Odooではモデルがデータベース上のデータ構造を定義します。受注や在庫、商品といったビジネス情報はすべてモデルに格納され、アプリやレポートはその定義に従ってデータを読み書きします。
モデルの仕組みを理解することは、開発者だけでなく機能コンサルタントにも必須です。フィールドや関連、業務ロジックの土台がモデルであり、それらが正しく設計されているほどカスタマイズや保守が楽になります。
この記事はOdooで最も重要なモデルの一つであるproduct.productに焦点を当てます。カスタムモジュール作成、外部システム連携、商品カタログ設定などの場面で必ず触れるモデルです。
product.product モデルとは何か
product.productは実際に売買される“個別の品目(バリアント)”を表します。見積や発注、在庫移動に登場する具体的なアイテムはこのモデルのレコードです。
product.productはproduct.templateと役割が異なります。templateは製品ファミリーに共通する属性を保持し、product.productはそのテンプレートに紐づく具体バリアントです。バリアントがない単一商品ではテンプレートにつき1つのproduct.productが生成され、色やサイズなどの組み合わせがある商品は各組み合わせごとに個別レコードが作られます。
このモデルはproductモジュール内で定義され、販売・購買・在庫・Eコマースなど多くのアプリが参照します。見積に行を追加したり入庫処理を行うとき、実際にはproduct.productを操作しています。
product.productはproduct.templateからの委譲継承(delegation)を利用しており、共通フィールドはテンプレート側で管理され、バリアント固有の項目だけをvariant側に置ける設計です。これにより冗長を避けつつ個別の上書きが可能になります。
モデルの主要フィールド
ここからはproduct.productでよく使う代表的なフィールドを紹介します。これらを押さえておくとバリアント設計や連携がスムーズになります。
1. name
型: Char。バリアント名を保持します。一覧やフォーム、書類に表示され、単一商品ではテンプレート名と同じになりがちですが、バリアントでは属性を含めた表記になることがあります。
2. product_tmpl_id
型: Many2one (product.template)。バリアントと親テンプレートを結びつける中核の関係フィールドです。すべてのproduct.productは一つのproduct.templateに属します。テンプレート側を拡張したい場合、この関連を意識して実装します。
3. default_code
型: Char。社内コード(SKU)です。識別、バーコード検索、外部システム連携でよく使われ、バリアントごとに個別のコードを持たせられます。
4. barcode
型: Char。EANやUPCなどのバーコードを保持します。POSや倉庫でのスキャンに使われ、設定されると商品間で一意であるべきフィールドです。
5. create_date
型: Datetime。レコード作成日時。Odooが自動管理するため監査や期間集計に使えます。
6. write_date
型: Datetime。最終更新日時。こちらも自動管理され、データ更新の把握に便利です。
7. active
型: Boolean。論理削除フラグ。Falseにすると通常ビューから隠され履歴保持のために物理削除されません。
8. type
型: Selection。製品種別(消耗品/サービス/在庫品)。消耗品は在庫追跡されず、サービスは在庫が存在しません。在庫管理対象か否かで適用される業務フローが変わります。
9. categ_id
型: Many2one (product.category)。製品カテゴリ。レポート、価格ルール、カタログ整理に利用され、階層構造を持てます。
10. list_price
型: Float。販売価格。見積やEC表示の既定値で、顧客別価格や価格表で上書き可能です。
11. standard_price
型: Float。原価。在庫評価や粗利計算に使われ、通常は購買や手入力で更新します。
12. uom_id
型: Many2one (uom.uom)。販売・在庫の計量単位。個/kg/Lなど数量の表現を定義します。
13. uom_po_id
型: Many2one (uom.uom)。購買時の単位。販売単位と異なる場合があり(例: 箱で購入して個で販売)、自動換算されます。
14. description_sale
型: Html。販売用説明。見積書や受注票に表示され、リッチテキストで商品説明を充実させられます。
15. description_purchase
型: Html。購買用説明。発注書や仕入先請求書に表示され、社内や仕入先向けの指示を書きます。
16. sale_ok
型: Boolean。販売可否フラグ。Falseにすると販売やECで非表示になります。内部使用品や購買専用品の管理に便利です。
17. purchase_ok
型: Boolean。購買可否フラグ。Falseにすると購買側で選択できなくなります。製造専用や販売専用の品目管理に使います。
18. image_1920
型: Binary。高解像度の製品画像。Odooは複数サイズの画像(image_512、image_256等)を保持し、フォームやECで表示利用します。
19. weight
型: Float。重量。配送計算や物流で使われ、単位は会社設定に依存します。
20. volume
型: Float。容積。配送費や倉庫のスペース計算に使われ、容積制限のある業務では重要です。
21. company_id
型: Many2one (res.company)。多拠点・複数会社環境での所有会社を示します。可視性や在庫管理に影響します。
22. currency_id
型: Many2one (res.currency)。list_priceやstandard_priceの通貨。通常は会社通貨ですが、価格表で他通貨に変換されます。
23. qty_available
型: Float。在庫数(手持ち数)。stock.quantから計算される読み取り専用フィールドで、可用性チェックやレポートに用います。在庫追跡対象の製品にのみ意味があります。
24. virtual_available
型: Float。予測在庫(入庫予定−出庫予定を勘案)。補充判断や調達計画で参照する読み取り専用の計算フィールドです。
25. product_template_attribute_value_ids
型: Many2many。バリアントを定義する属性値(例: 色=青、サイズ=M)へのリンク。バリアントの組み合わせ管理や絞り込みに使います。
26. sequence
型: Integer。表示順。商品一覧やコンフィグレータでの並び替えに使い、数値が小さいほど前に表示されます。
27. display_name
型: Char。計算による表示名。名称と属性を組み合わせた形でmany2oneや検索結果に表示される読み取り専用フィールドです。
28. responsible_id
型: Many2one (res.users)。品目の担当者。再発注ルールや内部オーナー割当で利用する任意フィールドです。
業務フローでの使われ方
1. 販売と見積作成
営業が見積を作る際、カタログからproduct.productを選択します。list_price、description_sale、uom_idが注文行に引き継がれ、価格は価格表で上書きされることがあります。sale_okがTrueの製品のみ選択可能です。
2. 購買と仕入先管理
発注書や仕入請求はproduct.productを参照します。購買コストによりstandard_priceが更新され、purchase_okがTrueの製品が購買対象になります。uom_po_idは箱単位など購買数量の単位を定義します。
3. 在庫管理と倉庫処理
在庫移動・ピッキング・クアントはすべてproduct.productを基に動きます。qty_availableやvirtual_availableが可用性の判断材料になり、バーコードによる高速検索はbarcodeフィールドを利用します。在庫追跡はstorableタイプのみ対象です。
4. ECサイトとウェブ表示
ウェブショップはproduct.productを表示します。サイズや色といったバリアントはオプションとして扱われ、画像・説明・価格はモデルのデータから読み込まれます。sale_okでEC上の表示有無をコントロールします。
5. 製造(MRP)
部品表は構成品や製品に対してproduct.productを参照します。typeフィールドで製造対象か消耗品かが決まり、在庫数が生産計画に影響します。
開発者がこのモデルを拡張する方法
開発者は複数の方法でproduct.productを拡張できます。Odooのモデル継承が主要な手段です。
モデル継承の使い分け
_modelで_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を使えばコードを書かずにフィールド追加が可能で、素早いカスタマイズに便利です。ただし複雑なロジックや将来のバージョン対応を考えると、保守性の高いカスタムモジュールで実装する方が安全です。APIはXML-RPC/JSON-RPCで公開されており外部連携も容易です。
実務でのベストプラクティス
- 外部連携ではdefault_codeやbarcodeをキーとしてマッピングしてください。これらは一貫してユニークに管理することが重要です。
- 各商品に対してtypeを正しく設定してください。消耗品・在庫品・サービスの違いにより適用されるプロセスが変わります。
- API連携では注文行などトランザクション系はproduct.productを用い、カタログ一括操作やテンプレート単位の処理はproduct.templateを使うのが適切です。
- カスタムフィールドは将来の競合を避けるために
x_プレフィックスやモジュール固有のプレフィックスを付けることを推奨します。 - 全バリアントに共通する情報(ブランドやカテゴリ)はproduct.templateに、バリアントごとに異なるデータ(個別バーコードなど)はproduct.productに配置するのが設計上の基本です。
よくある失敗例
- バリアント固有のロジックを実装する際はproduct.productを継承し、テンプレート単位の振る舞いならproduct.templateを検討してください。
- バリアントを手動で個々に作成する代わりに、コンフィグレータを使ってテンプレートからバリアントを生成するのが一般的で、整合性と仕組みの維持が楽になります。
- sale_okやpurchase_okの設定忘れに注意してください。設定次第で販売・購買画面に表示されないことがあります。
- super()を呼ばずにコアメソッドを上書きしてしまうと、他のモジュールや将来のアップグレードで不具合が発生するリスクがあります。
- テンプレートでフィルタすべき場面でproduct.productを使うなど、適切なモデルを使い分けないと検索やドメイン条件で誤動作します。
まとめ
product.productはOdooの製品設計の中核です。実際に売買されるアイテムを表し、product.templateとの関係を理解することで設定・カスタマイズ・連携がスムーズになります。
機能コンサルタントがカタログを設計する場合も、開発者がカスタムモジュールを作る場合も、product.productを正しく把握しておくと時間を節約しミスを減らせます。
Odoo導入でお困りですか?
Dasoloは企業のOdoo導入・カスタマイズ・最適化を支援します。API連携や開発を得意とし、product.productのようなコアモデルに関する実務経験が豊富です。
Odooの導入支援、カスタムモジュール作成、外部連携でお困りでしたらお気軽にご相談ください。 デモを予約する プロジェクトについてご相談しましょう。