[ServiceNow] Client Side ScriptからFlowを呼び出す

# はじめに

ServiceNowのFlow機能は、従前のWorkflowに代わる新しい機能です。FlowはFlow Designerで定義でき、必ずしもリッチなScriptが書けなくても、ローコード・ノーコードで作れます。
Flow Designerは、ServiceNow上で、ビジネスフロー要件を実現する強力なツールですが、作成されたFlowは、OOTBでは、UI ActionなどのClient Side Scriptから呼び出すことはできません。
ここでは、ServiceNowインスタンス上で、基本的な設定をして、実際に簡単なFlowをUI Actionから呼び出してみます。

# ACLの設定

最初に、Client Side ScriptがFlowを呼び出せるように、ACLを新規作成します。
ACLを以下のように設定します。

* Type: client_callable_flow_object
* Operation: execute
* Application: Global
* Name: (適当)（例: Trigger flow from client script）
* Requried roleとCoditionとScript: (適当)
    * 特にRoleやConditionの制限をせず、Login Userのみに許可する場合は、下記の様に設定します。

![ACL_ client_callable_flow_object.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/cabd10d1-4ecd-8b2d-eaeb-14eb5ccdea89.png)

```javascript:Script
answer = gs.getSession().isLoggedIn();
if (!answer) {
    answer = gs.getProperty('glide.security.allow_unauth_roleless_acl', false);
}
```

# Flowの作成

Flow DesignerでFlowを作成します。ただし、FlowはTriggerを含む設定なので、CallableなFlowは、実際にはSub Flowになります。
ここでは、UI ActionからSub Flowを呼び出す検証なので、どんなロジックでも良いのですが、例としてsys_userのsys_idを引数に取り、そのUserのいくつかのField値を返すSub Flowを作成します。以下が例ですが、環境独自のUser Fieldを含んでいます。

![SubFlow_GetUserInfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/158c6e92-2a38-e257-cd5b-d48e0f92d88d.png)

Flow Designerの便利な機能として、作成したSub Flowを呼び出すためにCode Snippetを自動生成してくれます。右上の三点 （…）アイコンから、Create code snippetを選択すると、Server Side用とClient Side用の標準的なSub FlowをCallするScriptが表示されます。

![SubFlow_CodeSnippet_Client.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/9d56796a-14ca-65fd-999c-4e1598564546.png)

# UI Actionの作成

新規のUIアクションを作成して、Code Snippetをコピーして、多少のロジックを整形します。ここでは、Formで開いているUserのManager fieldの値を取って、そのManagerのUser情報を取得して、JavaScriptのAlert関数で表示しています。

![UI_Action_Get_Manager_Info.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/15c919ce-1d1e-76f9-b088-e254ed463528.png)

```JavaScript:Script
function Get_Manager_Info() {
	var inputs = {};

	inputs['user_sys_id'] = g_form.getValue('manager'); // String 

	GlideFlow.startSubflow('global.getuserinfo', inputs)
		.then(function(execution) {
			return execution.awaitCompletion();
		}, errorResolver)
		.then(function(completion) {

			var status = completion.status;

			// Available Outputs:
			var outputs = completion.outputs;		
			var user_company = outputs['user_company']; // String		
			var user_compan_ja = outputs['user_compan_ja']; // String		
			var user_email = outputs['user_email']; // String		
			var user_name = outputs['user_name']; // String

			var messageBody = "";
			messageBody += getMessage("Name") + ": " + user_name + "\n";
			messageBody += getMessage("Campany") + ": " + user_company + "\n";
			messageBody += getMessage("Campany (Ja)") + ": " + user_compan_ja + "\n";
			messageBody += getMessage("Email") + ": " + user_email;
			
			alert(messageBody);
		});

	function errorResolver(error) {
		// Handle errors in error resolver
	}
}
```

# 実行結果

関連リンクのGet Maneger Infoをクリックすると、次のようにAlertでUserとしてのManagerの情報を表示されます。
ちなみに、このManagerであるUser (Deleted User 01) は、Active:Falseで論理削除されており、通常は表示できないUserですが、Sub Flowをログインユーザーの権限ではなくSystem Userで実行しているため、強制的に表示することが可能です。これはFlowがBusiness Ruleではできない利点の一つです。
なお、一般的にFlowは処理が遅いので、Business RuleでできることをFlowで実装することは、市民開発（ユーザー部門によるEUC開発）でもない限りお勧めしません。

![Alert_Get_Manager_Info.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/8ee72bcb-2a2f-5616-5edb-15e0c918494a.png)