メインコンテンツへスキップ

サービスカタログの自動設定構成


    申請を1件送信すると、承認・タスク生成・完了判定までが人の操作なしに進みます。この裏側を支えているのがBusiness Ruleです。sc_request・sc_req_item・sc_taskの計43件のうち、承認直後に動く2件は新旧2つの履行エンジンをそれぞれ起動する役目を持ちます。Australia PDIのOOTB設定を実機で追い、どの順番で何が動くかを確認しました。

    検証環境:Australia PDI / OOTB / 2026-09-01 確認

    先に押さえておくこと

    • ビジネスルールは3テーブル合計43件(sc_request10・sc_req_item20・sc_task13)が有効

    • 承認直後に動くStart WorkflowとStart FlowDesigner Flowは、beforeとafterでフェーズが異なるため、実行順はorder番号の大小どおりにならない

    • 承認からタスク生成・完了判定・REQ完了までは、複数のビジネスルールが連鎖して進む

    • sys_ui_policy・sys_data_policy2・sys_script_clientはsc_request/sc_req_item/sc_task本体でいずれも0件で、フォーム制御はcatalog_ui_policyとcatalog_script_clientという変数側の仕組みに集中する

    • 通知はsc_req_itemの18件中13件がApp Engine Studioのアプリ申請承認と共用されている

    ビジネスルールの実行タイミング

    サーバ側の処理は、DB書き込みを基準にした4つのタイミングに分かれます。書き込み前に動くbefore、書き込み後に動くafter、フォームを開く前に動くdisplay、非同期に動くasyncです。3テーブルの内訳を数えると、beforeとafterの比率がテーブルごとに違いました。

    テーブルbeforeafterdisplay合計sc_request46010sc_req_item614020sc_task75113合計1725143

    sc_req_itemはafterが7割を占めます。承認後に他レコードを生成・更新する処理が集中しているためです。sc_taskは逆にbeforeが多く、状態を書き込む前の補正が中心になります。


    画像

    before/afterの基本的な違いは、書き込みのどちら側で動くかに加えて、実行順序にもあります。同じテーブルの保存1回でも、beforeフェーズが全件完了してから初めてafterフェーズが始まります。この前提が、次に扱う2つの履行エンジンの実行順を左右します。

    承認直後に起動する2つの履行エンジン

    RITMのstageがrequest_approvedに変わった直後、履行を始めるための2件のビジネスルールが控えています。旧来のWorkflowエンジンを起動するStart Workflowと、Flow Designerエンジンを起動するStart FlowDesigner Flowです。カタログアイテム204件の内訳は、本シリーズ第5巻の実測で「Flow Designerのみ59・Workflowのみ55・両方5・どちらも未設定85」と確定しています。この5件でどちらが動くかを、実機のスクリプトから確認しました。


    画像

    Start Workflowはorder 10,000のbeforeルールです。条件は次のとおりです。

    !current.cat_item.workflow.nil() && current.stage=='request_approved'
      && current.context.nil() && current.flow_context.nil()

    条件が成立すると、次の処理でWorkflowを起動し、結果のcontextを書き込みます。

    startWorkflow(current.cat_item.workflow.toString());
    function startWorkflow(id) {
       var w = new Workflow();
       var context = w.startFlow(id, current, current.operation(), getVars());
       if (context != null)
          current.context = context.sys_id;
    }

    Start FlowDesigner Flowはorder -1,000のafterルールです。条件はほぼ対称です。

    !current.cat_item.flow_designer_flow.nil() && current.stage=='request_approved'
      && current.flow_context.nil() && current.context.nil()

    成立すると、fireCatalogTriggerでFlowを起動します。

    function startFlowDesignerFlow(current) {
       var flow = current.cat_item.flow_designer_flow;
       var flowName = flow.sys_scope.scope + "." + flow.internal_name;
       sn_flow_trigger.FlowTriggerAPI.fireCatalogTrigger(flowName, current);
    }


    画像

    2つの条件を並べると、どちらもcontextとflow_contextが空であることを確認してから動きます。ここで効くのが、beforeフェーズがafterフェーズより必ず先に完了するという原則です。

    Workflowのみ55件ではStart Workflowだけが条件を満たし、Flow Designerのみ59件ではStart FlowDesigner Flowだけが条件を満たします。両方が設定された5件では、beforeのStart Workflowが先に実行され、条件を満たしていればcontextへ値を書き込みます。DB書き込みのあとに評価されるStart FlowDesigner Flowは、その時点ですでにcontextが空でなくなっているため、条件が不成立になり起動しません。order番号だけを比較すると-1,000のFlow Designerが先に見えますが、beforeとafterのフェーズが違うため、実際に先に動くのは旧エンジンのWorkflowです。どちらも未設定の85件では、そもそもどちらの条件も成立しません。

    フローという言葉には、動く時点の異なる2つの実体があります。REQ用フロー「Service Catalog Request」は注文と同秒に起動していました(実測)。承認ルールも注文4秒後に承認依頼を作ります。一方、アイテム個別の履行フロー(flow_designer_flow)と旧Workflowは、上記の条件式のとおりstage=='request_approved'を満たすまで起動しません。実測でも、履行フロー「Service Catalog item request」の起動はREQ承認の後でした。承認の前に動くのはREQ用フローと承認ルール、承認された後に動くのが履行エンジンという分担です。

    履行タスクの生成から申請完了までのカスケード

    承認が完了したあと、履行タスクの生成からRequestの完了まで、複数のビジネスルールが順にバトンを渡します。全体の流れを図にまとめました。


    画像

    delivery_planによるタスク生成

    RITMのapprovalがapprovedに変わったとき、delivery_planが設定されている品目だけがタスク生成の対象になります。Start Tasks(after・order100)がDeliveryPlan.initTasks()を呼び、Create Request Item Child Tasks(after・order100)がCatalogTaskGeneratorで実際のsc_taskレコードを作ります。

    var plan = GlideappDeliveryPlan.get(current.delivery_plan);
    gs.include('CatalogTaskGenerator');
    var gen = new CatalogTaskGenerator(plan, gr);
    gen.createTasks();

    生成された各sc_taskは、Populate parent field in sc_task table(before・order100)によってparentフィールドへrequest_itemの値を複写されます。delivery_planが未設定の品目では、この一連の処理自体が動かず、履行は担当者の手動対応に委ねられます。

    タスク完了からRITM完了への遷移

    タスクが完了すると(stateが3・4・7のいずれかに変わる)、Close Ticket(before・order100)がactiveをfalseにし、所要時間を計算します。

    current.active = false;
    current.work_end = nowDateTime();
    if (!current.work_start.nil())
        current.business_duration = gs.calDateDiff(current.work_start.getDisplayValue(), current.work_end.getDisplayValue(), false);

    続くStart Peer Tasks(after・order100)が、兄弟タスクの残数を確認します。まだ未完了のタスクがあれば次のタスクを起動してRITMのstageを進行中の内容に更新し、すべて完了していればRITMのstageをcomplete・closed_incomplete・closed_skippedのいずれかに確定します。


    画像

    RITM完了からREQ完了への遷移

    RITMのstageが確定すると、Close Parent if Required(after・order100)が発火します。

    new SNC.RequestItem(current).closeParentRequest();

    このメソッドが親のsc_requestを閉じます。REQ側では、Set Request State(before・order1,100)がapprovalの変化とstageからrequest_stateを確定し、Mark Request Closed(before・order1,200)がactive・closed_by・closed_at・所要時間をまとめて確定します。

    if (current.request_state == "closed_complete" || ... || current.stage == "closed_skipped") {
        current.active = false;
        if (current.closed_by.nil()) current.closed_by = gs.getUserID();
        if (current.closed_at.nil()) {
            current.closed_at = gs.nowDateTime();
            current.business_duration = gs.calDateDiff(current.opened_at.getDisplayValue(), current.closed_at.getDisplayValue(), false);
        }
    }


    画像

    3テーブルのビジネスルール43件を、order順の一覧としてすべてまとめました。


    画像


    画像


    画像

    Assign from Stock(sc_req_item・before・order100)は、configuration_itemが設定されたときにCMDBのCIをPending Installにし、申請者へ割り当てる処理です。ハードウェア資産のカタログ項目からITAM(IT Asset Management)へつながる、実務での接点の1つです。Create Inventory Item(sc_req_item・after・order100)はstageがcompleteになったときに発火し、在庫アイテムの作成を担います。

    却下・取消のカスケード

    取消にも専用の仕組みがあります。承認が却下された場合と、申請そのものが取り消された場合は、完了とは別の経路が動きます。

    sc_task側のReject Parent(after・order100)は、承認タスクが却下され、かつ却下時の挙動がcancelに設定されている場合に、親のRITMをRequest Cancelledへ進めます。Process Rejection(after・order100)は却下をDeliveryPlan.rejectTask()へ伝え、計画側の状態を更新します。

    RITM側がRequest Cancelledになると、Close Tasks Due to Cancellations(after・order100)が配下のsc_taskをparent条件で検索し、まとめてClosed Incomplete(state=4)にします。同時に、実行中のFlow Designerコンテキストをcancel flow on request cancelled/deleted(after・order-100)がFlowAPI.cancel()で止める仕組みです。RITMが物理削除された場合は、Delete Tasks for Deleted Requested Item(before・order100)が配下のタスクをrequest_item条件で削除します。

    REQ側でも対になる処理があります。REQのstateが取消(4)に変わると、Cancel Flows Upon Cancellation(sc_request・after・order100)がsys_flow_contextを検索し、実行中のFlowを止めます。完了の経路とほぼ同じ構造が、取消の経路にも用意されています。

    価格と数量の再計算

    申請前の買い物かごに相当するテーブルはsc_cartとsc_cart_itemです。sc_cart_itemが持つ固有フィールドはquantity(既定値1)で、価格は保持しません。カートの中身がRITMへ変換される時点で、sc_req_itemのprice・quantity・recurring_price・recurring_frequency・billableへ値が引き継がれます。

    申請後、これらの値が変わるたびに合計金額が再計算されます。担当するReduce request price - item change(sc_req_item・after・order10,000)の条件は次のとおりです。

    current.recurring_price.changes() || current.recurring_frequency.changes()
      || current.state.changes() || current.approval.changes()
      || current.price.changes() || current.quantity.changes()
      || current.operation() == 'delete'

    処理は親のsc_requestを取得し、SNC.RequestのrecalculateAllPrices()を呼ぶだけです。

    var requestGr = new GlideRecord("sc_request");
    if (!requestGr.get(current.request.sys_id + "")) return;
    var request = new SNC.Request(requestGr, previous, current);
    if (request) request.recalculateAllPrices();

    SNC.Requestはプラットフォーム同梱のJavaクラスで、Script Includeとして編集画面には出てきません。合計金額を出し直す実際の計算式までは、今回の実機確認の範囲外です。ここで押さえておきたいのは、1件のRITMの価格・数量が変わるたびに、REQ全体の合計が自動で再計算されるという設計そのものです。品目を追加・削除・数量変更するたびに合計を手計算し直す必要はありません。

    フォーム制御に使われる仕組み

    sc_request/sc_req_item/sc_task本体の設定

    3テーブル本体には、フォームの表示・必須を制御するsys_ui_policy・sys_data_policy2・sys_script_clientが、いずれも0件でした。Incident管理やProblem管理と違い、業務テーブル本体には画面制御の仕組みがほぼ存在しません。

    変数側に集中するcatalog_ui_policyとcatalog_script_client

    制御はカタログアイテムの変数(item_option_new)に紐づく別系統に集中しています。catalog_ui_policyはアクティブ101件、catalog_script_clientはアクティブ138件です。それぞれapplies_catalog・applies_req_item・applies_sc_taskという3つのフラグを持ち、どの画面に適用するかを個別に切り替えられます。applies_catalogの公式説明(sys_documentation)を引用します。

    Indicates that this UI Policy will apply when ordering a Catalog Item

    (訳: このUIポリシーが、カタログ項目の注文時に適用されることを示す)

    同様にapplies_req_itemはRequested Itemのタスク画面への適用、applies_sc_taskはCatalog Task画面への適用を示します。1件のUIポリシー定義を、注文フォーム・RITM・Catalog Taskの3画面に個別配布できる仕組みです。

    半数近くが管理画面向けという内訳

    catalog_ui_policyとcatalog_script_clientの対象をcatalog_itemごとに集計すると、意外な内訳が見えました。上位には「Catalog Variable Creation」のような、カタログの管理画面そのものが並びます。対象の4項目と件数を次にまとめます。

    項目catalog_ui_policycatalog_script_clientCatalog Client Script25Catalog Variable Creation3535Catalog UI Policy32Creator Studio - Variable Editor16224項目の小計56 / 10164 / 138

    この4項目は、カタログ管理者がカタログ項目・変数・UIポリシーそのものを作成・編集するときに開く、ServiceNow自身の管理画面です。Apple iPhoneやStandard Laptopのような申請フォームとは別の系統に位置づけられます。カタログエンジンが自分自身の管理UIを、カタログエンジンの上に構築しています。


    画像

    通知に同居する2つの業務

    通知(sysevent_email_action)はsc_request9件・sc_req_item18件・sc_task4件でした。sc_req_itemの18件をevent_nameで分けると、13件がactivate.life.cycle.migrationという共通のイベント名を持ちます。


    画像

    件名を見ると用途が分かります。「Your app has been approved」「You have a new app request」。アプリ開発の申請を扱うApp Engine Studioの通知です。残る5件が、Delivery・Completed・Commentedといったカタログ本来の履行通知に当たります。

    同じイベントの通知はsc_request側にも3件あります。うち1件は「Request completed」というカタログ完了に見える名前のため、通知を調整するときはevent_nameで見分けます。


    画像

    条件式を見ると、どのイベントで発火するかが具体的に分かります。Request Item Deliveryの条件はstage=deliveryで、履行タスクが配送段階に入った瞬間にだけ届く設定です。Comment left on requestはcommentsVALCHANGESで、追加コメントが書き込まれるたびに発火します。この2つは、本記事で確認したビジネスルールが生成するstageの変化やcommentsの更新と同じ条件式を使っており、通知の起点は自動設定構成が作る状態変化そのものです。

    1回の保存で処理が動く順序

    ここまでの仕組みを、RITM保存1回の時系列に沿って並べます。


    画像
    1. カタログ変数のクライアントスクリプト・UIポリシー:catalog_script_client138件・catalog_ui_policy101件がブラウザ側で入力を制御する

    2. ACL:sc_request/sc_req_item/sc_taskで計106件が書き込み権限を判定する

    3. ビジネスルール(before):sc_request4・sc_req_item6・sc_task7が値を補正し、条件次第で保存を中断する

    4. DB書き込み

    5. ビジネスルール(after):sc_request6・sc_req_item14・sc_task5が他レコードを更新し、Workflow/Flowを起動する

    6. 通知:sc_req_item18件中13件はApp Intake共用のため、実際にカタログ履行へ関わるのは5件が中心になる

    画面が更新されないならクライアントスクリプトかUIポリシー、保存を押した瞬間に止まるならACLかbeforeルール、保存できたのに履行タスクが生成されないならafterルールという順番で切り分けます。

    独自の自動設定を追加するときの確認順序

    自社でカスタムのビジネスルールやFlowを追加するときは、次の順序で確認すると既存の43件と衝突しません。

    1. 既存のorder帯を避ける:sc_req_itemは-1,000〜10,000の範囲を標準ルールが使っている。自社の処理は500番台や1,500番台のような空いた帯に置く

    2. beforeかafterかを先に決める:値を補正するだけならbefore、他レコードやFlowを起動するならafter

    3. stageの値に依存しない:stageはchoice定義に無い値が実行時に入る特殊フィールド。条件式でstageを使う場合は実データの値(request_approvedやRequest Cancelledなど)を直接確認してから書く

    4. workflow/flow_designer_flowの両方設定を避ける:両方設定すると旧エンジンが優先され、新エンジンへの移行が意図どおりに進まない

    5. 通知はevent_nameで絞る:collection=sc_req_itemだけで数えるとApp Intake分が混ざる

    実機で気づいたこと

    order番号だけでは実行順を誤読する

    見た目どおりとは限りません。sys_scriptをorder順に並べると、Start FlowDesigner Flow(-1,000)がStart Workflow(10,000)より先に見えます。

    実際にはwhen列が違います。前者はafter、後者はbeforeです。beforeフェーズはafterフェーズが始まる前に必ず完了するため、実行順は見た目と逆になります。さらに両ルールの条件式はcontextとflow_contextが空かどうかを確認するため、先に動くStart Workflowがcontextを埋めると、あとから評価されるStart FlowDesigner Flowの条件は成立しません。

    order列だけで実行順を判断する一覧の読み方には注意が要ります。並べ替えるときはwhenも同時に確認します。両方のエンジンを設定したまま新エンジンへ移行するつもりでも、旧エンジンのworkflowフィールドを空にしない限り、実際に動くのは旧エンジンのままです。

    catalog_ui_policyの半数近くは申請フォームでなく管理画面向け

    catalog_ui_policy101件・catalog_script_client138件のうち、56件と64件が特定の2項目に集中していました。「Catalog Variable Creation」「Creator Studio - Variable Editor」という、カタログ管理者向けの管理画面です。

    ServiceNowはカタログという仕組み自体を使って、カタログを作るための画面を構築しています。一覧の件数だけを見て「申請フォームの制御が101件もある」と捉えると、実際にエンドユーザーの画面に影響する件数を過大に見積もります。

    自社のカタログ項目でフォームの動きを調べるときは、catalog_itemの値が実在する業務アイテムかどうかを先に確認します。管理画面向けの定義を含めたまま集計すると、影響範囲の見積もりがぶれます。

    parent・request_item・requestはBusiness Ruleで同期される

    本シリーズの概要編・フィールド編では、sc_taskが親をrequest・request_item・parentという3つの経路で持ち、OOB側のスクリプトも経路の使い方が統一されていない点を指摘しました。今回、その理由の一部が分かりました。

    Populate parent field in sc_task table(before・order100)がparentへrequest_itemの値を複写し、Auto Populate Request Field(before・order350)がrequestへrequest_item.request(またはparentがsc_requestの場合はparent自身)の値を複写しています。生成時点でこの2つのルールが働くため、通常の運用では3つの経路が同じ値を指します。

    ただし、これはBusiness Ruleによる同期です。辞書レベルの制約とは異なり、REST APIなどでこれらのルールを経由せずにレコードを作ると、経路がずれる可能性があります。自社スクリプトでsc_taskを検索する条件を書くときは、生成経路がこの2つのルールを通っているかを確認します。

    旧Workflowエンジンは空のまま、参照だけが残っている

    wf_workflow・wf_activity・wf_contextを数えると、いずれも0件でした。定義そのものが空です。一方で、カタログアイテム側のworkflowフィールドには参照が残っています(有効アイテム152件のうち35件)。Start Workflowルールの起動条件は参照の有無で判定するため、参照先の実体が無いまま起動条件が成立し得る構造です。

    では何が動かしているのか。承認ルールとフローです。$1,100のノートPC注文1件の実測では、REQ宛ての承認は注文4秒後に承認ルールが生成しており、sc_request宛ての有効4件のうち$1,000超の承認必須ルールがこの注文に該当していました。RITM宛ての承認は、RITM用フロー「Service Catalog item request」の起動5秒後に生成されていました。通知は、sysevent_email_actionの通知定義がイベント駆動で送ります。定義数はsc_request 9・sc_req_item 18・sc_task 4・sysapproval_approver 17件です。

    自社インスタンスでWorkflowのみ設定のアイテムを使う場合は、参照先のワークフロー定義が実在するかを先に確認します。実在しなければ、そのアイテムは承認ルール以外の履行が動きません。

    用語

    • OOTB:Out of the Box。プラグイン追加やカスタマイズを行っていない、製品のデフォルト状態

    • PDI:Personal Developer Instance。ServiceNowが無償で提供する個人検証用インスタンス

    • RITM:Requested Item。sc_req_itemに保存される、申請された品目1件

    • REQ:Request。sc_requestに保存される、申請1件全体

    • delivery_plan:カタログ項目ごとに設定する履行タスクの計画。設定が無いと履行タスクは自動生成されない

    • stage:internal_typeがWorkflowという特殊型のフィールド。実行中のワークフローやフローのアクティビティ名がそのまま反映される

    検証範囲とおことわり

    • 検証環境:Australia PDI / OOTB / 2026-09-01 確認

    • 件数はすべてOOTBの定義・設定の数です。本番環境やカスタマイズ済み環境では異なります

    • SNC.Request・SNC.RequestItemはプラットフォーム同梱のJavaクラスで、内部の計算式・処理内容までは確認していません

    • ワークフロー・フローの内部(各アクティビティの中身)までは追っていません

    • 実際にレコードを1件保存して処理順序を観測する検証は、本巻では行っていません(承認カスケードのスクリプト内容から順序を確認しています)

    • 通知の本文テンプレート・実際の送信可否までは確認していません

    • カタログ管理画面向けの4項目という分類は、catalog_item名から本巻で判別した範囲です。他にも同種の項目が含まれる可能性があります

    付録:自分の環境で確認するときのURL

    • ビジネスルールのタイミング別:/sys_script_list.do?sysparm_query=collection=sc_req_item^active=true^GROUPBYwhen

    • 2つの履行エンジン起動ルール:/sys_script_list.do?sysparm_query=collection=sc_req_item^active=true^nameINStart Workflow,Start FlowDesigner Flow

    • カタログUIポリシー:/catalog_ui_policy_list.do?sysparm_query=active=true

    • カタログクライアントスクリプト:/catalog_script_client_list.do?sysparm_query=active=true

    • 通知(App Intake系):/sysevent_email_action_list.do?sysparm_query=collection=sc_req_item^active=true^event_name=activate.life.cycle.migration

    • 通知(カタログ本来):/sysevent_email_action_list.do?sysparm_query=collection=sc_req_item^active=true^event_name!=activate.life.cycle.migration

    • 履行タスクのビジネスルール:/sys_script_list.do?sysparm_query=collection=sc_task^active=true^ORDERBYorder

    • REQ完了系のビジネスルール:/sys_script_list.do?sysparm_query=collection=sc_request^active=true^ORDERBYorder

    引用した公式説明を実機で確認する方法

    この記事で引用したapplies_catalogの説明文は、ServiceNowが製品に同梱しているフィールドのドキュメントです。次のURLを自分のインスタンスで開くと、同じ記述が見つかります。

    • フィールドの公式説明(引用元):/sys_documentation_list.do?sysparm_query=name=catalog_ui_policy^hintISNOTEMPTY

    関連記事

     
     
    ServiceNowのPDI(Personal Developer Instance)を実機で観察して、Noteに記事を書いています 実装・運用・教育の現場視点で淡々と記録中です リクエストがあればその記事も書きます 個人の観察日記です

    あなたへのおすすめ