予約ルールの設定

Field Service の予約ルールは、ユーザーがカスタム条件に基づいてリソースの予約レコードを作成または編集するときに表示する警告やエラー メッセージを作成します。 たとえば、ユーザーが仕事の実行に必要なスキルがないリソースに対してスケジュール ボードで作業指示書の予約を試みる場合、警告するように予約ルールを作成することができます。

予約ルールは、作成または編集された予約可能なリソース予約に先がけて実行されるカスタム JavaScript 方式です。 JavaScript 方法は、作成された予約可能なリソース予約レコードの情報を含むパラメーターを引き受けることができ、必須プロパティを含む JavaScript オブジェクトを戻さなければなりません。

予約を作成または変更するときに検証するよう予約ルールを設定します。

Note

  • 予約ルールは、スケジュール ボードとスケジュール アシスタントの日次、週次、または月次のビューではなく、時間単位のビューでのみ使用できます。 また、予約可能なリソースの予約フォームを介して予約が作成または更新されたときにも利用できます。
  • フォームでビジネス プロセス フローが有効になっている場合、予約可能なリソースの予約フォームでは予約ルールを使用できません。
  • 予約ルールは、スケジュール ボードの再割り当て機能では使用できません。
  • 各カスタム予約ルールは、エラー/警告を 1 つだけ返すことができます。 複数のメッセージを返すには、検証ごとに個別の予約ルールを設定します。

ソリューションの作成

予約ルールを設定するための最初のステップは、カスタム JavaScript Web リソースを作成することです。 CRM でソリューションを作成してカスタム JavaScript Web リソースを追加するか、カスタマイズ用の既存のソリューションを使用することをお勧めします。

CRM ソリューションの作成

  1. 設定>ソリューション から、予約ルールの JavaScript Web リソース用の新しいソリューションを作成します。

次のスクリーンショットは、新しく作成されたソリューションを示しています。 自分のソリューションでは、既定の公開元ではなく、一意の公開元を使用することをお勧めします。

Field Service の予約ルールのスクリーンショット

  1. ソリューションを作成したら、Web リソース コンポーネントを選択して、新しい Web リソースを作成します。
  2. 新しい Web リソース フォームで、以下の情報を入力します: a. 名前 b. 表示名 c. スクリプト (Jscript) をタイプとして選択する
  3. テキスト エディタ オプションを選択して、予約ルールの JavaScript コードを入力します。
  4. 保存 を選択して、Web リソースを保存します。
  5. 公開する を選択して、予約ルール Web リソースが公開されていることを確認します。

新しい Web リソースのスクリーンショット

予約ルールの設定

  1. メインメニューから、Field Service>リソース に移動して、予約設定予約ルール を選択します。

    Field Service のアクティブな予約ルール リストのスクリーンショット

  2. 新しい予約ルールを作成するには、+ 新規 を選択します。

  3. 予約ルールフォームから、次の情報を入力します: a. a. 名前 Web リソース (最近作成した Web リソースを選択します)。 c. JavaScript で定義したメソッド名を入力します。

    予約ルールのスクリーンショット。

  4. 予約ルールを保存します。 保存した予約ルールは、スケジュール ボードとスケジュール アシスタントの時間単位のビューまたはエンティティ フォームで使用されます。 予約ルールのレコードを非アクティブ化して、スケジュール ボード、スケジュール アシスタント、または予約エンティティ フォームがルールを実行しないようにすることができます。

Note

予約ルールは現在、スケジュール ボードとスケジュール アシスタントの時間単位ビューでのみサポートされています。 予約ルールは、予約可能なリソース予約フォームを使用して予約が作成または更新されるときにもサポートされます。 予約ルールは予約レコードの削除時に いいえ を実行します。 複数編集を使用する場合、予約ルールはフォームでは機能しません。

CRM アクションの作成

このセクションでは、カスタム CRM アクションを使用して、予約ルールの一部として検証を実行する方法を示す例を見ていきます。

予約ルール検証の CRM アクションを使用する場合も、上記に記載したカスタム Web リソースを作成する必要があります。 カスタム Web リソースで定義する JavaScript は、カスタム CRM アクションを呼び出し、カスタム CRM アクションからの結果を呼び出します。 カスタム CRM アクションを呼び出すために使用できるサンプル コードについては、本文書の最後にある添付 A を参照してください。

カスタム CRM アクションは、CRM で作成する必要があります。 カスタム Web リソース用に定義した CRM ソリューションを使用して、カスタム CRM アクションを追加することをお勧めします。

このカスタム CRM アクションには、次の入力および出力パラメーターがあるべきです。 シナリオに必要な場合は、入力および出力パラメーターをもっと追加できます。 カスタム CRM アクションを呼び出すために定義する JavaScript が、その他の入力および出力パラメーターをサポートするように更新されていることを確認する必要があります。

入力パラメーター:

  • originalScheduleStart – DateTime
  • originalScheduleEnd – DateTime
  • originalBookableResource – EntityReference
  • originalScheduleSource – 候補リスト
  • newScheduleStart – DateTime
  • newScheduleEnd – DateTime
  • isCreate – ブール値
  • isUpdate – ブール値

出力パラメーター:

  • isError – ブール値
  • isWarning – ブール値
  • errorMessage – 文字列
  • warningMessage - 文字列

次のスクリーンショットは、カスタム CRM アクションの例を示しています。 このサンプルでは、 newBookableResource が作業指示書の優先リソースと一致し、newScheduleStart約束した開始時間約束した終了時間 内にあるかどうかを確認します。 約束した時間枠の日付が 1 日であると推測されます。 例: 約束した開始時間: 2016 年 1 月 1 日午前 8 時 / 約束した終了時間: 2016 年 1 月 1 日午後 12 時。

カスタム CRM アクションのスクリーンショット。

サンプル コード

作成した JavaScript 関数は、予約コンテキストと見なされる単一のパラメーターを受け入れることができます。 渡された予約コンテキスト パラメータは、クライアント側のスクリプトで使用される典型的な CRM コンテキストでは ありません。

予約コンテキスト スキーマ:

export type BookingRuleContext = {
    oldValues: BookingRuleBookingRecord;
    newValues: BookingRuleBookingRecord;
    isCreate: boolean;
    isUpdate: boolean;
};
 
export type BookingRuleBookingRecord = {
    ResourceRequirementId?: string;
    ResourceId?: string;
    StartTime?: Date;
    EndTime?: Date;
    ResourceScheduleSource?: string;
};

予約のコンテキスト パラメーターは、次の JavaScript 定義を持っています。

Note

それは、この JavaScript コードを予約ルールのカスタム Web リソースに含める必要は ありません

ResourceScheduleSource の可能性のある値は、リソース スケジュール ソースのグローバル オプション セットからです。 予約ルールがスケジュール ボードまたはスケジュール アシスタントからトリガーされるかどうかを確認するするために、このプロパティを使用するようにできます。

    var sbContext = {
    oldValues: {
        StartTime: "01/01/2016 08:00AM",
        EndTime: "01/01/2016 05:00PM",
        ResourceId: "00000000-0000-0000-0000-00000000",
        ResourceScheduleSource: 690970001
    },
    newValues: {
        StartTime: "01/01/2016 08:00AM",
        EndTime: "01/01/2016 05:00PM",
        ResourceId: "00000000-0000-0000-0000-00000000",
        ResourceScheduleSource: 690970001
    },
    isCreate: true,
    isUpdate: false
    };

検証メソッドは、次の定義を持つ JavaScript オブジェクトを戻す必要があります。

Note

それは、この JavaScript コードを予約ルールのカスタム Web リソースに含める必要は ありません

    var ruleResult = {
    IsValid: false,
    Message: "Some Message Here",
    Type: "error" // this can be either "error" or "warning"
};

例 JavaScript 関数の定義。 次の JavaScript コードは、カスタム Web リソースに含める必要がある唯一の JavaScript コードです。


    function Validate(ctx) {
      var url = Xrm.Page.context.getClientUrl();
      var ruleResult = {
  	IsValid: false,
       Message: '',
       Type: 'error'
      };

      //
      // perform some lookups or other validation logic here.
      //
  
      ruleResult.IsValid = false;
      ruleResult.Message = 'Some Error Message Here.';
      ruleResult.Type = 'error';

      return ruleResult;
    }

次の JavaScript を使用して、前のサンプルと同じ入力パラメーターと出力パラメーターを持つカスタム CRM アクションを呼び出すことができます。

予約ルール レコードでは、メソッド名MSFSAENG.ScheduleBoard.Validate である必要があります。 参考までに、この記事の "予約ルールの設定" セクションのスクリーンショットを参照してください。


    /// <reference path="xrm.d.ts" />
    function brErrorCallback(sb) {
    // Add custom error handeling here if desired.
     return;
    }
    function brWarningCallback(sb) {
    // Add custom warning handeling here if desired.
    return;
    }
    function brSuccessCallback(sb) {
    // add custom sucess handeling here if desired.
    return;
    }
    var MSFSAENG;
    (function (MSFSAENG) {
    MSFSAENG.ScheduleBoard = {
        url: Xrm.Page.context.getClientUrl() + "/api/data/v8.1/",
        actionName: "msfsaeng_MSFSAScheduleBoardRuleActionSample",
        actionInputParameters: function (ctx) {
            var inputParameters = {};
            if (ctx.isUpdate) {
                inputParameters = {
                    "originalScheduleStart": ctx.oldValues.StartTime,
                    "originalScheduleEnd": ctx.oldValues.EndTime,
                    "originalBookableResource": {
                        "@odata.type": "Microsoft.Dynamics.CRM.bookableresource",
                        "bookableresourceid": ctx.oldValues.ResourceId,
                        "name": ""
                    },
                    "originalScheduleSource": ctx.oldValues.ResourceScheduleSource,
                    "newScheduleStart": ctx.newValues.StartTime,
                    "newScheduleEnd": ctx.newValues.EndTime,
                    "newBookableResource": {
                        "@odata.type": "Microsoft.Dynamics.CRM.bookableresource",
                        "bookableresourceid": ctx.newValues.ResourceId,
                        "name": ""
                    },
                    "newScheduleSource": ctx.newValues.ResourceScheduleSource,
                    "isCreate": ctx.isCreate,
                    "isUpdate": ctx.isUpdate
                };
            }
            else {
                inputParameters = {
                    "newScheduleStart": ctx.newValues.StartTime,
                    "newScheduleEnd": ctx.newValues.EndTime,
                    "newBookableResource": {
                        "@odata.type": "Microsoft.Dynamics.CRM.bookableresource",
                        "bookableresourceid": ctx.newValues.ResourceId,
                        "name": ""
                    },
                    "newScheduleSource": ctx.newValues.ResourceScheduleSource,
                    "isCreate": ctx.isCreate,
                    "isUpdate": ctx.isUpdate
                };
            }
            return JSON.stringify(inputParameters);
        },
        ctx: null,
        ruleResult: {
            IsValid: true,
            Message: "",
            Type: ""
        },
        outputParameters: {
            isError: false,
            isWarning: false,
            errorMessage: "",
            warningMessage: ""
        },
        Validate: function (context) {
            this.ctx = context;
            ScheduleBoardHelper.callActionWebApi(this);
            return this.ruleResult;
        },
        errorCallback: brErrorCallback,
        warningCallback: brWarningCallback,
        successCallback: brSuccessCallback
    };
    var ScheduleBoardHelper = (function () {
        function ScheduleBoardHelper() {
        }
        ScheduleBoardHelper.callActionWebApi = function (sb) {
            var oDataEndpoint = sb.url + sb.actionName;
            var req = new XMLHttpRequest();
            req.open("POST", oDataEndpoint, false);
            req.setRequestHeader("Accept", "application/json");
            req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
            req.setRequestHeader("OData-MaxVersion", "4.0");
            req.setRequestHeader("OData-Version", "4.0");
            req.onreadystatechange = function () {
                if (req.readyState == 4) {
                    req.onreadystatechange = null;
                    if (req.status == 200) {
                        sb.outputParameters = JSON.parse(req.response);
                        if (sb.outputParameters.isError) {
                            sb.ruleResult.IsValid = false;
                            sb.ruleResult.Message = sb.outputParameters.errorMessage;
                            sb.ruleResult.Type = 'error';
                            if (sb.errorCallback)
                                sb.errorCallback(sb);
                            return;
                        }
                        else if (sb.outputParameters.isWarning) {
                            sb.ruleResult.IsValid = false;
                            sb.ruleResult.Message = sb.outputParameters.warningMessage;
                            sb.ruleResult.Type = 'warning';
                            if (sb.warningCallback)
                                sb.warningCallback(sb);
                            return;
                        }
                        else {
                            sb.ruleResult.IsValid = true;
                            sb.ruleResult.Message = '';
                            sb.ruleResult.Type = '';
                            if (sb.successCallback)
                                sb.successCallback(sb);
                            return;
                        }
                    }
                    else {
                        alert('Error calling Rule Action. Response = ' + req.response + ', Status = ' + req.statusText);
                    }
                }
            };
            req.send(sb.actionInputParameters(sb.ctx));
        };
        return ScheduleBoardHelper;
    }());
    })(MSFSAENG || (MSFSAENG = {}));

追加メモ

予約可能なリソースの予約は、カスタム条件に基づいて、リソースの予約レコードを作成または編集するときにユーザーに表示される警告またはエラー メッセージを作成するために予約ルールを使用するために有効になっています。 システムは 予約ルールの preventDefault を使用します。 したがって、onSave イベントに関連するビジネス プロセス フローやその他のカスタム スクリプトは、予約ルールを有効にした予約可能なリソースの予約エンティティでは使用できません。

ただし、以下の設定を有効にすることで、予約フォームの保存時に予約ルールの処理を無効にでき、ユーザーはビジネス プロセス フローを使用できます。 クライアント側の API を使用して、環境レベルでこの設定を有効にできます。

設定 msdyn_DisableProcessBookingRulesOnSaveBookingForm の現在値を読み取ります。

Xrm.Utility.getGlobalContext().getCurrentAppSettings()["msdyn_DisableProcessBookingRulesOnSaveBookingForm"]

設定 msdyn_DisableProcessBookingRulesOnSaveBookingForm を有効にします。

Xrm.Utility.getGlobalContext().saveSettingValue("msdyn_DisableProcessBookingRulesOnSaveBookingForm",true,).then(() => {a = "success"}, (error) => {a = error})

設定 **msdyn_DisableProcessBookingRulesOnSaveBookingForm** を無効にします。

Xrm.Utility.getGlobalContext().saveSettingValue("msdyn_DisableProcessBookingRulesOnSaveBookingForm",false,).then(() => {a = "success"}, (error) => {a = error})