ブログ

2021/03/24
【プリザンター】 第89回)サーバスクリプト#5 申請ワークフローを作成(後編)

作成するスクリプト他の概要

こんにちは、CCSの田中です。

前回は、前編としてテーブルの作成まで説明しました。今回はサーバスクリプトを作成していきたいと思います。
サーバスクリプト以外に、スクリプトやスタイルも設定していますので、そちらも説明していきます。

今回作成するものは以下になります。
3)以降がサーバスクリプトになります。

1)disabledのスクリプト:項目を非活性にする
2)ボタン表示のためのスタイル:承認ボタン等を表示する
3)決裁者の決定
4)承認時プロセスの更新
5)自動メール送信
6)承認・否決ボタンの設置
7)決裁後の読み取り専用変更

作成するスクリプト他の詳細

さて、メインのサーバスクリプトについて説明していきましょう。
スクリプト自体の量が多いため、細かくは説明できないことをご了承ください。
サーバスクリプト以外にも、通常のクライアント側のスクリプトとスタイルも設定を行います。

最初にクライアント側のスクリプトです。テーブルの管理から「スクリプト」タブで以下を設定してください。
これは、ユーザが直接編集の必要がないところは非活性にするためのスクリプトです。
各項目のコントロールCSSで disabledを指定したところが有効になります。
出力先は、「新規作成」「編集」にチェックを入れます。

<disabledのスクリプト>


$p.events.on_editor_load = function () {
$('.disabled')
.prop('disabled', true)
.css('background-color', '#f5f5f5');
}


次にスタイルです。テーブルの管理から「スタイル」で以下を設定してください。
これは、承認ボタン等を表示するためのスタイルです。
出力先は、「全て」にします。

<ボタン表示のためのスタイル>

.approval-control {
float: right;
margin-right: 10px;
}


それでは本番のサーバスクリプトです。
1つずつ記載してきます。

決裁者の決定では、申請者が所属している部署の部長グループに入っている人が承認者となるスクリプトです。
今回複数名の時は考慮はしておりません。

条件:レコードの読み込み時
<決裁者の決定>

try {
context.Log('決裁者の決定');
context.UserData.FinCode = 900;
model.ClassC = manager(context.DeptId, 3).UserId;

function manager(deptId, groupId) {
let members = Array.from(groups.Get(groupId).GetMembers());
for (let i = 0; i < members.length; i++) { if (members[i].UserId > 0) {
let user = users.Get(members[i].UserId);
if (user.DeptId === context.DeptId) {
return user;
}
}
}
}

} catch (e){
context.Log(e.stack);
}


上記で別の申請者が申請した場合に、context.DeptIdを使っているとログインしている人の所属長に変わってしまうケースがあったため、以下のように修正しています。
<(修正版)決裁者の決定>

try {
context.Log('決裁者の決定');
context.UserData.FinCode = 900;
let owneruser = users.Get(model.Owner);
model.ClassC = manager(owneruser.DeptId, 3).UserId;

function manager(deptId, groupId) {
let members = Array.from(groups.Get(groupId).GetMembers());
for (let i = 0; i < members.length; i++) { if (members[i].UserId > 0) {
let user = users.Get(members[i].UserId);
if (user.DeptId === deptId) {
return user;
}
}
}
}

} catch (e){
context.Log(e.stack);
}


2つ目は承認時にプロセスの更新です。申請時は自分の所属部長に現在位置が移るので、現在位置に部長を入れ、承認が完了の場合は決済日欄に今日の日付をいれるようにします。また、申請者に現在位置を戻すため、現在位置を申請者に設定します。

条件:更新前
<承認時プロセスの更新>

try {
context.Log('承認時のプロセス更新');
context.Log('ControlID=' + context.ControlID);
switch (context.ControlId) {
case 'Approval':
model.Status = 200;
model.Manager = manager(model.ClassC);
break;
case 'ApprovalM':
model.Status = status(900);
model.DateD = new Date();
break;
}
if (model.Status === 900) {
model.Manager = model.Owner;
}

function status(code) {
if (context.UserData.FinCode === code) {
return 900;
} else {
return code;
}
}

function manager(userId) {
var user = users.Get(userId);
if (user) {
return user.UserId;
} else {
return model.Manager;
}
}
} catch (e) {
context.Log(e.stack);
}


3つ目は、メール送信です。
「通知」機能でメール送信ができますが、ここではスクリプトで実現しています。
それぞれの状態にあった送信先に、それぞれの文章でメールを送信するように設定します。

条件:更新後
<自動メール送信>

try {
context.Log('自動メール通知');
let user = users.Get(model.Manager);
let notification = notifications.New();
if (user.UserId > 0) {
notification.Address = '[User' + user.UserId + ']';
switch (model.Status) {
case 200:
notification.Title = '承認依頼:' + model.Title;
notification.Body = user.Name + '殿:掲題の承認依頼が届いています。';
notification.Send();
break;
case 900:
notification.Title = '可決:' + model.Title;
notification.Body = user.Name + '殿:掲題の申請が可決されました。';
notification.Send();
break;
case 920:
notification.Title = '否決:' + model.Title;
notification.Body = user.Name + '殿:掲題の申請が否決されました。';
notification.Send();
break;
}
}
} catch (e){
context.Log(e.stack);
}


4つ目はボタンの設置です。
新規作成直後は、「申請」ボタン、申請後は承認者欄に「承認」と「否決」ボタンを表示します。

条件:画面表示の前
<承認・否決ボタンの設置>

try {
context.Log('承認・否決ボタンの設置');
if (model.Manager === context.UserId) {
switch (model.Status) {
case 100:
if (context.Action !== 'new') {
columns.Body.ExtendedHtmlAfterField = buttons('', '申請');
}
break;
case 200:
columns.DescriptionA.ExtendedHtmlAfterField = buttons('M', '承認');
break;
}
}

function buttons(suffix, text) {
let html = '<div class="approval-control"><button id="Approval' + suffix + '" class="button button-icon validate" type="button" onclick="if (!confirm(\'' + text + 'してよろしいですか?\')) return false;$p.send($(this));" data-icon="ui-icon-circle-triangle-e" data-action="Update" data-method="put">' + text + '</button></div>';
if (suffix !== '') {
html += '<div class="approval-control"><button id="Veto' + suffix + '" class="button button-icon validate" type="button" onclick="if (!confirm(\'否決してしてよろしいですか?\')) return false;$p.send($(this));" data-icon="ui-icon-circle-close" data-action="Update" data-method="put">否決</button></div>';
}
return html;
}
} catch (e){
context.Log(e.stack);
}


5つ目は、決裁後にレコードを読み取り専用にする処理です。
状態が完了になったものは、読み取り専用に設定しています。

条件:画面表示の前
<決裁後の読み取り専用変更>

try {
context.Log('完了したものは読み取り専用');
if (model.Status === 900) {
model.ReadOnly = true;
}
} catch (e) {
context.Log(e.stack);
}

まとめ

さて、いかがでしたか?

今回は前回とあわせて2回にわたりサーバスクリプトの5回目として実践的なワークフローを作成してみました。
記載の通りインプリム社から出ているサンプルを参考にしておりますが、それよりはシンプルなものにしています。
プリザンターでの申請ワークフローは複雑にしすぎると、メンテナンスが大変になるためシンプルなものでよいのではないかと思っています。

導入の支援、スクリプト開発などでお困りの場合は、当社で支援もいたします。プリザンター逆引き辞典PDF版やスタイル・スクリプトサンプル集PDF版の販売もしております!

☆☆ブログ内容への質問や追加説明をご希望の方は
【問い合わせフォーム】 こちら からお気軽にお問い合わせください☆☆

PAGE TOP