odooのPDF帳票で「奈良県葛城市」を出力する

# 地名や人名の異体字

東京都葛飾区の「葛」と奈良県葛城市の「葛」とでは、字形が異なっているそうです。行政実務や冠婚葬祭の案内状などでは、これらを正確に表したいところですが、コンピュータの一般的なフォントでは、これらを区別できませんでした。

**東京都葛飾区の「葛」と奈良県葛城市の「葛」**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/faf73492-7cbc-d4c6-893d-e40ac94b438c.png)

https://moji.or.jp/mojikiban/aboutivs/

行政実務における人名の記載を主な目的とし、これらの字形の差異を区別しているのが、**IPAmj明朝フォント**です。

# odooの帳票出力エンジンと問題点

odooでは、[QWeb Reports](https://www.odoo.com/documentation/master/developer/reference/backend/reports.html)を使ってHTML帳票やPDF帳票を出力できます。標準で`Odoo Unicode Support Noto`フォントがCSSによりfont-familyとして指定されていますので、漢字やかなの出力も可能です。
しかし、異体字（IVS）を含むと、PDF帳票で縮退文字＋空白文字に文字化けして出力されてしまいます。
これは、odoo内部で[wkhtmltopdf](https://wkhtmltopdf.org/)を使ってhtmlからpdfに変換しており、この[wkhtmltopdf](https://wkhtmltopdf.org/)がIVSに対応していないことが理由であると考えられます。

# OCAのreporting-engine - Py3o Reporting Engine

[OCA(Odoo Community Association)](https://odoo-community.org/)の有志によって、 **[OCA/reporting-engine](https://github.com/OCA/reporting-engine)** が公開されており、その中に、[LibreOffice](https://ja.libreoffice.org/)をベースとしたレポートエンジンである **[Py3o Reporting Engine(report_py3o)](https://github.com/OCA/reporting-engine/tree/16.0/report_py3o)** が含まれています。
[LibreOffice](https://ja.libreoffice.org/)自体は、IVSに対応していますので、**IPAmj明朝フォント**を使って異体字でも正常にpdf帳票として出力できます。

## インストール - Py3o Reporte Engine(report_py3o)

[report_py3oのインストール](https://github.com/OCA/reporting-engine/blob/16.0/report_py3o/README.rst#installation)を参考に次のアプリやモジュール等をインストールします。

- [LibreOffice](https://ja.libreoffice.org/) アプリケーション
- [py3o.template](https://pypi.org/project/py3o.template/) と [py3o.formats](https://pypi.org/project/py3o.formats/) ライブラリ
- [report_py3o](https://github.com/OCA/reporting-engine/tree/16.0/report_py3o) モジュール
- [IPAmj明朝フォント](https://moji.or.jp/mojikiban/font/)

https://github.com/OCA/reporting-engine/tree/16.0/report_py3o

**LibreOffice アプリケーション**
```bash
sudo apt-get -y install --no-install-recommends libreoffice
```

**py3o.template と py3o.formats ライブラリ**
```bash
sudo pip3 --disable-pip-version-check --no-cache-dir install --upgrade py3o.template py3o.formats
```

**report_py3o モジュール**
```bash
cd /opt/odoo
git clone --branch=16.0 --depth=1 https://github.com/OCA/reporting-engine.git oca/reporting-engine
```

`oca/reporting-engine` のパスを `odoo.conf` に追記します。
```ini:/etc/odoo/odoo.conf
[options]
:
addons_path = /opt/odoo/odoo/odoo/addons,/opt/odoo/odoo/addons,/opt/odoo/oca/reporting-engine
:
```

**IPAmj明朝フォント**
```bash
# ローカルにインストール
mkdir -p ~/.local/share/fonts

# IPAmj明朝フォント
curl -o ipamjm00601.zip -sSL https://dforest.watch.impress.co.jp/library/i/ipamjfont/10750/ipamjm00601.zip
unzip ipamjm00601.zip -d ~/.local/share/fonts/ipamjm0601

# キャッシュ
fc-cache -vf
fc-list | grep ipa
```

:::note warn
**IPAmj明朝フォントのインストール先**
LibreOfficeからフォントを検索・取得できるように `~/.local/share/fonts/` 内にインストールします。
:::

## 有効化 - Py3o Reporte Engine(report_py3o)

odooサーバーを起動（再起動）し、 **Apps** で **Py3o Reporte Engine(report_py3o)** モジュールを **有効化(ACTIVATE)** します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/2afd41c8-6822-90ea-4951-aaa665386172.png)

# Py3o帳票テンプレートのサンプル

[Sample py3o report templates](https://github.com/akretion/odoo-py3o-report-templates) プロジェクトで、 **Py3o Reporte Engine** を使った **Py3o帳票テンプレート** のサンプルが公開されています。
ここでは、その中の **[Sale Report Py3o(sale_report_py3o)](https://github.com/akretion/odoo-py3o-report-templates/tree/16.0/sale_report_py3o)** モジュールを **有効化(ACTIVATE)** して、帳票の出力を確認してみます。

## サンプルモジュールと依存モジュールのインストール

**[Sale Report Py3o(sale_report_py3o)](https://github.com/akretion/odoo-py3o-report-templates/tree/16.0/sale_report_py3o)** モジュールは、いくつかの外部モジュールに依存していますので、それらも一緒にインストールします。

```bash
cd /opt/odoo/oca
export ODOO_VERSION="16.0"

git clone --branch=${ODOO_VERSION} --depth=1 https://github.com/akretion/odoo-py3o-report-templates

git clone --branch=${ODOO_VERSION} --depth=1 https://github.com/akretion/odoo-usability
git clone --branch=${ODOO_VERSION} --depth=1 https://github.com/OCA/bank-payment
git clone --branch=${ODOO_VERSION} --depth=1 https://github.com/OCA/sale-workflow
git clone --branch=${ODOO_VERSION} --depth=1 https://github.com/OCA/server-tools

sudo pip3 --disable-pip-version-check --no-cache-dir install --upgrade astor

```

プロジェクト（モジュール）のパスを `odoo.conf` に追記します。
```ini:/etc/odoo/odoo.conf
[options]
:
addons_path = /opt/odoo/odoo/odoo/addons,/opt/odoo/odoo/addons,/opt/odoo/oca/reporting-engine
    ,/opt/odoo/oca/odoo-py3o-report-templates
    ,/opt/odoo/oca/odoo-usability
    ,/opt/odoo/oca/bank-payment
    ,/opt/odoo/oca/sale-workflow
    ,/opt/odoo/oca/server-tools
:
```

## 有効化 - Salesアプリ と Sale Report Py3oモジュール

odooサーバーを起動（再起動）し、 **Apps** で **Sales** アプリと **[Sale Report Py3o(sale_report_py3o)](https://github.com/akretion/odoo-py3o-report-templates/tree/16.0/sale_report_py3o)** モジュールとを **有効化(ACTIVATE)** します。

## Salesアプリの帳票出力

**Sales** アプリでデータの `S000003` を開き、 `Print` で、 `Quotation / Order` を選択すると ODT形式の **`Quotation - S00003.odt`** が出力されます(ダウンロード)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/3aacc4ef-5d76-f2ea-3ad1-ded879e2582a.png)

# Sales帳票のPDF帳票化（IPAmj明朝フォントの埋め込み）

`Quotation / Order` 帳票の一部のデータ項目を **IPAmj明朝フォント** に変更し、帳票をPDF形式で出力してみます。尚、出力されたPDF形式ファイルには、 **IPAmj明朝フォントが埋め込まれます。**

## ODTテンプレートの編集

`Quotation / Order` 帳票のODTテンプレートは、次のファイルです。
```
odoo-py3o-report-templates/sale_report_py3o/sale_order.odt
```
このファイルを **LibreOffice** で開き、例えば、 **「Invoice Address」** の **データ項目** (`[partner_invoice_id]`)のフォントを **IPAmj明朝** に変更し、ファイルを保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/cbec1132-6216-c62c-80cc-3641238a016c.png)

:::note warn
**アジア諸言語用フォント**の変更

サンプルのテンプレートファイルは、言語が `フランス語` で作成されており、アジア諸言語用フォントに `Noto Sans CJK SC Regular` が指定されています。
**西洋諸言語用フォント** と **アジア諸言語用フォント** との両方に **`IPAmj明朝`** フォントを指定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/97346ede-00a9-f01d-8a31-1ae814d7b621.png)

:::

## PDF形式への切り替え

`odoo-py3o-report-templates/sale_report_py3o/report.xml` ファイルで、 **レポートの出力形式(`py3o_filetype`)** を **odt** から **pdf** に変更し、モジュールをアップグレードすると、 `Print` の `Quotation / Order` で、PDF形式の **`Quotation - xxxxxx.pdf`** が出力されます。

**変更： `<field name="py3o_filetype">pdf</field>`**

```xml:sale_report_py3o/report.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>

...

<record id="sale.action_report_saleorder" model="ir.actions.report">
    <field name="report_type">py3o</field>
    <!--
    <field name="py3o_filetype">odt</field>
    -->
    <field name="py3o_filetype">pdf</field>
    <field name="module">sale_report_py3o</field>
    <field name="py3o_template_fallback">sale_order.odt</field>
    <!--
    <field name="py3o_server_id" ref="local_py3o_server"/>
    <field name="py3o_filetype">pdf</field>
    <field name="print_report_name">object.name + '-' + object.date_order.strftime('%Y-%m-%d') + '-' + object.commercial_partner_id.name.replace(' ', '_') + '.pdf'</field>
    -->

</record>

...

</odoo>
```

## 異体字を含む地名の登録とPDF帳票出力

**Sales** アプリを開き、Salesデータの住所を **`奈良県葛城市`** として登録します。
**「葛󠄂」** の文字は、[MJ022335](https://moji.or.jp/mojikibansearch/info?MJ%E6%96%87%E5%AD%97%E5%9B%B3%E5%BD%A2%E5%90%8D=MJ022335) のページを開き、 **コピーフィールド** から文字をコピーしてペーストします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/9449280a-0ae6-96a3-17bc-eb9a147bd37e.png)

**【出力結果】**
`Print` の `Quotation / Order` で、PDF形式の **`Quotation - xxxxxx.pdf`** が出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/0d6a6186-0225-40d2-d789-2a450541695b.png)

:::note info
**IPAmjMincho(埋め込みサブセット)**
Acrobat Reader 等のPDFビューワーで開き、文書のプロパティを確認すると、 **`IPAmjMincho` フォントが埋め込まれている** ことがわかります。
フォントが埋め込まれているため、 **IPAmj明朝フォント** が **インストールされていないデバイス** でこのPDFファイルを開いても、この字形で正しく表示出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/b8bd3f98-2bd1-abd7-c8d2-377c5137ff30.png)
:::

# おわりに

odooサーバーに **Py3o Reporte Engine** をインストールし、異体字を含む **「奈良県葛城市」** のデータをPDF帳票として出力しました。
また、出力されたPDFファイルには、 **IPAmj明朝フォント** が埋め込まれていることを確認しました。