odoo-report について
Odoo 14~19 のメールテンプレートと QWeb レポートを扱う開発者向けスキルです。作成、デバッグ、検証、プレビュー、バージョンに応じた移行を支援し、レンダリングや PDF レポートの指針も示します。
主な機能
- 01メールテンプレートの作成と分析
- 02QWeb PDF レポートの作成
- 03レンダリングとテンプレートエラーのデバッグ
- 04テンプレートの検証とプレビュー
- 05Odoo バージョン間のテンプレート移行
- 06バージョン別レンダリングの指針
活用シーン
- 01見積書メールテンプレートの作成
- 02購買オーダーの PDF レポート作成
- 03メールがプレーンテキストになる原因の調査
- 04異なる Odoo バージョン間でのテンプレート移行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ahmed-lakosha/ odoo-plugins --skill odoo-reportインストール後、Claude Code で/odoo-reportを入力して読み込まれたか確認します。
詳細
Odoo メールテンプレートと QWeb レポートのスキル(v2.1)
Odoo のバージョン 14〜19 に対応した、メールテンプレートと QWeb レポートの作成、管理、デバッグ、移行を行うスキルです。
ワークフロー
このスキルでは、自然言語を使ってテンプレートとレポートに関するすべてのワークフローに対応します。
| 実行したいこと | 入力する内容 |
|---|---|
| メールテンプレートを作成する | 「sale.order の見積もり用メールテンプレートを作成して」 |
| QWeb PDF レポートを作成する | 「purchase.order 用の QWeb PDF レポートを作成して」 |
| テンプレートを移行する | 「このテンプレートを Odoo 14 から 17 に移行して」 |
| テンプレートを分析する | 「このテンプレートの問題点を分析して」 |
| レンダリングをデバッグする | 「メールがプレーンテキストで表示される理由をデバッグして」 |
| テンプレートを修正する | 「壊れた QWeb 式を修正して」 |
| デプロイ前に検証する | 「デプロイ前にこのテンプレートを検証して」 |
| テンプレートを一覧表示する | 「sale.order のテンプレートをすべて一覧表示して」 |
| 出力をプレビューする | 「このメールテンプレートをプレビューして」 |
設定
- 対応バージョン:Odoo 14、15、16、17、18、19
- コアモデル:
mail.template - レンダリングエンジン:ヘッダーには inline_template(Jinja2 に似た構文)、body_html には QWeb
ユーザーによる上書き設定:プロジェクトの .claude/ ディレクトリに odoo-report.local.md があるか確認してください。見つかった場合は、その YAML フロントマターの設定(default_version、author、default_layout)をデフォルトとして使用します。
テンプレートのアーキテクチャ
mail.template
├── Inherits: mail.render.mixin (rendering engine)
├── Inherits: template.reset.mixin (reset - Odoo 16+)
│
├── Header Fields (inline_template engine):
│ subject, email_from, email_to, email_cc, reply_to, partner_to
│
├── Content Fields (QWeb engine):
│ body_html
│
├── Attachment Fields:
│ attachment_ids (static)
│ report_template (Odoo 14-16) / report_template_ids (Odoo 17+)
│ report_name (dynamic filename)
│
└── Configuration:
email_layout_xmlid, auto_delete, mail_server_id,
use_default_to, scheduled_date, template_category (16+)
レンダリングフロー
mail.template.send_mail_batch(res_ids)
├─► _generate_template(res_ids, render_fields)
│ ├─► _classify_per_lang()
│ ├─► _render_field() per field (inline_template or qweb)
│ ├─► _generate_template_recipients()
│ ├─► _generate_template_attachments() (static + PDF report)
│ └─► Return rendered values dict
├─► Create mail.mail records
├─► Apply email_layout_xmlid (if set)
└─► Send via mail_server_id or default
2 つのレンダリングエンジン
1. インラインテンプレート(Jinja2 に似た構文)
使用対象:subject、email_from、email_to、email_cc、reply_to、partner_to、lang、scheduled_date
{{ object.name }}
{{ object.partner_id.name }}
{{ (object.user_id.email_formatted or user.email_formatted) }}
{{ object.state == 'draft' and 'Quotation' or 'Order' }}
{{ ctx.get('proforma') and 'Proforma' or '' }}
2. QWeb エンジン
使用対象:body_html
<t t-out="object.name"/>
<t t-out="format_amount(object.amount_total, object.currency_id)"/>
<t t-if="object.state == 'draft'">Draft</t>
<t t-elif="object.state == 'sent'">Sent</t>
<t t-else="">Confirmed</t>
<t t-foreach="object.order_line" t-as="line">
<tr><td t-out="line.name"/></tr>
</t>
<a t-att-href="object.get_portal_url()">View</a>
バージョン判定マトリクス
| 機能 | 14 | 15 | 16 | 17 | 18 | 19 |
|---|---|---|---|---|---|---|
| 出力タグ | t-esc | t-out | t-out | t-out | t-out | t-out |
report_template(M2O) | Y | Y | Y | - | - | - |
report_template_ids(M2M) | - | - | - | Y | Y | Y |
template_category | - | - | Y | Y | Y | Y |
| 会社のブランディングカラー | - | - | - | - | - | Y |
format_datetime() | - | Y | Y | Y | Y | Y |
is_html_empty() | - | - | Y | Y | Y | Y |
バージョンの検出優先順位
- ユーザーが指定した
--versionフラグ - ディレクトリパス(
odoo14、odoo17など) __manifest__.pyのバージョン文字列(例:'17.0.1.0.0')- 特定できない場合はユーザーに確認する
メールレイアウトテンプレート
| レイアウト | 幅 | 用途 |
|---|---|---|
mail.mail_notification_layout | 900px | ヘッダーとフッターを含む完全な通知 |
mail.mail_notification_light | 590px | シンプルな通知 |
mail.mail_notification_layout_with_responsible_signature | 900px | レコードの user_id の署名を使用(16 以降) |
ベストプラクティス
1. 常にフォールバックを使用する
<t t-out="object.partner_id.name or 'Valued Customer'"/>
2. 書式設定ヘルパーを使用する
<t t-out="format_amount(object.amount_total, object.currency_id)"/>
<t t-out="format_date(object.date_order)"/>
3. 一貫性を保つためにレイアウトを使用する
<field name="email_layout_xmlid">mail.mail_notification_layout</field>
4. 空の HTML を処理する(16 以降)
<t t-if="not is_html_empty(object.description)">
<div t-out="object.description"/>
</t>
5. バージョンに適した出力を使用する
<t t-out="value"/>
<t t-esc="value"/>
6. バージョンに応じてレポートを添付する
<field name="report_template" ref="module.report_action"/>
<field name="report_template_ids" eval="[(4, ref('module.report_action'))]"/>
7. 互換性のためにメールテーブルを使用する
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr><td style="padding: 20px;">Content</td></tr>
</table>
8. 動的なファイル名を安全に扱う
<field name="report_name">{{ (object.name or 'Document').replace('/', '-') }}</field>
wkhtmltopdf(PDF レポートに必須)
インストール
# Windows
winget install wkhtmltopdf.wkhtmltox
# Ubuntu/Debian
sudo apt-get install wkhtmltopdf
# macOS
brew install wkhtmltopdf
Odoo の設定(必須)
[options]
bin_path = C:\Program Files\wkhtmltopdf\bin # Windows
# bin_path = /usr/local/bin # Linux
重要な制限事項:オフラインモード
wkhtmltopdf はネットワークにアクセスせずに実行されます。
- Google Fonts CDN は読み込まれません
- 外部画像はレンダリングされません
- フォントには
web.external_layoutを使用してください - システムフォントを使用してください:
'DejaVu Sans', 'Arial', sans-serif
よくあるエラー
| エラー | 原因 | 解決方法 |
|---|---|---|
Unable to find Wkhtmltopdf | bin_path が設定されていない | odoo.conf に bin_path を追加する |
| PDF の生成がタイムアウトする | 外部リソースが要求された | CDN URL を削除する |
| 空の PDF が生成される | CSS/SCSS のエラー | SCSS の構文を検証する |
| コード 1 で終了する | HTML の構文エラー | QWeb XML を検証する |
アラビア語/RTL のサポート
ラテン文字以外のテキストに必須のテンプレートラッパー
<template id="report_document">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
</div>
</t>
</t>
</t>
</template>
web.html_container を使用しないと、アラビア語のテキストは ÙØ§ØªÙˆØ±Ø©(UTF-8 のバイト列が Latin-1 として読み取られた状態)と表示されます。
2 言語のラベル
<th style="background: #1a5276; color: white; padding: 12px;">
Date | التاريخ
</th>
RTL の配置
<div style="direction: rtl; text-align: right;">
يرجى إرسال حوالاتكم على الحساب المذكور أعلاه
</div>
レポートの SCSS スタイル設定
アセットバンドル
'assets': {
'web.report_assets_common': [
'module/static/src/scss/report_styles.scss',
],
},
Google Fonts の落とし穴
// BROKEN - Semicolons in URL break SCSS parsing
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
// FIXED - Use weight range syntax
@import url('https://fonts.googleapis.com/css2?family=Poppins:[email protected]&display=swap');
// BEST - Don't use Google Fonts (wkhtmltopdf is offline!)
推奨フォントスタック
$report-font-family: 'DejaVu Sans', 'Arial', 'Helvetica', sans-serif;
用紙形式の設定
<record id="paperformat_custom" model="report.paperformat">
<field name="name">Custom A4</field>
<field name="format">A4</field>
<field name="orientation">Portrait</field>
<field name="margin_top">20</field>
<field name="margin_bottom">20</field>
<field name="margin_left">15</field>
<field name="margin_right">15</field>
<field name="header_line" eval="False"/>
<field name="dpi">90</field>
</record>
レポートへのリンク:<field name="paperformat_id" ref="module.paperformat_custom"/>
| 形式 | 寸法 | 用途 |
|---|---|---|
| A4 | 210 x 297 mm | 国際標準 |
| Letter | 216 x 279 mm | 米国標準 |
| Legal | 216 x 356 mm | 法的文書 |
| 横向き | 任意 + Landscape | 横長の表、グラフ |
デバッグのワークフロー
レポートやテンプレートの問題を診断する際は、次の順序で確認してください。
- インフラストラクチャ:wkhtmltopdf はインストールされていますか? odoo.conf の bin_path は設定されていますか? サーバーは再起動されていますか?
- テンプレートの構造:web.html_container → web.external_layout → div.page になっていますか?
- レポートアクション:report_name はテンプレート ID と一致していますか? binding_model_id は正しいですか?
- シェルでのテスト:
env.ref('module.report_action')._render_qweb_pdf([record_id]) - ブラウザーのキャッシュ:キャッシュをクリアします(Ctrl+Shift+R)
参照ファイル
特定のタスクに取り組む際は、詳しい情報を得るためにプラグインディレクトリから次のファイルを参照してください。
テンプレートの作成
- 目的/モデル別のパターン選択:
memories/template_patterns.md - メールのスターター XML:
templates/email/basic_notification.xml、templates/email/document_email.xml - レポートのスターター XML:
templates/qweb/basic_report.xml、templates/qweb/table_report.xml - フィールド定義:
data/template_fields.json - バージョン別のコンテキスト変数:
data/context_variables.json - レイアウトオプション:
data/layouts.json
バージョンの判断
- バージョンのルーティングルールと移行パス:
memories/version_routing.md - バージョン検出ロジックと機能マップ:
helpers/version_helper.md
検証
- 事前検証チェックリスト:
validators/template_validator.md
QWeb の品質
- 安全性、パフォーマンス、メール/レポートのガイドライン:
memories/qweb_best_practices.md
モジュール固有のテンプレート
- モジュール別の既知の Odoo テンプレート ID:
data/module_templates.md
移行リファレンス
自動変換
| 移行元 → 移行先 | 変換 |
|---|---|
| 14 → 15+ | t-esc → t-out、t-raw → t-out |
| 14-16 → 17+ | report_template → report_template_ids に eval="[(4, ref(...))]" を設定 |
| 任意 → 16+ | template_category フィールドを追加 |
| 任意 → 19 | 会社のブランド設定を追加:company.email_secondary_color、company.email_primary_color |
移行ワークフロー
- 移行元のバージョンを検出します(構文のヒューリスティックまたはディレクトリ名)
- バックアップを作成します:
{file}.bak - 変換を順番に適用します
- 移行後の XML を検証します
- 差分の概要を表示します
完全な移行マトリックスとルールについては、memories/version_routing.md を参照してください。
よくあるエラー
| エラー | 原因 | 解決策 |
|---|---|---|
AttributeError: 'NoneType' has no attribute 'name' | NULL フィールドへのアクセス | object.field.name or '' を使用します |
QWebException: t-esc is deprecated | 15+ で古い構文を使用 | t-esc を t-out に置き換えます |
KeyError: 'format_amount' | コンテキストヘルパーが不足 | mail.render.mixin が継承されていることを確認します |
ValidationError: Invalid XML | QWeb の形式が不正 | タグの閉じ忘れを確認します |
アラビア語のテキストが ÙØ§ØªÙˆØ±Ø© と表示される | web.html_container が不足 | UTF-8 ラッパーを追加します |
| PDF が空白 | wkhtmltopdf が見つからない、または CSS エラー | bin_path を確認し、SCSS を検証します |