サーバースクリプト
ERPNextのサーバースクリプトで、User作成時にEmployeeを自動生成する方法を解説します。
ERPNextのサーバースクリプト活用:
ユーザと従業員を自動連携する手順
ERPNextを導入したけれど、ユーザー登録と従業員登録を二重で行うのが手間… と感じていませんか?
本記事では、サーバースクリプト(Server Script)を使って User作成と同時にEmployeeを自動生成する方法 を解説します。
はじめに
ERPNextには標準で以下の 5つのカスタマイズ手段 があります。
- カスタムフィールド
- カスタムフォーム
- クライアントスクリプト
- サーバースクリプト
- アプリ
用途に応じて段階的に拡張でき、現場に寄り添った調整が可能です。
本記事では バックエンド処理を軽量・柔軟に変えられるサーバースクリプト に絞り、
実際の使い方を交えてご紹介します。
今回は、User作成と同時にEmployeeを自動生成する方法を解説します。
外部アプリを作らなくても、ERPNext標準の Server Script機能 と短いPythonコードだけで実現できます。
またERPNextは 本体とカスタムの分離、および 公式Hook/APIによる拡張設計 により、
アップデートに強い「壊れにくいカスタマイズ」を実現できます。
(詳細は別記事 壊れないカスタマイズ 、クライアントスクリプト をご覧ください。)
では、まずは最小構成でサーバースクリプトを体験し、段階的に理解を広げていきましょう。
サーバースクリプト(Server Script)とは?
サーバースクリプト(Server Script)とは、ERPNextのサーバー側(Python)で動作する 小さな処理を埋め込む仕組み です。
イメージとしては、SalesforceのApexトリガー や kintoneのWebhook+サーバー関数 に近く、
ドキュメントのイベントにフックして自動処理や連携を走らせる ことができます。
内部では frappe API(DBアクセス、ドキュメント操作、メッセージ出力など) にアクセスできるため、
カスタムアプリを作らなくても「ちょっとした自動化」を即実装できます。
クライアントスクリプトがUI改善を担うのに対して、
サーバースクリプトは 業務ロジックの自動化・裏側の制御 を担う位置づけです。
例えば
-
ドキュメントイベント処理
- Userが作られたらEmployeeも自動作成
- Sales Invoiceが確定したら在庫を引き落とす
-
定期バッチ
- 毎晩の請求書リマインド送信
- 未処理タスクの自動通知
-
APIエンドポイント
- 外部サービスから呼び出せる簡易Webhook
- 独自のRESTエンドポイントを追加
-
権限制御・検証
- 保存前に独自のビジネスルールをチェック
- 条件に合わない場合はエラーを返す
など、
「アプリ化するまでもない処理を、ERPNext本体に安全に差し込める」軽量拡張 が可能です。
実装ステップ
では、実際にサーバースクリプトを登録してみましょう。
ここでは 「ユーザーを作成したら、自動的に従業員レコードも作成される」最小構成 を実装します。
手順
-
設定 → カスタマイズ → サーバースクリプト へ移動
-
新規作成 → 下記を設定
- Doctype:
ユーザ
- Script Type:
DocType Event
- Event:
挿入後
- Doctype:
-
下記コードを貼り付け → 保存
# Website User は対象外
def split_first_last(name):
name = (name or "").strip()
if not name:
return {"first": "", "last": ""}
p = name.find(" ")
if p == -1:
return {"first": name, "last": ""}
return {"first": name[:p], "last": name[p+1:]}
# ループ防止
if not frappe.flags.get("sync_user_employee_in_progress"):
u = doc # User
# Website User は対象外(必要ならこの条件を外す)
if u.user_type != "Website User":
# 既に user_id で紐づいた Employee があれば何もしない
if not frappe.db.exists("Employee", {"user_id": u.name}):
# メール一致で既存Employeeを探索
employee_name = None
if u.email:
employee_name = (
frappe.db.get_value("Employee", {"company_email": u.email}, "name")
or frappe.db.get_value("Employee", {"personal_email": u.email}, "name")
)
frappe.flags["sync_user_employee_in_progress"] = True
try:
if employee_name:
emp = frappe.get_doc("Employee", employee_name)
if not emp.user_id:
emp.db_set("user_id", u.name, update_modified=True)
else:
# ここでタプルアンパックを使わない
basis = (u.full_name or u.first_name or u.username or "").strip()
# 最速・禁則回避の名前分解
sp = basis.find(" ")
if sp == -1:
first = basis
last = ""
else:
first = basis[:sp]
last = basis[sp+1:]
emp = frappe.get_doc({
"doctype": "Employee",
"first_name": first or (u.first_name or u.username),
"last_name": last,
"status": "Active",
"company": "MyHaTch ホールディングス",
"date_of_joining": frappe.utils.today(),
"user_id": u.name,
"personal_email": u.email or None,
})
emp.insert(ignore_permissions=True)
finally:
frappe.flags["sync_user_employee_in_progress"] = False
4. コード解説
def split_first_last(name)
if not frappe.flags.get("sync_user_employee_in_progress"):
emp.insert(ignore_permissions=True)
5. 留意点
サーバースクリプトはとても便利ですが、いくつか注意すべき点があります。
よくハマるポイントを以下に整理します。
1. Safe Exec による制限
サーバースクリプトは RestrictedPython という安全モードで動きます。
これは「自由にコードが書ける代わりに、危険な操作は禁止するルール」と考えてください。
import
文が使えません
(frappe
やfrappe.utils
はOK)getattr
/setattr
/ タプルアンパック(a, b = ...
)などは無効化- 代わりに
frappe.flags.get()
など安全APIを使います
2. doc オブジェクトの扱い
イベントスクリプトでは doc
という変数に処理対象のドキュメントが入っています。
ただし関数の中に閉じ込めると参照できなくなることがあるため、
トップレベルで if
を並べるシンプルな書き方が推奨です。
3. エラーとデバッグ
- 入力が不正な場合は
frappe.throw()
でユーザーに警告できます - デバッグは
frappe.log_error("内容", "タイトル")
で Error Log に残せます - v15には「Server Script Log」というDocTypeは存在しないので、Error Logで統一管理されます
5. パフォーマンスへの影響
サーバースクリプトは「保存処理の最中に実行」されるため、処理が重いと画面全体が遅くなります。
外部サービス連携など時間がかかる処理は、バックグラウンド処理に任せるのが適切です。
6. 運用上の注意
サーバースクリプトはデータベースに保存されるため、Gitなどのコード管理には含まれません。
そのため、export-fixturesでJSONに出力してリポジトリに含めるなど、
追跡できる運用ルールを決めておくことが大切です。
6. まとめ
サーバースクリプトは “自社の業務ロジックを自動化” するための最短ルート です。
- SalesforceのApexトリガーやkintoneのWebhook関数のように使える
- ERPNext本体とは分離された仕組みで、公式のHook/APIに基づいて動作する
- そのため、アップデートに強く、壊れにくい拡張が可能
さらにAIの補助を使えば、こうした小さな自動化コードは誰でも短時間で書ける時代になりました。
オープンソースであるERPNextは、そのための 最良の“発射台” と言えます。
複数システムやExcelで分散管理している現場も、ERPNextで一元化すれば作業負担を大きく減らせます。
しかも、導入コストは大手ERPに比べて圧倒的に低い水準です。
ぜひERPNextとサーバースクリプトを活用し、業務の自動化を加速させてください。
導入・運用の伴走は、私たち MyHatch にお任せください。
よくある質問(FAQ)
Q. サーバースクリプトはアップデートで壊れませんか?
▼
ERPNextのサーバースクリプトは 本体コードと分離 して管理されるため、
アップデートによる直接的な破損リスクは小さいです。
ただし、Doctypeのフィールド構成やAPI仕様が変更された場合は影響を受ける可能性があります。
そのため、定期的にテスト環境でアップデートを試し、 サーバースクリプトが正常に動作するかを確認する運用が推奨されます。
Q. サーバースクリプトとクライアントスクリプトの違いは?
▼
- クライアントスクリプト はブラウザ(フロント側)で動作し、フォーム入力やUIの挙動を制御します。
例: フィールドの自動入力、保存前バリデーション、UIエフェクト。
- サーバースクリプト はERPNextのサーバー(バックエンド側)で動作し、
データの保存時イベントやバッチ処理、API連携などを制御します。
例: User作成時にEmployeeを自動生成、毎晩のリマインド送信。
→ UIを変えるならクライアントスクリプト、業務ロジックを自動化するならサーバースクリプト、という住み分けです。
Q. サーバースクリプトはどこまで自由に書けますか?
▼
サーバースクリプトは RestrictedPython(安全サンドボックス) 上で動作するため、
通常のPythonと違い制約があります。
import
は原則禁止(frappeとfrappe.utilsは利用可)- 危険な組み込み(getattr/setattr、タプルアンパックなど)は無効化
- DBアクセスやDoc操作は
frappe
APIを通じて行う
小さな自動化や検証に適しており、複雑な処理はカスタムアプリで実装するのが推奨です。