【Fiori】CDS + BOPFでトランザクション実行

##はじめに
SAPUI5のアプリケーションを作るとき、[過去の記事](https://qiita.com/tami/items/81dd4e185ffbc42113fa)ではODataサービスを登録して、DPCクラスでCRUDの操作を書いて・・・と、コーディングをする場面が結構ありました。
BOPFを使うとコーディング不要でCRUDの操作が実装できます。これまで1日かかっていた作業が10分でできてしまいます（筆者比）。今回は、[前回](https://qiita.com/tami/items/3322068524cfc30d236b)までに作ったCDSビューにBOPFを追加して、CRUD操作ができるようにします。

##BOPFについて
###BOとは
ビジネスオブジェクトのことで、データとそれに対する操作が一体となったクラスのようなものです。

###BOPFとは
Business Object Processing Frameworkの略で、ビジネスオブジェクトに対する汎用的なサービス（CRUDオペレーションなど）が提供されます。BOPFを使うとコーディング不要でデータに対する基本的な操作が実装できます。
BOPFは古くからSAP標準のアプリケーションで使われてきましたが、SAP NetWeaver 7.50からアドオン開発でも使えるようになりました。
参考：[Introduction to Business Object Processing Framework (BOPF)](https://archive.sap.com/documents/docs/DOC-45425)

###BOPFの構成
ビジネスオブジェクトは、ノードで構成されるツリー状の構造をしています。それぞれのノードにはデータ（テーブルの行）と、関連するビジネスロジックがひもづけられています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f05fa747-1eb1-5b76-d38b-fb4bd928e964.png)
[Introduction to Business Object Processing Framework (BOPF)](https://archive.sap.com/documents/docs/DOC-45425)より引用

###BOPFの作り方
CDSからBOPFを作る場合、アノテーションを書くだけでBOPFが自動的に生成されます。開発ツールはADTを使う必要があります。

##ステップ
1. CDSビューにアノテーションを追加
2. Fiori Appからトランザクションを実行

##1. CDSビューにアノテーションを追加
以下のアノテーションを追加します。

```abap
@ObjectModel: {
    modelCategory: #BUSINESS_OBJECT,
    compositionRoot: true,
    transactionalProcessingEnabled: true,
    createEnabled: true,
    updateEnabled: true,
    deleteEnabled: true,
    writeActivePersistence: 'zstudents'
}
```

###アノテーションの意味

|アノテーション |意味  |
|---|---|
|modelCategory  |ビジネスオブジェクトの種類を指定します。アプリケーションの動作には特に影響を与えません。|
|compositionRoot  |複数のビューが階層的な関係を持つとき、このビューがルートであるかどうかを指定します。|
|transactionalProcessingEnabled  |更新などのトランザクションを許可するかどうか。rootビューのレベルでのみ指定できる属性です。|
|createEnabled~deleteEnabled  |登録、更新、削除を許可するかどうかを指定します。     |
|writeActivePersistence  |更新対象となるテーブルを指定します。|

全体はこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b6907194-66ee-227b-4f11-742e289e56fe.png)

有効化すると、ビューと同じ名前のBOPFビジネスオブジェクトが登録されます。
ショートカット：Ctrl+Shift+Aで探してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a7047828-1c53-687e-7a84-c9b13e011464.png)
ここからBOのルートノードに移動できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ab06542b-b5ef-f8fa-aea0-6a4860b10178.png)
ここから追加のアクションやチェックなどを実装できますが、今回はそのまま使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/bf35b5a8-1386-1592-8038-d38379b1e00c.png)

たったこれだけで！トランザクションが実行できるようになります。

##2. Fiori Appからトランザクションを実行
Fiori Appをリフレッシュすると、削除ボタンと+ボタンが出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/be8c3833-cdc4-9029-9850-f988e6caad57.png)

###登録
+ボタンを押すと、新規登録画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8a692a67-a8de-eed4-ae62-cb17b6cb7b12.png)
適当な値を入力して保存ボタンを押すと、保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f6aa6ab5-e86b-1191-16e3-372f38695a5c.png)
念のためSE11でも確認してみると、Keyが自動的に採番されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/42a490d4-371b-b7ff-c870-0983259e4fa0.png)
このためにKeyはUUIDにしていたのでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/e3ae80b3-8f83-a100-d73f-793ed6dca883.png)

###更新
詳細画面に移動すると、編集ボタンが表示されます。編集ボタンを押すと更新画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b8ce43a5-ac77-d0d6-9095-3d28e0e795b7.png)
住所を変更して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/09ef57ab-cc6c-dca5-d3f8-0287493c9958.png)
更新できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/992be20f-182c-c50f-fa2b-8cdea7c84161.png)

###削除
行を選択して削除ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/332725c2-6499-128b-2e26-141ef7c13053.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f54c754e-e8d6-d7ca-fdab-210ab1671a3f.png)
削除されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/bb8b7bcc-85ee-6521-731b-dbaebffbbc34.png)

CRUDの操作だけでなくメッセージ出力なども自動的にやってくれることがわかります。

##次回
BOPFのアクションやバリデーションを使って追加のロジックを実装してみたいと思います。