カスタム Odoo モジュールを構築する方法: OWL、ORM、継承に関する開発者ガイド
Odoo の 82 の公式モジュールと 40,000 を超えるコミュニティ モジュールでは正確なビジネス要件をカバーできない場合、カスタム モジュール開発がそのギャップを埋めます。このガイドでは、モジュール構造、OWL フロントエンド フレームワーク、ORM パターン、継承メカニズム、OCA (Odoo Community Association) ガイドラインに沿ったベスト プラクティスなど、2026 年の Odoo モジュール構築の基礎について説明します。
カスタム Odoo モジュールとは何ですか?
カスタム Odoo モジュール は、Python バックエンド ロジック、XML ビュー定義、JavaScript フロントエンド コンポーネント、および Odoo の機能を拡張するセキュリティ ルールの自己完結型パッケージです。モジュールは、まったく新しい機能を追加したり、既存の動作を変更したり、Odoo を外部システムと統合したりできます。 Odoo の各部分自体はモジュールであり、アーキテクチャは本質的に拡張可能です。
モジュールのディレクトリ構造
適切に構成されたモジュールは、次の標準構造に従います。
my_custom_module/
├── __init__.py # Python package init
├── __manifest__.py # Module metadata and dependencies
├── models/
│ ├── __init__.py
│ └── my_model.py # Business logic and data models
├── views/
│ ├── my_model_views.xml # Form, tree, and kanban views
│ └── menu.xml # Menu items and actions
├── security/
│ ├── ir.model.access.csv # Access control list
│ └── security.xml # Record rules and groups
├── data/
│ └── data.xml # Default data records
├── static/
│ └── src/
│ ├── js/ # OWL components
│ ├── css/ # Stylesheets
│ └── xml/ # QWeb templates
├── wizard/ # Transient models for wizards
├── reports/ # QWeb report templates
└── tests/ # Unit tests
マニフェストファイル
__manifest__.py ファイルはモジュールの ID を定義します。
{
'name': 'My Custom Module',
'version': '18.0.1.0.0',
'category': 'Custom',
'summary': 'Short description of what the module does',
'description': """
Long description with details about
features and configuration.
""",
'author': 'ECOSIRE',
'website': 'https://ecosire.com',
'license': 'LGPL-3',
'depends': ['base', 'sale', 'stock'],
'data': [
'security/ir.model.access.csv',
'views/my_model_views.xml',
'views/menu.xml',
'data/data.xml',
],
'assets': {
'web.assets_backend': [
'my_custom_module/static/src/js/**/*',
'my_custom_module/static/src/css/**/*',
'my_custom_module/static/src/xml/**/*',
],
},
'installable': True,
'application': False,
'auto_install': False,
}
バージョン規則: {odoo_version}.{major}.{minor}.{patch} (例: 18.0.1.0.0)。
ORM の操作
Odoo のオブジェクト リレーショナル マッピング (ORM) は、すべてのバックエンド開発の基礎です。モデルはデータベース テーブルにマップされ、ORM は CRUD 操作、計算フィールド、制約、およびワークフロー管理を提供します。
モデルの定義
from odoo import models, fields, api
class ProjectTask(models.Model):
_name = 'my_module.task'
_description = 'Project Task'
_order = 'priority desc, create_date desc'
name = fields.Char(string='Task Name', required=True)
description = fields.Html(string='Description')
state = fields.Selection([
('draft', 'Draft'),
('in_progress', 'In Progress'),
('done', 'Done'),
('cancelled', 'Cancelled'),
], default='draft', tracking=True)
assigned_to = fields.Many2one('res.users', string='Assigned To')
deadline = fields.Date(string='Deadline')
priority = fields.Selection([
('0', 'Normal'),
('1', 'Important'),
('2', 'Urgent'),
], default='0')
tag_ids = fields.Many2many('my_module.tag', string='Tags')
progress = fields.Float(compute='_compute_progress', store=True)
フィールドタイプのリファレンス
|フィールドの種類 | Python の種類 |使用例 | |---|---|---| |シャア | str |短いテキスト (名前、参照) | |テキスト | str |長いプレーンテキスト | | HTML | str |リッチテキストコンテンツ | |整数 |整数 |整数 | |フロート |フロート | 10 進数 | |ブール値 |ブール | True/False フラグ | |日付 |日付 |時間のない日付 | |日時 |日時 |日付と時刻 | |選択 | str |ドロップダウンの選択肢 | |メニーツーワン |整数 | 1 つのレコードへのリンク | |ワンツーメニー |リスト | Many2one の裏側 | |たくさんの2たくさん |リスト |複数のレコードへのリンク | |バイナリ |バイト |添付ファイル |
計算フィールドと制約
@api.depends('subtask_ids.state')
def _compute_progress(self):
for task in self:
total = len(task.subtask_ids)
done = len(task.subtask_ids.filtered(
lambda t: t.state == 'done'
))
task.progress = (done / total * 100) if total else 0
@api.constrains('deadline')
def _check_deadline(self):
for task in self:
if task.deadline and task.deadline < fields.Date.today():
raise ValidationError(
"Deadline cannot be in the past."
)
継承メカニズム
Odoo は 3 種類の継承を提供しており、それぞれ異なる目的を果たします。
1. クラスの継承(拡張)
フィールドを追加するかメソッドをオーバーライドして、既存のモデルを拡張します。これが最も一般的なパターンです。
class SaleOrderExtend(models.Model):
_inherit = 'sale.order'
custom_reference = fields.Char(string='Custom Ref')
approved_by = fields.Many2one('res.users')
def action_confirm(self):
# Add custom logic before standard confirmation
for order in self:
if order.amount_total > 10000 and not order.approved_by:
raise UserError("Orders over $10,000 require approval.")
return super().action_confirm()
2. プロトタイプの継承
既存のモデルからすべてのフィールドとメソッドをコピーする新しいモデルを作成します。
class CustomPartner(models.Model):
_name = 'my_module.partner'
_inherit = 'res.partner' # Copies structure
_description = 'Custom Partner'
3. 委任の継承
Many2one リンクを介して既存のモデルに委任する新しいモデルを作成します。親モデルのフィールドは子モデルに透過的に表示されます。
class LibraryMember(models.Model):
_name = 'library.member'
_inherits = {'res.partner': 'partner_id'}
partner_id = fields.Many2one('res.partner', required=True,
ondelete='cascade')
membership_date = fields.Date()
member_number = fields.Char()
OWL フレームワーク (フロントエンド)
Odoo 18はフロントエンドフレームワークとしてOWL(Odoo Web Library)を使用します。 OWL は React や Vue に似たコンポーネントベースのフレームワークですが、Odoo のニーズに合わせて特別に設計されています。
基本的なOWLコンポーネント
/** @odoo-module */
import { Component, useState } from "@odoo/owl";
import { registry } from "@web/core/registry";
class TaskDashboard extends Component {
static template = "my_module.TaskDashboard";
setup() {
this.state = useState({
tasks: [],
filter: 'all',
});
this.loadTasks();
}
async loadTasks() {
this.state.tasks = await this.env.services.orm.searchRead(
"my_module.task",
[["state", "!=", "cancelled"]],
["name", "state", "assigned_to", "deadline"]
);
}
get filteredTasks() {
if (this.state.filter === 'all') return this.state.tasks;
return this.state.tasks.filter(
t => t.state === this.state.filter
);
}
}
QWeb テンプレート (XML)
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="my_module.TaskDashboard">
<div class="o_task_dashboard">
<div class="task-filters">
<button t-on-click="() => state.filter = 'all'">All</button>
<button t-on-click="() => state.filter = 'in_progress'">
In Progress
</button>
</div>
<div class="task-list">
<t t-foreach="filteredTasks" t-as="task" t-key="task.id">
<div class="task-card">
<span t-esc="task.name"/>
</div>
</t>
</div>
</div>
</t>
</templates>
セキュリティ構成
すべてのモデルには明示的なアクセス ルールが必要です。これらがなければ、ユーザーはモデルのデータにアクセスできません。
アクセス制御リスト (ir.model.access.csv)
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_task_user,task.user,model_my_module_task,base.group_user,1,1,1,0
access_task_manager,task.manager,model_my_module_task,my_module.group_manager,1,1,1,1
レコード ルール (security.xml)
<record id="task_own_rule" model="ir.rule">
<field name="name">Own Tasks Only</field>
<field name="model_id" ref="model_my_module_task"/>
<field name="domain_force">
[('assigned_to', '=', user.id)]
</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>
モジュールをテストする
Odoo は、Odoo 固有のテスト クラスを備えた unittest フレームワークを使用した Python 単体テストをサポートしています。
from odoo.tests.common import TransactionCase
class TestTask(TransactionCase):
def setUp(self):
super().setUp()
self.task = self.env['my_module.task'].create({
'name': 'Test Task',
'state': 'draft',
})
def test_task_creation(self):
self.assertEqual(self.task.state, 'draft')
self.assertEqual(self.task.progress, 0)
def test_deadline_constraint(self):
with self.assertRaises(ValidationError):
self.task.write({
'deadline': fields.Date.subtract(
fields.Date.today(), days=1
),
})
odoo-bin -d test_db --test-enable -i my_custom_module --stop-after-init を使用してテストを実行します。
よくある質問
Q: カスタム Odoo モジュールの構築にはどのくらい時間がかかりますか? 単純なモジュール (新しいフィールド、基本ビュー) には 1 ~ 3 日かかります。中程度のモジュール (新しいモデル、ワークフロー、レポート) には 1 ~ 3 週間かかります。複雑なモジュール (マルチモデル システム、外部統合、カスタム OWL コンポーネント) には 4 ~ 12 週間かかります。カスタム モジュールが必要だが社内に Odoo 開発者がいない企業の場合は、当社のチームから 経験豊富な Odoo 開発者を雇用 してください。
Q: コアの Odoo コードを変更するか、別のモジュールを作成する必要がありますか? 必ず別のモジュールを作成してください。コア コードを変更すると、アップグレードが不可能になり、バージョン更新中にマージ競合が発生します。継承を使用して、カスタム モジュールから既存のモデルとビューを拡張します。
Q: OCA ガイドラインとは何ですか? Odoo Community Association (OCA) は、命名規則、ドキュメント要件、テスト カバレッジの期待、コード スタイル ルールなど、モジュールの品質に関するコーディング標準を発行しています。 OCA ガイドラインに従うことで、モジュールが保守可能であり、より広範なコミュニティ エコシステムと互換性があることが保証されます。
専門家の助けを得る
カスタム Odoo モジュールを構築するには、Python、JavaScript、PostgreSQL、および Odoo のフレームワーク規則に関する専門知識が必要です。単純なフィールド拡張が必要な場合でも、複雑なマルチモジュール システムが必要な場合でも、ECOSIRE の Odoo カスタマイズ サービス は、OCA 標準に基づいて構築された実稼働対応モジュールを提供します。
お問い合わせ してカスタム モジュールの要件について話し合い、開発の見積もりを取得してください。
執筆者
ECOSIRE Research and Development Team
ECOSIREでエンタープライズグレードのデジタル製品を開発。Odoo統合、eコマース自動化、AI搭載ビジネスソリューションに関するインサイトを共有しています。
関連記事
Amazon.de Odoo の統合: Odoo ERP を使用したドイツ最大のマーケットプレイスでの販売
ドイツ市場向けに Amazon.de を Odoo ERP と統合する方法。 FBA ドイツ、全ヨーロッパのフルフィルメント、ドイツの VAT、VerpackG コンプライアンス、決済調整をカバーします。
Odoo でドイツの e コマース市場に参入: 海外販売者向けのステップバイステップ ガイド
ドイツの電子商取引市場に参入する海外の販売者のための完全なガイド。市場分析、法的要件、VAT 登録、マーケットプレイスの選択、ドイツの消費者に販売するための Odoo ERP セットアップをカバーします。
Odoo を使用したドイツの e コマースの返品管理: 高収益市場向けの戦略
Odoo ERP を使用してドイツの高い e コマース返品率に対処する方法。 Zalando、Otto、Amazon.de、Kaufland の返品処理ワークフロー、理由コード分析、補充の自動化、マーケットプレイス固有のポリシーをカバーします。