ServiceNowのタスク(Task)テーブルでは、状況(State)項目を変更すると自動でアクティブ(Active)項目の値も変更されます。この仕組みと、タスク継承テーブルに新たに非アクティブと判定されるStateを追加する方法を説明します。
タスク継承テーブルに新たに非アクティブと判定されるStateを設定する方法だけを知りたい方はこちらのページ内リンクをどうぞ
状況(State)とアクティブ(Active)の関係の具体例
まずは、状況(State)とアクティブ(Active)の関係の具体例を見てみます。標準のインシデント(Incident)テーブルの状況(State)項目には、次の6つのStateが存在し、Stateの変更に応じてアクティブ(Active)項目の値も自動で変更されます。
状況(State)とアクティブ(Active)を制御するロジック
状況(State)とアクティブ(Active)を制御するロジックの概要は次のようになっています。
状況(State)とアクティブ(Active)を制御する4つのロジック
タスク(Task)テーブルには、状況(State)とアクティブ(Active)を制御するロジックとして、次の4つのビジネスルール(Business Rule)が存在します。
動く順番 | 名前 | どんな時に動くか | 何をするか |
1 | Task Active State Management | 状況(State)が変更されたとき | 状況(State)が非クローズStateからクローズStateに変更された場合は非アクティブに、逆の時はアクティブにする |
2 | mark closed | 状況(State)がクローズStateになったとき | 非アクティブにする ※ Task Active State Managementとの違いは後述 |
3 | task closer | 状況(State)が非クローズStateなのに非アクティブに変更されたとき | 状況(State)をクローズStateに変更する |
4 | task reopener | 状況(State)がクローズStateなのにアクティブになった、または非アクティブなのに状況(State)がオープン(Open=1)になったとき | 状況(State)をオープン(Open=1)に変更しアクティブにする |
なお、この表ではアクティブ(Active)項目をtrue/falseにすることを、それぞれアクティブにする/非アクティブにすると表現しています。
クローズStateの判定方法は後述するとして、今の段階ではこれらのロジックによって、状況(State)とアクティブ(Active)の一方が変更されると、他方も連動して変更されるようにになっていることを理解いただければ大丈夫です。
クローズと判定される状況(State)
前述の各ロジックにおけるクローズ状況の判定は、”TaskStateUtil”スクリプトインクルード(Script Include)によって行われており、各処理によって少しずつ判定ロジックが異なるので、そちらを説明します。
Task Active State Management
“Task Active State Management”ビジネスルール(Business Rule)では、該当のテーブルの状況(State)項目のclose_states属性(Attributes)で設定されているStateをクローズStateと判定します。
標準のタスク(Task)テーブルの状況(State)項目にはclose_states属性(Attributes)が設定されておらず、設定する場合はDictionary Override機能を用いることになります。例として、インシデントテーブルのclose_statesは次のように設定されています。なお、インシデントテーブルの場合、State=7はクローズを表し、State=8はスキップを表します。
mark closed, task closer
“mark closed”および“task closer“ビジネスルール(Business Rule)では、上述のTask Active State Managementと同様に該当のテーブルの状況(State)項目のclose_states属性(Attributes)を確認し、設定されていればそのステータスをクローズステータスと判定します。設定されていない場合はシステムデフォルトのクローズステータスであるState=3(完了してクローズなど), 4(未完了でクローズなど), 7(スキップしてクローズなど)をクローズステータスと判定します。各Stateの値(3, 4, 7)がどのラベルになっているかは、タスクを継承した各テーブル内で変更されている可能性があるため、カスタマイズを行う場合は改めて確認してください。
上述の動作より、該当のテーブルの状況(State)項目のclose_states属性(Attributes)が設定されていれば、mark closedの前にTask Active State Managementによって非アクティブにされるため、基本的にはこのビジネスルールが動くことはありませんが、close_state属性が設定されていない場合に、システムデフォルトのクローズStateを用いて非アクティブにするという役割があります。
システムデフォルトのクローズStateは”TaskStateUtil” Script Include内にハードコードされている
なお、システムデフォルトのクローズStateはSystem Propertyなどではなく”TaskStateUtil”というScript Includeの中にハードコードされているため、スクリプトインクルード(Script Include)をカスタマイズしない限り変更はできません。OOTBへの変更になるためお勧めしません。
次にコードを示します。(こちら2022年10月のTokyoバージョン時点の情報で、システム設計としてはPropertyに切り出すのが綺麗なので、今後のバージョンアップでいつの間にかプロパティ化されている可能性はあります。)
SYSTEM_INACTIVE_STATES : [3, 4, 7], // task default inactive/close states
task reopener
“task reopener”ビジネスルール(Business Rule)では、”mark closed”および”task closer”の時とほぼ同じ判定ロジックですが、スキップしてクローズなどを表すState=7のときはクローズStateとして判定されないことに注意が必要です。
新たにクローズStateを設定する手順
ここまで読めば詳しい方は設定できると思いますが、タスクを継承したテーブルにおいて、新たにクローズStateを設定する手順を示します。
- 状況(State)項目のDictionaryレコードを探す
- 新しいクローズStateを作成する
- Dictionary Override機能で状況(State)項目のclose_states属性(Attribute)をOverrideし新たにクローズStateと判定させたいStateを設定する
1. 状況(State)のDictionaryレコードを探す
まず、状況(State)の設定を行うためのDictionaryレコードを探します。わかっている人は、好きな方法で探してください。ここでは探し方の一例を示します。
- メニュー > System Difinition > Tablesより、当該のテーブル定義を探して遷移する
- テーブルの定義から、状況(State)項目を探す
※ この時、該当テーブルがタスク(Task)テーブルを継承していない場合は本記事の対象外なので注意です
2. 新しいクローズStateを作成する
状況(State)項目の定義を開いたら、新たなクローズStateを定義します。こちらもわかっている方は好きな方法で作成してください。
- 画面下部のChoicesタブの”New”をクリックします
- Stateを作成する
※ この際、標準のStateとValueが被らないように注意してください
3. Dictionary Override機能で状況(State)項目のclose_states属性(Attribute)をOverrideし新たにクローズStateと判定させたいStateを設定する
- 状況(State)項目の定義を開いたら、画面下部のDictionary Overrideタブの”New”をクリックします
- Attribute項目をOverrideして、close_statesを設定します
※ 複数のStateを設定する場合は、セミコロン(;)で区切ります(なお、ServiceNowにおける一般的な区切り文字はカンマ(,)ですが、これは複数のAttributeを設定する際の区切りとしてカンマ(,)を使うため、これと区別するためセミコロン(;)が使われていると思われます)
※ 上述のmark closed Business Ruleの動作から、この属性が設定されていると、システムデフォルトのクローズState(3, 4, 7)は無視されるため、システムデフォルトのクローズStateの場合もクローズさせたい場合は、それらのStateも含めて記載しておく必要があります
こちらで新たな状況(State)をクローズStateとして設定できます。
設定を検証するときの注意
設定を検証する際は、インシデント(Incident)テーブルなど、タスク(Task)テーブルに加え多くの追加のロジックが含まれるテーブルを使うと、それらの影響を受けてしまう可能性があります。
そのため、設定を検証する際は、タスク(Task)テーブルに対してほとんど変更が加わっていない標準の継承テーブルであるチケット(Ticket)テーブルを用いるのがお勧めです。
状況(State)とアクティブ(Active)を制御するロジックの補足
最後に、上述の説明で簡略化していた部分について、少し補足をしておきます。
各ロジックにおいて例外テーブルが設定されている
上述の4つのビジネスルール(Business Rule)では、次のように、特定のテーブルでは動作しないように設定されています。
Order | Name | 例外テーブル |
50 | Task Active State Management | Demand[dmn_demand]テーブル |
800 | mark closed | Demand[dmn_demand], Incident[incident], Problem[problem]テーブル |
900 | task closer | Demand[dmn_demand], HR Task[sn_hr_core_task]テーブル |
901 | task reopener | Demand[dmn_demand]テーブル |
task closerで状況(State)が変更される際に用いられるState
task closerでは、上述の通り、状況(State)が非クローズStateのであるにも関わらず、アクティブ(Active)を非アクティブ、つまりfalseに変更されると、状況(State)をクローズStateに変更します。
この際に、どのクローズStateに変更するかは、該当のテーブルのState(状況)項目のdefault_close_state属性(Attribute)が設定されている場合はそのStateが用いられ、設定されていない場合は、システムデフォルトの完了してクローズなどを表すState=2が用いられます。
この設定も、close_statesと同様にDictionary Overrideによって変更が可能です。
task reopenerで状況(State)が変更される際に用いられるState
こちらはtask closerとほぼ同じ動きをするのですが、少し複雑な設定になっているのでコードを引用しながら説明します。
“TaskStateUtil” Script Includeでは次のように、コンストラクタ内でState(状況)項目のdefault_work_state属性(Attribute)で設定されている値を見に行っていて、初期化時点では、default_work_state属性(Attribute)があればその値に、そうでなければシステムデフォルトのState=2に設定されています。
// (引用者コメント) 定数定義部内
ATTR_DEFAULT_CLOSE : "default_close_state",
SYSTEM_DEFAULT_WORK : 2, // task work in progress state
// (引用者コメント) コンストラクタ内
initialize : function(/*GlideRecord*/ task) {
// (引用者中略)
this._getDefaultWork();
// (引用者中略)
},
// (引用者コメント) コンストラクタから呼び出されるDefaultWork Stateの初期化関数
_getDefaultWork : function() {
var value = this.stateElement.getAttribute(this.ATTR_DEFAULT_WORK);
if (value)
this.defaultWork = value;
else
this.defaultWork = this.SYSTEM_DEFAULT_WORK;
},
しかし、”task reopener” Business Ruleにおいては次のような呼び出され方をしているため、結局、getDefaultWorkState()の戻り値としては、default_work_state属性(Attribute)があればその値に、そうでない場合はState=1が返ることがわかります。
current.state = new TaskStateUtil(current).setDefaultWorkState(1).getDefaultWorkState();
getDefaultWorkState : function() {
return this.defaultWork;
},
setDefaultWorkState: function(defaultWorkState) {
// See if a value exists for the default work state attribute
var value = this.stateElement.getAttribute(this.ATTR_DEFAULT_WORK);
// If it does then use it, else use the passed-in value
if (value)
this.defaultWork = value;
else
this.defaultWork = defaultWorkState;
// Allow the method to be chained with other methods
return this;
},
この設定も、close_statesと同様にDictionary Overrideによって変更が可能です。
標準のタスク継承テーブルでは追加のロジックが設定されていることがある
例えばインシデント(Incident)テーブルなどの標準テーブルでは、タスク(Task)テーブルのロジックに加え、同名のmark_closedが定義されていたり、incident autocloseという追加のロジックが入っていたりするので、継承先テーブルの追加ロジックについても注意が必要です。
以上です。タスクテーブルは奥が深いですね。
コメント