壊れないカスタマイズ
ERPNextは「カスタマイズするとアップデートできない」というERPあるあるを解決します。本体は常に最新、カスタムは独立して残せる。その技術的仕組みを解説します。
本記事の内容は以下の環境で検証しています。環境差による挙動の違いにご注意ください。
• ERPNext: v15.75.1 (version-15)
• Frappe Framework: v15.77.0 (version-15)
• Bench: v5.x
• Database: MariaDB 10.x
• OS: Ubuntu 22.04 LTS (64bit)
ERPNextの柔軟な拡張機能
ERPを導入する技術者にとって、最大の不安材料のひとつは 「カスタマイズを入れるとバージョンアップできなくなる」 ことです。
ERPNextは、この問題をHookとOverWrideの2つの仕組みで、設計レベルから解決しています。
- HOOK = 標準機能コードの実行タイミングに、カスタムの処理を差し込める仕組み!
- ソース = 標準側のソースは触らない!カスタムのソースは独立したファイルに配置する!
- Override = 必要な処理だけ標準機能を差し替えて、カスタムの処理を実行する!
1. バージョンアップに耐えられるERPNextの設計思想
ERPNextの「壊れないカスタマイズ」は、次の5つの仕組みによって支えられています。
どれも実際に導入支援をしていると「効いているな」と感じる部分です。
① 責務の分離
ERPNext では「本体」と「カスタマイズ」をはっきり分けて管理できる仕組みが標準で用意されています。
カスタマイズを追加するための 専用の領域 が最初から設けられており、そこに置いたアプリやフィールドは、あたかも標準機能の一部のように自然に動作します。しかもこの領域はコアとは独立しているため、本体コードを一切書き換える必要がありません。
さらに Hook 機構を通じて「どのイベントで処理を差し込むか」「どの関数を上書きするか」が公式に定義されているので、単なるアドオンにとどまらず、既存の処理を安全にオーバーライドすることまで可能です。
この設計思想のおかげで、手軽にカスタマイズを加えつつ、本体を最新の状態に保つことができるのです。
② DBスキーマの工夫
ERPNext では、コアの DB テーブルに物理カラムを直接追加することはありません。 代わりに、カスタム項目は tabCustom Field という専用テーブルに「メタ情報」として保存されます。
この仕組みにより、コア側のマイグレーションで新しいカラムや制約が追加されても、 カスタム項目が衝突することはなく、アップデート後にエラーが発生しにくい設計になっています。
他のERPでは「DBを直接触ったせいでアップデートで壊れる」というのが日常茶飯事ですが、
ERPNext では構造的にそのリスクを避けられるのです。これ、かなり安心感がありますよね。
凄くないですか???
③ Hook機構
カスタマイズ時、コアのソースを修正する必要はなく、hooks.py
でイベントやメソッドを上書きします。
これは、公式に用意されたAPIを使うため非常に安全です。
つまり「裏技」ではなく「正規ルート」でカスタマイズが保障されており、将来の互換性を損ないません。
④ Export/Importの標準化
bench export-fixtures
で上記のカスタムフィールドや追加DBテーブルをJSON化可能です。
CI/CDに組み込みやすく、テスト環境と本番の差異を減らせます。
経験上「本番と開発の差分が分からない」という混乱はERP導入でよくある落とし穴ですが、ERPNextは標準でそれを防ぐ仕組みを持っています。
⑤ Gitによるバージョン管理
ERPNextとカスタムは別Gitリポジトリで管理します。
衝突が起きるのは自分のアプリの中だけです。
つまり「アップデートで本体と自作コードがぐちゃぐちゃに衝突する」心配はなく、Gitフローを理解していればチーム開発でも安心です。
2. カスタマイズの4レイヤー
ここからは、具体的なカスタマイズ方法を解説します。
カスタマイズは、4段階に分けることができます。
1. カスタムフィールド
ERPNext では、管理画面からカスタムフィールドを簡単に追加できます。
マウス操作だけで、テキストの入力欄や表示形式、プルダウンリスト、チェックボックスなどを自由に設定できます。
データベースには tabCustom Field
として自動で登録され、コアテーブルを直接改変しないため、アップデート時の衝突リスクを避けられる仕組みになっています。
操作も直感的で簡単です。
2. クライアントスクリプト
画面上のイベントは Custom Script でフック可能です。
例えば「受注フォームで商品を選択した際に、自動的に在庫数を表示する」といった動作を簡単に実現できます。
// client_script.js
frappe.ui.form.on("Sales Order Item", {
item_code(frm, cdt, cdn) {
frappe.call({
method: "my_custom_app.api.get_stock_balance",
args: { item_code: locals[cdt][cdn].item_code },
callback: r => frappe.msgprint(`在庫数: ${r.message}`)
});
}
});
現場感覚で言えば、これは「ちょっとした自動化」をノーコードに近い形で素早く組み込めるレイヤーだと言えます。
AI活用のポイント
いまは ChatGPT に 「Sales Order Item の item_code
変更時に在庫数を表示する Client Script を書いて」 と伝えるだけで、ひな形コードを即座に出してくれます。
そのまま動くレベルのものも多く、あとは自社ルールに合わせて微調整するだけ。 ERPNext はオープンソースなので API・DocType・イベント名・実装例が公開されており、 AI が内部仕様を前提に「正しいコード」を提案しやすい点が強みです。 これはクローズドERPには真似できない利点です。
3. カスタムフォーム・印刷フォーマット
フォームや印刷レイアウトは JSON 形式で保存されるため、開発環境から本番環境への エクスポート/インポート が容易です。 特に日本の業務では請求書・見積書のフォーマットが重要ですが、 ERPNext では自由に追加・編集が可能です。現場で「お客様指定の帳票フォーマットに合わせたい」といった要望にも柔軟に対応できます。
4. カスタムアプリ
さらに高度な拡張が必要な場合は、bench new-app my_custom_app
で独立したアプリを作成します
この方法では ERPNext 本体を一切変更せず、追加アプリ側で処理を「差し替える」ように動かせるため、バージョンアップ時の不具合をほぼ確実に回避できます。
例えば、受注から納品書を作成する標準メソッドを差し替える場合は、以下のように hooks.py にOverrideする宣言を記述し、overrides.make_delivery_noteにアドオン機能を記述します。
# hooks.py
override_whitelisted_methods = {
"erpnext.selling.doctype.sales_order.sales_order.make_delivery_note":
"my_custom_app.overrides.make_delivery_note"
}
# my_custom_app/overrides.py
import frappe
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note as erpnext_make_delivery_note
def make_delivery_note(source_name, target_doc=None):
"""
カスタムメッセージをログに出力
"""
# --- 標準の処理を呼び出し ---
delivery_note = erpnext_make_delivery_note(source_name, target_doc)
# --- カスタム処理を追加 ---
# 独自フィールドに値をコピー
sales_order = frappe.get_doc("Sales Order", source_name)
if hasattr(delivery_note, "custom_sales_person"):
delivery_note.custom_sales_person = sales_order.sales_person
# カスタムメッセージをログに出力
frappe.logger().info(f"Custom override: Delivery Note created from Sales Order {source_name}")
return delivery_note
この仕組みを理解すると「本体は触らず、追加アプリで責務を分離する」という設計思想がしっかり腹落ちします。 結果として、システムはバージョンアップに強くなり、チーム開発でも役割分担が明確になります。
全体として、ERPNext のカスタマイズは
・軽い調整はカスタムフィールド
・現場対応はフォームや帳票、スクリプト」
・本格的な拡張はカスタムアプリやサーバーサイドスクリプト
という3段階で整理されており、実務上も非常に扱いやすい設計になっています。
標準で提供される Hook ポイント
ERPNext(正確には Frappe Framework)は、拡張用に多くのフックを標準で用意しています。
代表的なものをカテゴリごとに整理すると、以下のようになります。
🔹 イベントフック
doc_events
DocType の作成・更新・削除時に処理を差し込む
例:validate
,before_save
,on_submit
🔹 メソッドフック
override_whitelisted_methods
既存の API エンドポイントを自作関数で置き換える
🔹 UI / フロントエンド系
fixtures
Custom Field や Print Format を JSON 化して配布可能app_include_js
/app_include_css
独自の JS / CSS を読み込む
🔹 スケジュールジョブ
scheduler_events
定時実行処理を登録可能(毎時・毎日・Cron指定など)
3. カスタマイズ実例
-
業種別カスタマイズ
現場ごとに必ず出てくる「ちょっとした追加項目」は、ERPNextでは Custom Field で解決できます。- 農業法人なら「収穫量」を入力する欄を加えるだけで、帳票や集計にすぐ反映可能。
- 不動産業なら「契約更新日」をフィールド化すれば、更新管理の抜け漏れを防げます。
どちらも数クリックで済むため、「システムを壊さずに現場にフィットさせる」好例です。
-
出力カスタマイズ
日本企業では請求書や見積書のフォーマット要求が厳しいのは周知の事実です。
ERPNextでは「消費税の明細」や「取引先コード」といった会社固有の要素を、印刷フォーマットに組み込むだけ。
開発を伴わずに現場に納得感を出せるのは、導入を進める上で大きな武器になります。 -
独自ワークフロー
承認ルートを追加したい場面は多々あります。例えば「100万円以上の発注は役員承認」といったルール。
ERPNextでは Workflow と Server Script を組み合わせることで、現場の慣習を壊さずにシステムへ反映可能です。
これは「業務プロセスにシステムを合わせる」ERPNextの真価が出る部分です。 -
NG例
導入現場でよく見かける失敗も共有しておきます。- コアの
.py
を直接編集 → これは一見手っ取り早いですが、アップデートで必ず消えます。 - DocType の構造変更 → 短期的には便利でも、将来的に互換性を壊すリスクが高い。
- Fixture 化を忘れる → 開発環境では動くのに、本番に反映されず「なぜ?」となる典型例です。
どれも経験豊富な技術者なら「絶対に避けるべき」と口を揃える落とし穴です。
- コアの
まとめ
ERPNextは「カスタマイズ=アップデート不可」という、従来ERPにありがちな呪縛を根本から解き放ちました。
コアは常に最新を保ちながら、独自アドオンや業務固有の設定はそのまま残せる。
このアーキテクチャこそが大きな安心材料です。
導入現場に立つ技術者にとって、これは「攻めのカスタマイズ」と「守りの運用」を同時に実現できる数少ない仕組みといえます。
短期的な現場ニーズに応えながらも、将来のバージョンアップを恐れず進められる――その柔軟さは、他のERPにはなかなか見られません。
つまりERPNextは、単なる“安価なERP”ではなく、長期的なシステムの成長に寄り添える選択肢として強く位置づけられるのです。