0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【連載 第7回】ServiceNow標準機能だけで作る「Pull型」自動化連携 ― Business Ruleで依頼者に進捗を見せる

0
Last updated at Posted at 2026-10-22

本記事は連載「ServiceNow標準機能だけで作るPull型自動化連携」の第7回です。
第6回では、結果登録APIで自動化の結果を記録し、成功なら次の作業へ進め、失敗なら人の担当グループへ引き継ぐところまで作りました。
今回は、Business Ruleを1本だけ追加して、SCTASKの進捗をRITMのActivityに表示し、依頼者が「今どうなっているのか」を確認できるようにします。

この回で作るもの

ここまでの仕組みでは、自動化の状態はSCTASKの State × Assigned to で表されています。しかし依頼者が普段見るのはRITMで、SCTASKの変化は直接見えません。

そこで、SCTASKの状態が変わったときに、RITMの Additional comments に進捗を1行ずつ書き込みます。

SCTASKの変化 RITMのActivityに表示される内容
Open + autoengine1 → In Progress + autoengine1(確保) [Automation] Task claimed and queued.
autoengine1 → autoengine1running(実行開始) [Automation] Execution started.
→ Closed Complete(正常完了) [Automation] Execution completed successfully.

状態管理用のカスタムフィールドは、ここでも追加しません。既存のStateとAssigned toの変化を読み取って、表示するだけです。

1. 役割分担

結果の記録と進捗の表示は、次のように分けています。

情報 記録先 担当 読み手
進捗(確保・実行開始・完了) RITMの Additional comments 本記事のBusiness Rule 依頼者
結果の詳細 SCTASKの Work Notes 結果登録API(第6回) 運用者
結果の表示用テキスト RITMの execution_result_display 結果登録API(第6回) 依頼者
結果の履歴(機械処理用) RITMの execution_result_json 結果登録API(第6回) 後続の自動化処理

Business Ruleは進捗の通知だけを担当します。結果の中身や失敗の詳細は転記しません。

2. Business Ruleを作成する

System Definition > Business Rules を開き、New を選択します。

フィールド 設定値
Name SCTASK Activity to RITM
Table Catalog Task [sc_task]
Active true
Advanced true
When after
Order 100
Insert false
Update true
Delete false

2.1 実行条件

StateかAssigned toのどちらかが変わったときだけ動かします。Advanced Conditionを使う場合は、次を指定します。

current.state.changes() || current.assigned_to.changes()

それ以外の更新(Work Notesの追記など)では、RITMにコメントを追加しません。

2.2 なぜ after なのか

SCTASKの更新が確定した後に、別のレコード(RITM)を更新するためです。SCTASK自身の値を書き換えるわけではないので、before にする必要はありません。

3. Business Rule Script

Script欄に、次のコードを設定します。

IN_PROGRESS_STATE と CLOSED_COMPLETE_STATE は、対象インスタンスの sc_task.state の内部値に合わせてください。特に CLOSED_COMPLETE_STATE は、第6回の結果登録APIと同じ値にする必要があります。

(function executeRule(current, previous) {
    'use strict';

    var IN_PROGRESS_STATE = '2';
    var CLOSED_COMPLETE_STATE = '3';
    var WAITING_ASSIGNEE = 'autoengine1';
    var RUNNING_ASSIGNEE = 'autoengine1running';

    if (current.request_item.nil()) {
        return;
    }

    var ritm = current.request_item.getRefRecord();

    if (!ritm || !ritm.isValidRecord()) {
        return;
    }

    if (!ritm.comments.canWrite()) {
        gs.warn(
            'SCTASK Activity to RITM: comments cannot be updated for ' +
            ritm.getValue('number')
        );
        return;
    }

    var currentAssignee = getAssignedToUserName(current);
    var previousAssignee = getAssignedToUserName(previous);
    var message = '';

    // Open + autoengine1 -> In Progress + autoengine1
    if (current.state.changesTo(IN_PROGRESS_STATE) &&
        currentAssignee === WAITING_ASSIGNEE) {
        message = [
            '[Automation] Task claimed and queued.',
            'Task: ' + current.getValue('number')
        ].join('\n');
    }

    // In Progress + autoengine1 -> In Progress + autoengine1running
    if (current.assigned_to.changes() &&
        previousAssignee === WAITING_ASSIGNEE &&
        currentAssignee === RUNNING_ASSIGNEE) {
        message = [
            '[Automation] Execution started.',
            'Task: ' + current.getValue('number')
        ].join('\n');
    }

    // In Progress -> Closed Complete
    if (current.state.changesTo(CLOSED_COMPLETE_STATE)) {
        message = [
            '[Automation] Execution completed successfully.',
            'Task: ' + current.getValue('number')
        ].join('\n');
    }

    if (!message) {
        return;
    }

    ritm.comments = message;
    ritm.update();

    function getAssignedToUserName(record) {
        if (!record || !record.isValidRecord() ||
            record.getElement('assigned_to').nil()) {
            return '';
        }
        var user = record.getElement('assigned_to').getRefRecord();
        return user && user.isValidRecord()
            ? user.getValue('user_name') || ''
            : '';
    }
})(current, previous);

3.1 コードのポイント

状態の変化を「前後の組み合わせ」で判定する
changesTo() と previous の値を使い、第2回で決めた状態遷移のどこを通ったかを判定しています。

判定 条件
確保 Stateが In Progress に変わり、担当が autoengine1
実行開始 担当が autoengine1 から autoengine1running に変わった
正常完了 Stateが Closed Complete に変わった

ユーザーはsys_idではなく user_name で比べる
第5回のAPIと同じく、インスタンスに依存しない名前で判定します。

書き込めない場合は何もしない
RITMの comments に書き込む権限がなければ、更新せずにSystem Logへ警告を出します。Business Ruleのエラーで、SCTASKの更新そのものが妨げられることはありません。

RITMに紐づかないSCTASKは対象外
request_item が空のSCTASKでは、何もしません。

3.2 失敗時はコメントを出さない

結果登録APIがFAILEDを受け取ると、SCTASKは In Progress のまま、failure_assignment_group へ引き継がれ、Assigned toは空欄になります。

  • Stateは In Progress のまま変わらない → 「確保」の条件に当てはまらない
  • 担当は autoengine1running から空欄に変わる → 「実行開始」の条件に当てはまらない
  • Closed Complete にはならない → 「正常完了」の条件に当てはまらない

そのため、失敗時にはBusiness Ruleからコメントは出ません。失敗の詳細は、運用者向けのWork Notesと、結果登録APIが更新する execution_result_display で扱います。

comments(Additional comments)は依頼者に表示されます。内部情報や機密情報を含めないでください。

3.3 人が担当する作業では動かない

人が担当するSCTASKは、Assigned toが autoengine1 系ではないため、「確保」と「実行開始」のコメントは出ません。

一方、「正常完了」の判定は担当者を見ていないため、人が担当するSCTASKをClosed Completeにした場合も [Automation] Execution completed successfully. が出ます。自動化の作業だけに絞りたい場合は、完了判定にも担当者の条件を追加してください。

4. 複数の自動化エンジンを使う場合

第3回で紹介したように、作業3を自動化エンジン2(autoengine2)に担当させる場合、このサンプルのままでは「確保」と「実行開始」のコメントが出ません。WAITING_ASSIGNEE と RUNNING_ASSIGNEE を autoengine1 固定で比べているためです。

複数のエンジンに対応するには、たとえば次のように、名前の規則で判定する方法があります。

function isWaitingAssignee(userName) {
    return /^autoengine[0-9]+$/i.test(userName);
}

function isRunningAssignee(userName) {
    return /^autoengine[0-9]+running$/i.test(userName);
}

この場合は、第5回のAPIの isAllowedAutomationUser() も同じ規則に合わせてください。

5. 表示内容

RITMのActivityには、次のように表示されます。

確保したとき

[Automation] Task claimed and queued.
Task: SCTASK0010006

実行を開始したとき

[Automation] Execution started.
Task: SCTASK0010006

正常に完了したとき

[Automation] Execution completed successfully.
Task: SCTASK0010006

Execution Planで複数の作業がある場合は、SCTASKごとにこの3行が順に並びます。依頼者は、RITMの画面だけで、どの作業まで進んだかを追えます。

6. 動作確認

第4〜6回で作ったAPIを順に呼び、RITMのActivityを確認します。

6.1 確保

  1. Open + autoengine1 のSCTASKを用意する
  2. Table APIでStateを2に更新する(第4回)
  3. RITMのActivityに Task claimed and queued. が追加される

6.2 実行開始

  1. SCTASKが In Progress + autoengine1 であることを確認する
  2. 第5回のAPIで、Assigned toを autoengine1running に変更する
  3. RITMのActivityに Execution started. が追加される

6.3 正常完了

  1. 第6回の結果登録APIへSUCCESSを送る
  2. SCTASKがClosed Completeになる
  3. RITMのActivityに Execution completed successfully. が追加される

6.4 チェックリスト

  • Business Ruleが sc_task の after update で動く
  • 確保・実行開始・正常完了で、それぞれ1件ずつコメントが追加される
  • Work Notesの追記など、StateやAssigned toに関係しない更新ではコメントが追加されない
  • FAILEDの結果登録では、コメントが追加されない
  • RITMに紐づかないSCTASKでは、何もしない
  • CLOSED_COMPLETE_STATE が結果登録APIと同じ値になっている

次回予告

次回は、第4〜6回の処理を1本にまとめたE2Eテストスクリプトで、依頼から完了までを通しで動かします。取得 → 確保 → 詳細取得 → 実行開始 → 実行 → 結果登録の流れと、各段階で確認するポイントを紹介します。

連載記事


※ 本記事の内容は個人の見解であり、所属する組織の公式な見解ではありません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?