1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【SAPUI5】Deep Insertを使ったデータの登録(2)

Last updated at Posted at 2019-03-18

概要

今回は、Deep Insertをするための処理を作成します。

前回の記事:Deep Insertを使ったデータの登録(1)
次回の記事:Deep Insertを使ったデータの登録(3)

Deep Insertをするためには、ODataのDPC拡張クラスでCREATE_DEEP_ENTITYメソッドを実装します。
Deep Insertをするとき、Fioriアプリケーション側から構造の中にテーブルを持った型でデータを渡します。(これをDeepな構造という)
この形で渡されたとき、自動的にCREATE_ENTITYではなくCREATE_DEEP_ENTITYが呼ばれます。

Deepな構造の例
image.png

ステップ

  • Deep Insert用の処理を実装
  • Deep Insertのテスト

Deep Insert用の処理を実装

DPC拡張クラスで以下の処理を実装します。
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY

  METHOD /iwbep/if_mgw_appl_srv_runtime~create_deep_entity.
*   Deep entityの型
    DATA: BEGIN OF ls_salesorder.
        INCLUDE TYPE zcl_z_mob58_04_salesor_mpc_ext=>ts_salesorder.
    DATA: tosalesorderitem TYPE zcl_z_mob58_04_salesor_mpc_ext=>tt_salesorderitem,
          END OF ls_salesorder.
    DATA: ls_headerdata TYPE bapi_epm_so_header,
          lt_itemdata   TYPE TABLE OF bapi_epm_so_item,
          ls_itemdata   TYPE bapi_epm_so_item,
          lv_so_id      TYPE bapi_epm_so_id,
          lt_return     TYPE TABLE OF bapiret2.

    "EntitySet名により分岐
    CASE iv_entity_set_name.
      WHEN 'SalesOrderSet'.
        "アプリケーションから渡されたデータを読み込み
        io_data_provider->read_entry_data(
          IMPORTING
            es_data = ls_salesorder
        ).
        "ヘッダをBAPI受け渡し用の構造にセット
        MOVE-CORRESPONDING ls_salesorder TO ls_headerdata.
        "明細をBAPI受け渡し用のテーブルにセット
        LOOP AT ls_salesorder-tosalesorderitem INTO DATA(ls_item).
          MOVE-CORRESPONDING ls_item TO ls_itemdata.
          "delivery_dateにタイムスタンプを設定する
          GET TIME STAMP FIELD ls_itemdata-delivery_date.
          APPEND ls_itemdata TO lt_itemdata.
        ENDLOOP.

        CALL FUNCTION 'BAPI_EPM_SO_CREATE'
          EXPORTING
            headerdata    = ls_headerdata
*            persist_to_db = abap_true
          IMPORTING
            salesorderid  = lv_so_id
          TABLES
            itemdata      = lt_itemdata
            return        = lt_return.

        "エラーハンドリング
        READ TABLE lt_return WITH KEY type = 'E' TRANSPORTING NO FIELDS.
        IF sy-subrc = 0.
          mo_context->get_message_container( )->add_messages_from_bapi(
            EXPORTING
              it_bapi_messages          = lt_return                 " Return parameter table
          ).
          RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
            EXPORTING
              message_container = mo_context->get_message_container( ).
        ENDIF.

        "登録された受注の情報を取得
        CLEAR: ls_headerdata, lt_itemdata, ls_salesorder.
        CALL FUNCTION 'BAPI_EPM_SO_GET_DETAIL'
          EXPORTING
            so_id      = lv_so_id
          IMPORTING
            headerdata = ls_headerdata
          TABLES
            itemdata   = lt_itemdata
*           RETURN     =
          .

        "登録された情報を設定してアプリケーションへ返す
        MOVE-CORRESPONDING ls_headerdata TO ls_salesorder.
        me->copy_data_to_ref(
          EXPORTING
            is_data = ls_salesorder
          CHANGING
            cr_data = er_deep_entity
        ).

      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

先頭で定義したls_salesorderという構造は、アプリケーションからDeepな構造でデータを受け取るためのものです。
大まかな処理の流れは以下のようになっています。
①アプリケーションから渡されたデータ(Deepな構造)を読み込み
②BAPIで受注を登録
③登録された情報を取得してアプリケーションに返す
このメソッドは同じODataサービスに属するすべてのEntity Setが利用する可能性があるため、Entity Setの名前によって処理を分岐させています。

Deep Insertのテスト

Deep Insertで受注を登録してみます。
トランザクション:/IWFND/GW_CLIENTを起動します。

①登録用のデータのコピー元として、ヘッダ+明細を取得する

Request URIに以下のように入力します。
/sap/opu/odata/SAP/<サービス名>/SalesOrderSet('500000001')?$expand=ToSalesOrderItem&$format=json
image.png

②登録用のデータを作成する

レスポンスデータをコピーして、以下の形に編集します。
2件の明細を持つデータとなっています。
値未設定の項目は、BAPIの仕様上登録時に設定されているとエラーになるためブランクにしています。

{
  "SoId": "",
  "CreatedBy": "",
  "ChangedBy": "",
  "CreatedByBp": false,
  "ChangedByBp": false,
  "Note": "2019.3.17 MOV58",
  "BuyerId": "100000005",
  "BuyerName": "TECUM",
  "CurrencyCode": "EUR",
  "LifecycleStatus": "",
  "BillingStatus": "",
  "DeliveryStatus": "",
  "ToSalesOrderItem": [{
    "SoId": "",
    "SoItemPos": "",
    "ProductId": "HT-1040",
    "Note": "EPM DG: SO ID 0500000002 Item 0000000010",
    "CurrencyCode": "",
    "GrossAmount": "2963.10",
    "GrossAmountExt": "2963.1000",
    "NetAmount": "2490.00",
    "NetAmountExt": "2490.0000",
    "TaxAmount": "473.10",
    "TaxAmountExt": "473.1000",
    "Quantity": "3",
    "QuantityUnit": "EA"
  },
 {
    "SoId": "",
    "SoItemPos": "",
    "ProductId": "HT-1041",
    "Note": "EPM DG: SO ID 0500000002 Item 0000000010",
    "CurrencyCode": "",
    "GrossAmount" : "583.10",
    "GrossAmountExt" : "583.1000",
    "NetAmount" : "490.00",
    "NetAmountExt" : "490.0000",
    "TaxAmount" : "93.10",
    "TaxAmountExt" : "93.1000",
    "Quantity": "1",
    "QuantityUnit": "EA"
  } ]
}

③POSTメソッドで登録する

②で編集したデータを左側のRequestの部分に貼り付けます。
Request URIに以下のように入力して、POSTメソッドを実行します。
/sap/opu/odata/SAP/<サービス名>/SalesOrderSet
image.png

登録された伝票番号が返ってくれば成功です。
image.png

テーブルSNWD_SOを見てみます。
image.png

トラブルシューティング

エラーになった場合はまずCREATE_DEEP_ENTITYのメソッドに入る前と入った後、どちらでエラーになっているかを確認します。メソッドに外部デバッガを置き、POSTを実行したときにメソッドが呼ばれれば後者、呼ばれなければ前者です。

  • CREATE_DEEP_ENTITYに入る前のエラーの場合

    • Entity Setのプロパティで登録を許可しているか
    • URIを正しく指定しているか
    • 登録データの形式は正しいか(データ型、あるいはJSONフォーマットが正しいか)
  • CREATE_DEEP_ENTITYに入った後のエラーの場合

    • 基本的にはBAPIのエラーなので、BAPIから返ってくるメッセージを確認する

更新の場合はどうするか

データ登録の場合はCREATE_DEEP_ENTITYですが、親子関係のあるデータを更新したい場合はどうすればよいのでしょうか?
UPDATE_DEEP_ENTITYというメソッドはなく、以下のスレッドによれば2通りのやり方があるようです。
https://archive.sap.com/discussions/thread/3908823

①CREATE_DEEP_ENTITYを使う
メソッドの中で登録か更新かを判断して対応する
例:キーが渡されれば更新、渡されなければ登録

②$batch Processingを使う
複数のリクエストをまとめて処理する方法で、CHANGESET_BEGINというメソッドでまとめる単位を判断し、CHANGESET_PROCESSというメソッドで更新処理を行う
参考:https://archive.sap.com/documents/docs/DOC-57113

別の機会に、$batch Processingの実装もしてみたいと思います。

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?