mcpField
B
business-rule-patterns

business-rule-patterns

github.com/serac-labs開発7764 回インストール9 週間前に更新
リポジトリ

business-rule-patterns について

ServiceNow 開発者向けに、ビジネスルールの実行タイミング、レコード操作、フィールド変更の検出を解説するスキルです。性能面の指針や代表的な実装パターンも示します。

主な機能

  1. 01Before、After、Async、Display の使い分け
  2. 02current と previous によるレコード処理
  3. 03フィールド変更の検出と実行条件の設定
  4. 04自動割り当てと連鎖更新のパターン
  5. 05ルールのパフォーマンス改善

活用シーン

  1. 01レコードの検証とフィールドの自動入力
  2. 02更新後の関連レコード作成
  3. 03時間のかかる連携処理のバックグラウンド実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/serac-labs/serac --skill business-rule-patterns

インストール後、Claude Code で/business-rule-patternsを入力して読み込まれたか確認します。

詳細

ServiceNow のビジネスルールに関するベストプラクティス

ビジネスルールは、レコードの表示、挿入、更新、削除時に実行されるサーバーサイドスクリプトです。

各タイプの使い分け

タイプタイミングユースケースパフォーマンスへの影響
Beforeデータベースへの書き込み前現在のレコードの検証、変更低
Afterデータベースへの書き込み後関連レコードの作成、通知中
Asyncバックグラウンド(コミット後)高負荷の処理、連携なし(バックグラウンド)
Displayフォームの読み込み時フォーム表示の変更、デフォルト値の設定低

使用可能なオブジェクト

// In Business Rules, these are always available:
current // The record being operated on
previous // The record BEFORE changes (update/delete only)
gs // GlideSystem utilities

Before ビジネスルール

検証やフィールド操作に使用します。

// Prevent update if condition not met
;(function executeRule(current, previous) {
  if (current.state == 7 && previous.state != 6) {
    current.setAbortAction(true)
    gs.addErrorMessage("Must resolve before closing")
  }
})(current, previous)
// Auto-populate fields
;(function executeRule(current, previous) {
  if (current.isNewRecord()) {
    current.setValue("caller_id", gs.getUserID())
    current.setValue("opened_by", gs.getUserID())
  }
})(current, previous)

Before ルールでは、次の処理を行わないでください。

  • current.update() の呼び出し(再帰が発生します!)
  • 他のテーブルへのクエリ(処理速度を維持してください)
  • 外部 API の呼び出し

After ビジネスルール

関連レコードの操作に使用します。

// Create child record when priority is P1
;(function executeRule(current, previous) {
  if (current.priority.changesTo(1)) {
    var task = new GlideRecord("task")
    task.initialize()
    task.setValue("short_description", "P1 Follow-up: " + current.number)
    task.setValue("parent", current.sys_id)
    task.insert()
  }
})(current, previous)
// Update parent record
;(function executeRule(current, previous) {
  var parent = new GlideRecord("problem")
  if (parent.get(current.problem_id)) {
    parent.setValue("related_incidents", parent.related_incidents + 1)
    parent.update()
  }
})(current, previous)

Async ビジネスルール

トランザクションをブロックすべきではない、高負荷の処理に使用します。

// External integration
;(function executeRule(current, previous) {
  var integrator = new ExternalSystemIntegration()
  integrator.syncIncident(current.sys_id)
})(current, previous)
// Send custom notification
;(function executeRule(current, previous) {
  gs.eventQueue("incident.priority.high", current, current.assigned_to, gs.getUserID())
})(current, previous)

便利なメソッド

current メソッド
current.isNewRecord() // True if insert
current.isValidRecord() // True if record exists
current.getValue("field") // Get field value
current.setValue("field", val) // Set field value
current.setAbortAction(true) // Cancel the operation
current.operation() // 'insert', 'update', 'delete'
current.isActionAborted() // Check if aborted
フィールドの変更検出
current.priority.changes() // Field changed (any value)
current.priority.changesTo(1) // Changed TO this value
current.priority.changesFrom(3) // Changed FROM this value
current.priority.nil() // Field is empty
previous の比較
// Check if field was modified
if (current.state != previous.state) {
  gs.info("State changed from " + previous.state + " to " + current.state)
}

// Check specific change
if (current.assigned_to.changes() && !previous.assigned_to.nil()) {
  gs.info("Reassignment occurred")
}

条件の例

ルールの実行タイミングを制限するには、条件を使用します。

条件意味
current.active == trueアクティブなレコードのみ
current.isNewRecord()挿入時のみ
current.priority.changes()優先度が変更された場合のみ
gs.hasRole('admin')管理者のみ
current.assignment_group.nil()未割り当ての場合のみ

パフォーマンスに関するベストプラクティス

  1. 条件を使用する - ルールの実行タイミングを制限します
  2. Before ルールを高速に保つ - 可能であればクエリを行いません
  3. 連携には Async を使用する - トランザクションをブロックしません
  4. Display ルールを避ける - フォームの読み込みが遅くなります
  5. Order を設定する - 数値が小さいものから実行されます(100~500 の範囲)
  6. 「when to run」を確認する - insert、update、delete、query

よくあるパターン

自動割り当て
// Before Insert/Update
if (current.assignment_group.changes() && !current.assignment_group.nil()) {
  var members = new GroupMembers(current.assignment_group)
  current.assigned_to = members.getNextAvailable()
}
カスケード更新
// After Update
if (current.state.changesTo(7)) {
  // Closed
  var tasks = new GlideRecord("task")
  tasks.addQuery("parent", current.sys_id)
  tasks.addQuery("state", "!=", 7)
  tasks.query()
  while (tasks.next()) {
    tasks.setValue("state", 7)
    tasks.update()
  }
}

コメント