今回はユーザ別Apexロジックの実装方法についてご紹介したいと思います。
使用する機能は次の2つです。
- カスタム設定(階層)
- Typeクラス
はじめに
『プロファイル別に異なる入力チェックをデータ保存時に実施したい。』というユーザ部門の要求にみなさんどう実装しますか?
例えば、入力チェックが
・部長職なら値引率が40%までOK
・課長職なら25%までOK
・上記以外は10%までOK
といった閾値のみがプロファイル別に異なるという場合は、入力規則でIF関数を利用した実装を行うことが多いと思います。
ところが、さらに上記条件に加えて、商品種別や顧客ランクなど複雑に絡んだ入力チェックを実装する場合、Apexコードによる実装を選択することも多いですね。
このとき、Apexコード内でプロファイル別の処理分岐を実装する場合、プロファイルオブジェクトにカスタム項目を追加できないこともあり、分岐の条件がプロファイル名(※1)をキーに行うことになります。プロファイル名は組織改編などで変更要件が出る可能性もあり、そのたびにApexコードの改修が発生することはできれば避けたいところです。また、プロファイル数が多い場合、IF-ELSEがずらっと並ぶというコードになってしまいます。
※1プロファイルIDで分岐するとSandBoxで追加したプロファイルを本番環境にリリースする場合、IDが変更される可能性があり、正常に動作しないことあるのでカスタム表示ラベルで定義しておくなど考慮が必要です。
1.カスタム設定(階層)
プロファイル別の設定定義は、カスタム設定の階層型を利用します。階層型は、組織のデフォルトレコードを作成したあと、プロファイルまたはユーザを割り当てたレコードを作成することができます。
今回は、下記3プロファイルがある想定で設定します。
・部長プロファイル
・課長プロファイル
・その他プロファイル(デフォルト)
1)カスタム設定の作成
設定>アプリケーションの設定>開発>カスタム設定>新規 から下記キャプチャの設定を実施します。

2)組織のデフォルト値
Manageボタンをクリックして、組織のデフォルト値(値引率:10%)を設定します。

3)各プロファイル設定値
ビューの新規ボタンから、プロファイルを選択して「課長プロファイル」「部長プロファイル」レコードを作成し、それぞれ値引率を設定します。


4)確認
カスタム設定の内容をVisualforceで確認してみましょう。
・組織のデフォルト(値引率10%)

・課長ユーザ(値引率25%)

・部長ユーザ(値引率40%)

Apexコントローラによるビジネスロジックの実装を行わなくても、Visualforceからカスタム設定を参照するだけで、ログインユーザ毎の適切な値が取得できていることが確認できますね。
2.Typeクラス
次に、入力チェックロジックがプロファイル毎に異なる場合、Apexコードを利用した実装方法です。Typeクラスを利用するといわゆるReflectionの実装が可能になります。
1)Apexクラス
各プロファイルごとの入力チェッククラスを作成します。
このとき、共通クラスをスーパークラスとして、各プロファイル用クラスは継承させたサブクラスで定義します。
・共通入力チェッククラス
チェック結果Trueを返します。
・課長プロファイル用クラス
チェック結果でFalseを返してみます。
・部長プロファイル用クラス
チェック処理内で例外を生成します。
2)Apexクラスの割り当て
カスタム設定で各プロファイルごとにクラス名を割り当てます。
・カスタム設定定義

・組織のデフォルト値の設定(ValidateCommon)

・課長プロファイル(ValidateForKacho)

・部長プロファイル(ValidateForBucho)

3)検証Apexクラス/Visualforce
次に呼出しクラス、Visualforceを作成します。
商談に対する入力チェックを想定してみます。
・Apexクラス(Extensionクラス)
・Visualforce(ページ名:OppValidate)
※各プロファイルでVisualforceページを有効化するのを忘れずに!
4)確認
それでは、各ユーザで挙動を確認しましょう。
/apex/OppValidate?id=<商談レコードId>にアクセスします。
・その他プロファイル(デフォルト)
入力チェック結果がTrueです。

・課長プロファイル
入力チェック結果がFalseになっていますね。

・部長プロファイル
入力チェック処理で例外が発生しました。

さいごに
プロファイル別の処理分をカスタム設定の割り当てにて実施することにより、Apexコード自体はシンプルになったのではないでしょうか?また、組織改編やユーザの追加時にも、入力ロジックの追加がなければ、カスタム設定の割り当てを追加するだけで対応が可能です。またユーザに対してカスタム設定を割り当てることができるので一部の例外ユーザに対するハンドリングなども、柔軟に対応ができるようになります。
カスタム設定やTypeクラスなど、次々追加されている機能をうまく利用して保守性の高い実装を心掛けたいですね。