コンテンツにスキップ

saved

概要

サーバスクリプトで使用可能な更新前の「レコード」の情報をもつオブジェクトです。プロパティを使用し項目の値の読み取りが行えます。

制限事項

  1. 「更新前」の条件で意味を持ちます。その他の条件では、参照できても model と同等となります。
  2. 添付ファイル項目、コメント項目は使用できません。
  3. 項目のアクセス制御で「読取り権限」の無い項目は取得できません。
  4. 項目のアクセス制御で「更新権限」の無い項目は値を代入しても画面の表示を変更できません。
  5. 画面上に存在しない項目は取得できません。画面上にない項目を取得するには「AlwaysGetColumnsオブジェクト」を使用してください。

プロパティ

No プロパティ名 type 説明
1 IssueId / ResultId long ID項目
2 SiteId long 「サイトID項目」
3 Creator int 作成者項目
4 CreatedTime DateTime 作成日時項目
5 Updator int 更新者項目
6 UpdatedTime DateTime 更新日時項目
7 Ver int バージョン項目
8 Title string タイトル項目
9 Body string 内容項目
10 StartTime DateTime 開始項目
11 CompletionTime DateTime 完了項目
12 WorkValue decimal 作業量項目
13 ProgressRate decimal 進捗率項目
14 RemainingWorkValue decimal 残作業量項目
15 Status int 状況項目
16 Manager int 管理者項目
17 Owner int 担当者項目
18 Locked bool ロック項目
19 ClassA~ string 分類項目
20 NumA~ decimal 数値項目
21 DateA~ DateTime 日付項目
22 DescriptionA~ string 説明項目
23 CheckA~ bool チェック項目

メソッド

メソッドはありません。

使用例

「更新前」であっても model には、画面や CSV から送信されたデータで変更された値(これからデータベースに保持される値)が保持されています。
このため、model.Status が何であるかを判定するサーバスクリプトでは、ある状態に変更されたときだけ動作させたい処理を実現することが難しいです。
下記の例では状況項目が変化したかを saved を使って判定しています。

JavaScript(サーバスクリプト)
const prevStatus = saved.Status;
const currentStatus = model.Status;
if(prevStatus !== currentStatus) {
  context.Log(`Status just has been changed.`);
}

同様にして、特定のデータ項目の変更前後の監視を実現することができます。

また、更新後に同様の判定を行いたい場合には context.UserData に変更があったことを検知する共有変数を保持することで実現できる可能性があります。

ステータスに対して羃等(idempotent)な処理については、このような対応をする必要はありません。

サンプルコード

Note

コード内の【 ... 】は適宜修正してください。

1. 承認されたときに限って申請内容を商品マスタへ反映する

「商品登録申請」テーブルで新しい商品や変更内容を申請し、承認されたら、その内容を別サイト「商品マスタ」へ商品コードをキーにして反映します(同じ商品コードがあれば更新、無ければ新規作成)。サーバスクリプトを「更新前」に登録し、saved.Status(更新前の状況)とmodel.Status(これから保存される状況)を比べて、状況が「承認済」に変わった1回の更新のときに限ってitems.Upsertで商品マスタに書き込みます。下書きの保存や、承認済のレコードの再保存では何もしません。

実務での使いどころ

申請・承認のワークフローでは、承認された内容を別の台帳(マスタ)へ転記する作業がよく発生します。プロセスの「データの変更」は自分のレコードの項目しか変えられないため、承認を契機に別テーブルへ登録・更新するにはサーバスクリプトが必要です。

承認のたびに転記すると、承認済のレコードを後から開いて保存し直しても、マスタが申請時点の内容で上書きされてしまいます。savedで「承認済に変わった瞬間」に限って拾えば、転記は承認時の1回に限られます。context.ControlIdでプロセスのボタンを判定する方法と違い、画面のプロセス・一覧の一括処理・APIのどの経路で承認しても同じ判定ができます。

商品コードが空のまま承認された場合や、マスタへの反映に失敗した場合はエラーにして承認を取り消すため、「承認済なのにマスタに反映されていない」申請は残りません。転記先サイト・承認済の状況の値・キー項目・項目の対応を書き換えれば、稟議→発注台帳、入社申請→社員マスタ、契約申請→契約台帳などにも転用できます。

事前準備

1:転記先の「商品マスタ」テーブル(記録テーブル)に、以下の項目を有効化してください。

項目 項目コード 内容
タイトル Title 商品名
分類A ClassA 商品コード(Upsertのキー)
分類B ClassB 商品区分
数値A NumA 標準単価
分類C ClassC 最終反映元の申請ID

2:申請を行う「商品登録申請」テーブル(記録テーブル)に、以下の項目を有効化してください。状況はエディタに表示しておいてください。

項目 項目コード 内容
タイトル Title 商品名
分類A ClassA 商品コード
分類B ClassB 商品区分
数値A NumA 標準単価
状況 Status 選択肢一覧:100,下書き/200,申請中/300,承認済/900,差戻し

3:「商品登録申請」テーブルにプロセスを設定してください。

プロセス 変更前の状況 変更後の状況
申請 下書き 申請中
承認 申請中 承認済
差戻し 申請中 差戻し

4:「商品登録申請」テーブルにサーバスクリプトを登録します。
 4-1:「テーブルの管理 > サーバスクリプト」タブで「新規作成」を選択します。
 4-2:タイトル:任意の名前(例:upsertMasterOnApproval)
 4-3:スクリプト:下記サンプルコードを貼り付け、MASTER_SITE_IDを商品マスタのサイトIDに書き換えます。
 4-4:条件:「更新前」にチェック

JavaScript
// ==========================================================
// 「商品登録申請」テーブルで申請が承認されたら、その内容を別サイト「商品マスタ」へ
// 商品コードをキーにして反映する(同じ商品コードがあれば更新、無ければ新規作成)サンプルです。
// 実行条件は「更新前」。saved(更新前の値)とmodel(これから保存される値)の状況を比べ、
// 状況が「承認済」に変わった1回の更新のときだけ反映します。
// 下書きの保存や、承認済のレコードの再保存では何もしません。
//
// 【context.ControlIdではなくsavedで判定する理由】
//   APIからプロセスを実行するとcontext.ControlIdは空文字になります。
//   状況の変化をsavedとmodelで比べれば、画面のプロセス・一覧の一括処理・APIの
//   どの経路で承認しても同じ判定になります。
// ==========================================================

// 商品マスタのサイトID(【商品マスタのサイトID】に置き換えてください)
const MASTER_SITE_ID = 0;
// 「承認済」の状況の値
const APPROVED_STATUS = 300;

function upsertMasterOnApproval() {
    // 承認済「以外」から承認済「へ」変わったときだけ処理する
    const becameApproved =
        Number(saved.Status) !== APPROVED_STATUS &&
        Number(model.Status) === APPROVED_STATUS;
    if (!becameApproved) {
        return;
    }

    // 商品コードはUpsertのキー。空のまま承認させない(エラーにすると承認が取り消される)
    const productCode = model.ClassA;
    if (!productCode) {
        context.Error('商品コードが未入力のため承認できません。商品コードを入力してから承認してください。');
        return;
    }

    // Keysに指定した商品コード(ClassA)は完全一致で突き合わせられる
    const data = {
        Keys: ['ClassA'],
        Title: model.Title,
        ClassHash: {
            ClassA: productCode,
            ClassB: model.ClassB,
            ClassC: String(model.ResultId), // 最終反映元の申請ID
        },
        NumHash: {
            NumA: model.NumA,
        },
    };
    const result = items.Upsert(MASTER_SITE_ID, JSON.stringify(data));
    if (result) {
        context.Log(`商品マスタへ反映しました(商品コード=${productCode}、申請ID=${model.ResultId})`);
    } else {
        // 「承認済なのにマスタに反映されていない」状態を作らないよう、承認を取り消す
        context.Log(`商品マスタへの反映に失敗しました(商品コード=${productCode}、申請ID=${model.ResultId})`);
        context.Error('商品マスタへの反映に失敗したため、承認を取り消しました。管理者に連絡してください。');
    }
}
upsertMasterOnApproval();

注記

  • itemsはスクリプトを実行したユーザーの権限で動きます。承認者には、商品マスタの作成・更新権限を付与してください。
  • 商品マスタの商品コード(分類A)は重複させない運用にしてください。items.UpsertのKeysに指定した自由入力の分類項目は、完全一致で突き合わせられます(P-00はP-001と一致しません)。
  • 転記先は、申請と別のサイトにしてください。サーバスクリプトから同じサイト内の別レコードを更新すると、画面がハングすることがあります。
  • 承認を取り消したとき(承認済から別の状況に戻したとき)に、商品マスタを元に戻す処理は含みません。

関連情報