コンテンツにスキップ

context.Error

概要

サーバスクリプトで「レコード」の作成前、更新前、削除前にエラー判定した場合に、処理をキャンセルしエラーメッセージを画面に表示します。サーバスクリプトは途中で停止いたしません。

制限事項

  1. context.Errorを設定した場合、サーバスクリプトの処理自体は行われますが、クライアントへ返却されるのはエラーメッセージのみとなります。そのため、context.Errorに続く処理はサーバ上で行われますが、クライアント上のフォームには反映されません。
  2. サーバスクリプトの条件が「作成前」、「更新前」、「削除前」の場合に有効となります。

構文

context.Error(message);

パラメータ

パラメータ 型 必須 概要
message string ○ エラーメッセージ

戻り値

戻り値はありません。

使用例

下記の例では、組織ID 3 のユーザが状況項目を完了にして更新しようとした際に、その操作をキャンセルし、エラーメッセージを表示します。条件は「更新前」にチェックします。

JavaScript
1
2
3
4
5
6
7
try {
    if (context.DeptId === 3 && model.Status === 900) {
        context.Error('条件に該当したため、更新をキャンセルしました。');
    }
} catch (e) {
    context.Log(e.stack);
}

サンプルコード

1. 申請するとき、同じ月に同じタイトルの申請があれば止める

出張申請のテーブルで、状況を「申請中」にして更新するとき、同じ作成者・同じタイトルで対象日が同じ月の申請がほかにあれば、context.Errorで更新を止めてエラーメッセージを表示します。下書きの保存は止めません。

実務での使いどころ

出張申請・経費申請のように、同じ月に正当な申請が何件もある業務で、操作ミスによる同じ内容の二重申請を防げます。標準の「重複禁止」は1つの項目に対して常に働き、「同じ作成者に限る」「同じ月内なら重複とみなす」といった条件は付けられません。画面の入力を確かめるクライアントスクリプト($p.events.before_validate)と違い、サーバスクリプトでは、APIや一括更新で状況を変えた場合にも、同じ判定で止められます。

事前準備

1:「出張申請」テーブル(記録テーブル)で、以下の項目を有効化してください。

項目コード 内容
タイトル(Title) 申請のタイトル
日付A(DateA) 対象日
状況(Status) 選択肢一覧に「100,下書き」「200,申請中」を用意

2:スクリプトを登録します。

2-1:「テーブルの管理 > サーバスクリプト」タブで「新規作成」を選択する。
 2-2:タイトル: 任意の名前(例:rejectDuplicateApplication)
 2-3:スクリプト: 下記サンプルコードを貼り付け
 2-4:条件: 「更新前」にチェック

JavaScript
// 「申請中」の状況の値
const APPLIED_STATUS = 200;

// 対象日(Date)の月の初日と末日を「yyyy/M/d」で返す
function monthRange(date) {
    const first = new Date(date.getFullYear(), date.getMonth(), 1);
    const last = new Date(date.getFullYear(), date.getMonth() + 1, 0);
    const format = (d) => `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`;
    return { start: format(first), end: format(last) };
}

// 状況が「申請中」に変わる更新のとき、同じ作成者・同じタイトル・対象日が同じ月の
// 申請がほかにあれば、更新を止める(下書きの保存は止めない)
function rejectDuplicate() {
    // saved は更新前の値。申請中のレコードを保存し直したときは判定しない
    if (model.Status !== APPLIED_STATUS || Number(saved.Status) === APPLIED_STATUS) {
        return;
    }
    // 日付が空のとき、model では 1899/12/30 になる
    if (!model.DateA || model.DateA.getFullYear() < 1900) {
        context.Error('対象日を入力してから申請してください。');
        return;
    }
    const { start, end } = monthRange(model.DateA);
    const view = {
        View: {
            ColumnFilterHash: { DateA: `["${start} 00:00:00,${end} 23:59:59"]` },
        },
    };
    // 対象日が同じ月のレコードから、自分以外で、作成者とタイトルが同じものを探す
    const duplicates = Array.from(items.Get(context.SiteId, JSON.stringify(view)))
        .filter((item) => item.ResultId !== model.ResultId
            && item.Owner === model.Owner
            && item.Title === model.Title);
    if (duplicates.length > 0) {
        const ids = duplicates.map((item) => item.ResultId).join('、');
        context.Error(`同じ月に同じタイトルの申請があります(ID:${ids})。内容を確かめてください。`);
    }
}

rejectDuplicate();

注記

  • 状況が「申請中」に変わる更新のときのみ判定します(savedに更新前の値が入ります)。下書きのまま保存し直したときや、申請中のレコードを保存し直したときは判定しません。
  • 更新を止めると、画面には赤いメッセージが出て、状況は変わりません。APIで更新した場合は、HTTPステータス 500 と、context.Errorに渡したメッセージが返ります。
  • 日付が空のとき、modelの日付には空ではなく 1899/12/30 の日付が入ります。このサンプルでは、年が1900より前なら空として扱います。

関連情報