【ServiceNow】g_scratchpadの実例

# 1. はじめに
## 1-1. Server-side scriptとClient-side script
ServiceNowで使用できるスクリプトは、サーバーサイドとクライアントサイドに大別されます。

<dl>
<dt>サーバーサイドスクリプトが使えるModule</dt>
<dd>Business Rule</dd>
<dd>Script Include</dd>
<dt>クライアントサイドスクリプトが使えるModule</dt>
<dd>Client Script</dd>
<dd>UI Policy</dd>
</dl>

サーバーサイドとクライアントサイドのスクリプトでは、使用できるメソッドが異なります。

ただ、例えばクライアントサイドのスクリプトを書いていて、「あのサーバーサイドのメソッドが使いたい…」という場面は多々あります。

そんな時に使える機能の一つが`g_scratchpad`です。

## 1-2. g_scratchpadについて
`g_scratchpad`はGlideFormScratchpadクラスのオブジェクトです。

Display設定のBusiness Ruleに記述することで、サーバーサイドスクリプトで処理したオブジェクトをクライアントサイドに渡すことができます。

今回は、実際にどういう場面で`g_scratchpad`を活かすことができるのか、実例を示しながら書いていこうと思います。

:::note info
g_scratchpadの公式Docは[こちら](https://docs.servicenow.com/bundle/tokyo-application-development/page/app-store/dev_portal/API_reference/GlideFormScratchpadScoped/concept/c_GlideFormScratchpadScopedAPI.html)
:::

:::note info
使用するServiceNowのバージョンはTokyoです
:::

# 2. g_scratchpadの実例
## 2-1. 実例の前置き
ServiceNowにはGroupという機能があり、ユーザーに直接ロールを付与するのではなく、グループを通してロールを付与することができます。

ユーザー⇔グループ⇔ロール
田中さん⇔営業部グループ⇔売上テーブル参照権限・書き込み権限、etc...
佐藤さん⇔人事部グループ⇔人事評価テーブル参照権限・書き込み権限、etc...

というような感じです。

田中さんが営業部から企画部に異動になった場合、権限を一つずつ付け替えるのは面倒ですよね。

その場合、田中さんの所属を営業部グループから人事部グループに変えることで、紐づく権限もまとめて変更できるというわけです。

![dev139037.service-now.com_now_nav_ui_classic_params_target_sys_user_group_list.do%3Fsysparm_query%3Ddescription%253D%25E3%2583%2586%25E3%2582%25B9%25E3%2583%2588%26sysparm_first_row%3D1%26sysparm_view%3D%26sysparm_choice_query_raw%3D%26sysp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/7e3fb2e9-b2b4-5f19-55d3-061d1b8db654.png)

![dev139037.service-now.com_now_nav_ui_classic_params_target_sys_user_group.do%3Fsys_id%3Ddfe4269d471b1110afc6fa37536d4323%26sysparm_record_rows%3D3%26sysparm_record_target%3Dsys_user_group%26sysparm_record_list%3Ddescription%253D%25E3%2583%2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/e7fc245a-a6b4-4f44-8a85-02f622a02e7a.png)


例えばここで、備品管理テーブルなるものがあるとします。

![dev139037.service-now.com_now_nav_ui_classic_params_target_x_880928_my_cust_0_bihin_kanri.do%3Fsys_id%3D-1%26sys_is_list%3Dtrue%26sys_target%3Dx_880928_my_cust_0_bihin_kanri%26sysparm_checked_items%3D%26sysparm_fixed_query%3D%26sysparm_grou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/53153f84-cdd7-a6bc-358f-faadd5e16e92.png)


- 所属部
- 所属課
- 備品種別
- 管理番号

を記入して登録する運用です。（所属部、所属課、備品種別はプルダウンからの選択方式）

ところで、営業部には一課と二課がありますが、人事部は課がありません。

営業部の人が備品管理テーブルのフォーム画面を開いた場合には「所属課」フィールドが活性化しており、人事部の人が開いた場合には非活性になっている、という制御を行う必要が出てきました。

## 2-2. ユーザーの所属グループを返却するメソッド
「所属課」フィールドの活性/非活性を制御するには、ユーザーの所属するグループを取得する必要がありそうです。

フィールドの活性/非活性の制御はClient ScriptかUI Policyで実装できます。今回はUI Policyで実装することにしましょう。

UI Policyで使用できるスクリプトは、クライアントサイドスクリプトです。

クライアントサイドスクリプトで使用できるメソッドで、ユーザーの所属するグループを取得できるものはあるでしょうか。

実は、ありません。

`g_user.hasRole()`という、ロールを持っているか否かをTrue/Falseで返却してくれるメソッドはあるのですが、グループに関するメソッドはクライアントサイドにはないのです。

逆に、サーバーサイドスクリプトには、`isMemberOf()`というGlideUser APIのメソッドがあります。グループに所属しているか否かをTrue/Falseで返却してくれます。

`isMemberOf()`メソッドの結果をクライアントサイドで使用する際に、g_scratchpadが使用できるというわけです。

## 2-3. g_scratchpadの設定
実際の使用方法を見ていきましょう。

Business Ruleを作成します。Advancedにチェック、WhenはDisplayに設定します。

![dev139037.service-now.com_$studio.do_sysparm_transaction_scope=e2b550903fba111058d88a9b921858e6&sysparm_nostack=true&sysparm_use_polaris=false.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/60e2fcd1-b56a-3ed1-ea06-c821e68f34e6.png)

Advancedタブに以下のスクリプトを記入します。

```javascript
(function executeRule(current, previous /*null when async*/) {
	
	g_scratchpad.isMemberOfJinjibu = gs.getUser().isMemberOf('人事部');

})(current, previous);
```

![dev139037.service-now.com_$studio.do_sysparm_transaction_scope=e2b550903fba111058d88a9b921858e6&sysparm_nostack=true&sysparm_use_polaris=false (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/fb6ee82a-4fe4-c121-e688-876f67121ee4.png)


これで、`g_scratchpad.isMemberOfJinjibu`に、ユーザーの所属グループが人事部だった場合はTrueが、それ以外だった場合はFalseが格納されるようになりました。

## 2-4. クラアントサイドの設定
今回はUI Policyを使ってフォーム画面の表示制御を行います。

UI Policyの設定画面で、Tableは該当テーブルを指定し、Short Descriptionに適当な説明を記入します。

ScriptタブのRun scriptsにチェックを入れ、以下のスクリプトを記入します。

```javascript
function onCondition() {
	if (g_scratchpad.isMemberOfJinjibu) {
		g_form.setMandatory('shozokuka', false);
		g_form.setReadOnly('shozokuka', true);
	}
}
```

![dev139037.service-now.com_$studio.do_sysparm_transaction_scope=e2b550903fba111058d88a9b921858e6&sysparm_nostack=true&sysparm_use_polaris=false (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/9e09943c-d610-df33-259e-da77dfb4b986.png)

`g_scratchpad.isMemberOfJinjibu`がTrueだった場合、「所属課」フィールドを必須でなくし、読み取り専用に設定します。

## 2-5. 動作確認
田中さんは営業部グループ、佐藤さんは人事部グループに所属しています。

「代理操作ユーザー」で田中さん、佐藤さんそれぞれになりすましを行い、フォーム画面を確認してみます。

まず、田中さんの場合
![dev139037.service-now.com_now_nav_ui_classic_params_target_x_880928_my_cust_0_bihin_kanri.do%3Fsys_id%3D-1%26sys_is_list%3Dtrue%26sys_target%3Dx_880928_my_cust_0_bihin_kanri%26sysparm_checked_items%3D%26sysparm_fixed_query%3D%26sysparm_ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/fd72e08c-87b6-bd3c-170e-ea6331229140.png)

特に表示制御は行われていません。

次に、佐藤さんの場合
![dev139037.service-now.com_now_nav_ui_classic_params_target_x_880928_my_cust_0_bihin_kanri.do%3Fsys_id%3D-1%26sys_is_list%3Dtrue%26sys_target%3Dx_880928_my_cust_0_bihin_kanri%26sysparm_checked_items%3D%26sysparm_fixed_query%3D%26sysparm_ (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/604835/48cace5c-b3cc-5f3d-9416-304b3e01c05a.png)

「所属課」フィールドが必須でなくなり、グレーアウトして読み取り専用になっています。

無事、想定通りの挙動となりました。

# 3. まとめ
以上、`g_scratchpad`の実用例でした。

上記の例はUI Policyだけでも制御可能ですし（所属部に人事部が選ばれた場合、所属課を制御）、ACLでも実現できるので、あまり良い例ではなかったかもしれません…

クライアントサイドスクリプトで使いたい場面があるけど、サーバーサイドスクリプトにしかないメソッドは何かないかなーと考えて、パッと思い付いたのが`isMemberOf()`でした。

日本語で`g_scratchpad`の具体的な使用例の記事がなかったので、こんな感じで使えるよ、というのを書いてみた次第です。

業務で使う場面もそれなりにあるかと思いますので、少しでも参考になれば幸いです。