LoginSignup
6
0

More than 3 years have passed since last update.

【BOPF】Determination, Validationの実装

Last updated at Posted at 2019-09-10

はじめに

CDS + BOPFでFioriアプリケーションを作るシリーズの続きです。
今回は、BOPFに独自のロジックを実装します。

前回の記事
【Fiori】CDS + BOPFでトランザクション実行

今回のゴール

  • データを保存するときに登録日、更新日のタイムスタンプが設定されるようにする
  • 入力値のチェックをする

BOPFのDetermination, Validationを使って上記を実現します。

Determination

Determinationとは、ビジネスオブジェクトの変更、保存など、一定の条件が満たされたときに動くロジックです。Determinationを使ってデータを保存するときに登録日、更新日のタイムスタンプが設定されるようにします。

Determinationを登録する

ADTで、BOPFのルートノードを開きます。
image.png
image.png
Neme, Descriptionを入力します。クラス名は自動提案されますが、変更することもできます。
image.png
image.png
Determinationをどのタイミングで動かすのかを指定します。今回はデフォルト(Create, Update)のままとします。
image.png
有効化すると、クラスが生成されます。

生成されたクラスの構造

生成されたクラスをトランザクションSE24で見てみましょう。
/BOBF/CL_LIB_D_SUPERCL_SIMPLEというクラスを継承していることがわかります。
image.png
/BOBF/IF_FRW_DETERMINATIONというインターフェースが実装されています(親クラスから継承)。
image.png
メソッドは3つあり、いずれも親クラスからの継承ですが、EXECUTEというメソッドだけはこのクラスで再定義するようになっています。ここにDeterminationのロジックを書きます。
image.png

動作確認

EXECUTEメソッドのパラメータは以下のようになっています。
image.png

それぞれどのような値が入ってくるのか確認するためにデバッグしてみます。
image.png
IS_CTXにはBOのキー、ルートノードのキー、処理対象ノードのキーが入っています。今回はルートノードだけの構造なので、うしろ2つは同じ値です。
image.png
IT_KEYのテーブルにはIS_CTXとは異なるキーが入っています。
image.png

Determinationロジックを実装する

Determinationのロジックは、大きく分けて2ステップです。
1. 処理対象のデータを取得する
2. 更新する値をデータ更新用のインスタンスに渡す

処理対象のデータを取得する

    DATA: lt_data TYPE ztmob58_c_students.

    io_read->retrieve(
      EXPORTING
        iv_node                 = is_ctx-node_key        " Node Name
        it_key                  = it_key                 " Key Table
      IMPORTING
        et_data                 = lt_data                " Data Return Structure
    ).

インポートパラメータで渡されたio_readというオブジェクトのメソッドを使って、処理対象のデータを取得します。et_dataで渡されるテーブルの型は、Node Overviewで確認できます。
image.png

更新する値を更新用のインスタンスに渡す

現在のタイムスタンプを取得し、登録日と更新日に設定します。

    GET TIME STAMP FIELD DATA(lv_timestamp). "タイムスタンプを取得

    LOOP AT lt_data REFERENCE INTO DATA(lo_data).

      IF lo_data->created_at IS INITIAL.
        lo_data->created_at = lv_timestamp.
      ENDIF.
      lo_data->changed_at = lv_timestamp.

      io_modify->update(
        EXPORTING
          iv_node           = is_ctx-node_key         " Node
          iv_key            = lo_data->key            " Key
          is_data           = lo_data                 " Data
      ).

   ENDLOOP.

処理対象データをループし(今回は1件だけですが)、タイムスタンプを設定し、io_modifyというオブジェクトのメソッドを使ってノードのデータを更新します。

注目すべきは、updateメソッドに渡すis_dataという項目です。この項目はオブジェクト型なので、構造ではなくオブジェクトを渡す必要があります。
このために、
LOOP AT lt_data REFERENCE INTO DATA(lo_data).
という書き方をして、内部テーブルの行をオブジェクトで参照するようにしています。

ちなみに、it_dataのkeyには何が入っているのか確認したところ、it_keyと同じ値でした。
image.png

実行結果

新規登録時

image.png
登録日時、更新日時が設定されました。
image.png

変更時

上で登録したデータを変更します。
image.png
変更日時だけが更新されました。
image.png

Validation

Validationでは、特定のアクションを実行できるか (action validations)、またはノードのインスタンスの整合性が取れているか(consistency validations)をチェックします。Validationを使って誕生日が入力されているか、また年齢が6歳以上であることをチェックします。
※生徒情報なので、実行日時点で満6歳以上という想定

Validationを登録する

Determinationと同じ要領で、Validation用のクラスを登録します。
image.png
image.png
image.png
image.png
image.png
有効化すると、クラスが生成されます。

生成されたクラスの構造

Determinationとは異なり、/BOBF/CL_LIB_V_SUPERCL_SIMPLEというクラスを継承しています。
image.png
/BOBF/IF_FRW_VALIDATIONというインターフェースが実装されています。
image.png
メソッドは3つあり、EXECUTEというメソッドを再定義するようになっています。
image.png

Validationロジックを実装する

Validationのロジックは、大きく分けて3ステップです。
1. 処理対象のデータを取得する
2. メッセージオブジェクトのインスタンスを登録する
3. データチェックし、エラーの場合はメッセージを出力する

処理対象のデータを取得する

方法はDeterminationと同じです。

    DATA: lt_data TYPE ztmob58_c_students.

    io_read->retrieve(
      EXPORTING
        iv_node                 = is_ctx-node_key        " Node Name
        it_key                  = it_key                 " Key Table
      IMPORTING
        et_data                 = lt_data                " Data Return Structure
    ).

メッセージオブジェクトのインスタンスを登録

チェック用のメソッドが呼ばれた時点で、エクスポートパラメータEO_MESSAGEはインスタンス化されていません。なので、インスタンスを登録する必要があります。

*   メッセージオブジェクトをインスタンス化
    IF eo_message IS NOT BOUND.
      eo_message = /bobf/cl_frw_factory=>get_message( ).
    ENDIF.

データチェックし、エラーの場合はメッセージを出力する

まず、データ定義に2つの変数を追加します。

    DATA: lt_data TYPE ztmob58_c_students,
          lv_age  TYPE cmp_noyrs,
          ls_msg  TYPE symsg.

取得したデータをループする、という流れはDeterminationと同じです。骨格は以下のようになります。

*   データチェック
    LOOP AT lt_data REFERENCE INTO DATA(lo_data).
*     年齢が入力されているかチェック
      IF lo_data->birthday IS INITIAL.
*       メッセージ設定
      ELSE.
*       TODO: 6歳以上かチェック
          IF lv_age < 6.
*           メッセージ設定
          ENDIF.
      ENDIF.
*     メッセージを出力
      eo_message->add_message(
        EXPORTING
          is_msg       = ls_msg
          iv_node      = is_ctx-node_key
          iv_key       = lo_data->key
      ).
*     エラーになったキーを追加
      APPEND VALUE #( key = lo_data->key ) TO et_failed_key.
    ENDLOOP.

メッセージ出力には、eo_messageのadd_messageというメソッドを使います。重要なのはet_failed_keyにエラーになったキーを追加することで、これがないとエラーを出してもそのまま更新に進んでしまいます。

最終的には以下のようなコードになります。

*   データチェック
    LOOP AT lt_data REFERENCE INTO DATA(lo_data).
*     年齢が入力されているかチェック
      IF lo_data->birthday IS INITIAL.
        ls_msg = VALUE #( msgid = 'ZMOB58' msgno = 000 msgty = 'E').
      ELSE.
*     6歳以上かチェック
        CALL FUNCTION 'HRCM_TIME_PERIOD_CALCULATE'
          EXPORTING
            begda               = lo_data->birthday
            endda               = sy-datum
         IMPORTING
           noyrs               = lv_age
         EXCEPTIONS
           invalid_dates       = 1
           overflow            = 2
           OTHERS              = 3
                  .

          IF lv_age < 6.
            ls_msg = VALUE #( msgid = 'ZMOB58' msgno = 001 msgty = 'E').
          ENDIF.
      ENDIF.
*     メッセージを出力
      IF ls_msg IS NOT INITIAL.
        eo_message->add_message(
          EXPORTING
            is_msg       = ls_msg
            iv_node      = is_ctx-node_key
            iv_key       = lo_data->key
        ).

        APPEND VALUE #( key = lo_data->key ) TO et_failed_key.
      ENDIF.
    ENDLOOP.

実行結果

誕生日が未入力のとき

image.png
必須チェックは別のやり方でもできそうな気がしますが、今回はVaidationの動作確認ということで。

年齢が6歳未満のとき

image.png

まとめ

BOPFに独自のロジックを実装しました。

今後やってみたいこと

  • Actionの実装
  • 階層を持つCDSビューをBOPFで更新
6
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0