ServiceNowの会社テーブルで自社を特定する方法

## はじめに
### 会社テーブル
ServiceNowには会社（`core_company`）というテーブルがあり、顧客、取引先、親会社や子会社、グループ会社などを格納することができます。[^1]

### 会社テーブルに自社レコードを登録する意味
ところで、上に挙げたような関係先だけでなく、自社自身を会社テーブルに登録しておくと、ユーザーの所属企業として自社を指定することができるようになります。この属性値の設定によって、例えば、自社ユーザーのみ閲覧可能なACLを作成したり、自社ユーザーのみ指定可能な参照修飾子を作成したりできるので、このような自社の登録ということは幅広く行われていると思います。

では、この自社レコード、どのようにインスタンスに登録し、どのように識別しているでしょうか？この小文では自社レコードをテーマに扱いますが、基盤データテーブルにおいて特別な意味を持つ単一のレコードを持ちたいときには同じ議論になるので、その意味でも理解しておくと便利です。

## 自社レコードの識別方法
自社レコードを識別する方法にはいろいろ考えられます。素朴なものから順番に考えてみます。

### いちばん素朴な実装
一番簡単なのは、自社の名称で識別する方法で、例えばフィルター条件を設定するならこのように会社名が自社の名称であるレコードを抽出することができます。

![素朴な実装](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/bd8b3d5b-4e36-3d81-30d6-63efb1d9d69c.png)

この方式はある程度機能しますし実装は簡単ですが、問題があります。最大の問題は会社テーブルにおいて、名前がユニークになる保証がなく、同一名のレコードを複数登録できることです[^2]。また、自社名を変更するとその都度実装したフィルター条件を修正しなければならなくなり、運用負荷が非常に大きくなります。

### Sys IDの利用
必ず単一のレコードを取得できる方法としては、Sys IDを利用する方法があります。自社を表す会社レコードのSys IDを使って会社テーブルを検索すれば確実に自社のレコードを取得できます。

![Sys IDによる識別](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/91400489-c324-3175-805c-7c8f6576536e.png)

しかしこの方法にも問題があります。レコードのSys IDはインスタンスによって異なる可能性があるため、Sys IDを直接設定したりハードコーディングしたりすると、アプリケーションファイルの可搬性が失われてしまいます。可搬性を確保するために複数インスタンス間で自社レコードが確実に同じSys IDを持つようにするには、それなりの運用上の配慮が必要になります。

また、スクリプトならいざ知らず、生のSys IDを扱うことはワークフローのユーザーにとっては行いづらい業務になることも見過ごせません。

### システムプロパティの利用
複数インスタンスで異なるSys IDを持つレコードへの参照を、インスタンス間で可搬にするための方法として、Sys IDをシステムプロパティに設定する方法があります。

システムプロパティテーブル（`sys_properties`）に自社レコードのSys IDを表す項目を追加し、「プライベート」にチェックを入れて有効にします[^3]。そして、値に当該インスタンスにおける自社レコードのSys IDをセットします。

![Sys IDをもつプロパティ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/8e592a3a-ebb7-f94e-cc2b-8929ae601b7d.png)

これによって、スクリプトからはシステムプロパティを取得することで、どのインスタンスでも確実に自社レコードを識別することができます。

```JavaScript:Sample
gs.getProperty('mycompany.sys_id');
```

しかし、これにもまた難があります。システムプロパティから値を取得するにはスクリプティングが必要であり、IT専門ではないユーザーにとって使いづらい問題は解消していません。

いろいろと検討してきましたが、どの方法も一長一短であることがわかってきました。

## 会社テーブルの「プライマリ」フィールド

実はこの問題にはインスタンス側で答えが用意されています。会社テーブルが持つ「プライマリ`primary`」というTrue/False型のフィールド（つまりチェックボックス）を利用します。このチェックボックスはOOTBの状態では表示されていませんので、フォームレイアウトを変更することで表示できます。

![フォームレイアウトを変更してプライマリフィールドを表示する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/e393a1f3-c451-0a1a-726f-a638dc2c18ac.png)

このチェックボックスがチェックされている（`true`がセットされている）レコードを、ServiceNowでは自組織を表すレコードとみなします。

~~インスタンスによっては、プロヴィジョニングが完了した初期状態ですでにプライマリフィールドが`true`にセットされたレコードが用意されていることがあります（*Your name here*という名前が付いているレコードです）。その場合はそのレコードを編集して自社を正しく表すようにしてください。~~
**このレコードを用いると問題が起きるようです[^7]。これは使わずに新しいレコードを使ってください。**

![プライマリにチェックを入れる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/ce726cb7-94a5-a61f-db50-c0a9eb38904c.png)

なお、会社テーブルに対しては、1レコードのみプライマリフィールドを`true`にできるようなビジネスルール`validate_only_one_primary`が動いていて、2件以上の自社レコードはエラーになって作成できないようになっています。なので、自社レコードが2レコード以上できてしまう心配はありません。

## 利用方法

プライマリフィールドを使って自社レコードを用意できれば、その後の利用は簡単です。会社テーブルから抽出するときに、プライマリフィールドを使って指定すれば簡単に1件のレコードを抽出できます。

![プライマリフィールドによる抽出](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/513c0b4c-f9c4-a14f-ee5c-45208c6e4209.png)

ACLや参照修飾子の実装においても簡単に利用できます。ドットウォークする必要がありますが、スクリプト不要なので、IT専門でないユーザーでも簡単に使えると思います。

また、プライマリが`true`の会社レコードにはもう一つ重要な意味があります。このレコードは、アプリケーションナビゲーターの **All > System Properties > My Company （すべて > システムプロパティ > 会社）** メニューの参照先にもなっています。

![My Companyメニュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/f8101fc5-b0c3-9091-a842-1295f0bf23bd.png)

このメニューを開くと、自社レコードがMy Company（自分の会社）ビューという特別なビューで表示され、U16バナーイメージとバナーテキストという2つのフィールドだけが表示されます。

![自社レコード（My Companyビュー）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491737/ae0d7527-d0a3-7369-9b54-af21d4f930e9.png)

このフィールドに設定したバナー画像とバナーテキストは、インスタンスのバナー画像[^4]およびバナーテキスト[^5]に表示されます。バナー画像とバナーテキストはシステムプロパティで設定することもできますが[^6]、自社レコードへの設定が優先します。（正式には、バナーテキストについては優先するのではなく、システムプロパティを自社レコードへの設定値で上書きする動作をします）

これによって、バナー画像やバナーテキストを簡単に更新することもできます。

## まとめ
自社を表すレコードを会社テーブルに登録するときは、プライマリフィールドをつかって、唯一特別な自社レコードとして識別することができます。自社を特定するにはこの方法が最も簡単で、スクリプト開発も不要で、ユーザーフレンドリーでもあります。

また、このようなチェックボックスと、重複防止のビジネスルールを使った単一レコード識別の仕組みは他の用途にも応用できます。


[^1]: 場合によっては官公庁や地方公共団体、非営利団体、その他さまざまな法人を格納することもあり、その場合は「会社」という名前には合わないですが、他に利用できるテーブルもないのでそこはやむを得ないと思います。
[^2]: 別記事で特定フィールドをユニークにする方法を比較検討しています。 https://qiita.com/yujiarakitokyo/items/063944ab95f27de873d4
[^3]: Privateのチェックを入れることによって、そのプロパティを、インスタンスごとに異なる値を持つ環境変数のように使うことができます。入れない場合は更新セットの捕捉対象になり、インスタンス間で同一の値を持つことが原則になります。
[^4]: 左上角に表示されるロゴマーク。
[^5]: バナー画像にマウスカーソルを重ねた時に表示されるテキスト。
[^6]: https://docs.servicenow.com/ja-JP/bundle/vancouver-platform-user-interface/page/administer/navigation-and-ui/task/t_CustomizeTheLogoInSysProps.html
[^7]: 内部的にデモデータであるという扱いになっているようで、デモデータ削除をNow Supportから依頼すると削除されてしまいます。