RAPでSM30のような複数アイテム編集用画面を作る

## はじめに
ABAP Restful Application Programming Model (RAP)で、マスタデータなどの複数行を同時に編集する画面を作る方法が以下のヘルプに載っています。

[Developing Transactional Apps with Multi-Inline-Edit Capabilities](https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/f713ec52bcb8405ca9262918cffa5d25.html)

### 解説
List Report画面のテーブルは編集することができないので、Object Pageに遷移してからテーブルを編集します。このために親子の関係を持つビジネスオブジェクトを作る必要があります。実際に編集するのは子側のエンティティです。
親は1件だけあればよいので、「シングルトン」として作ります。具体的には、必ず結果が1件になるような条件で任意のデータソースを取得し、そこに子のエンティティの最大の更新日時をEtag用の項目として追加します。以下の例では`I_Language`のビューからログイン言語をキーに取得しています。


```abap:親のエンティティの定義
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Carrier Singleton Root View'

define root view entity /DMO/I_CarriersLockSingleton_S
  as select from    I_Language
    left outer join /dmo/carrier as carr on 0 = 0
  composition [0..*] of /DMO/I_Carrier_S as _Airline

{
  key 1                          as CarrierSingletonID,
      max (carr.last_changed_at) as LastChangedAtMax, 

      _Airline
}

where
  I_Language.Language = $session.system_language
```
ポイントはこれだけで、あとは子のエンティティを追加し、通常通りBehavior Definitionなどを作るだけです。

### 動作
ヘルプの通りに作ると、次のような動作になります。このままではステップ数が多すぎて**SM30の操作感とは程遠いと言わざるを得ません。**

- List Reportから行を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/23d35971-c124-9c6a-391b-1d6e50bdc7d0.png)
- 編集ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0fda473d-fbaf-ac69-278d-f5ccf7fb05a4.png)
- 新規行を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/493ebe13-5aec-0b8b-92ee-e5c162b684d3.png)
- ダイアログでキーを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8ff39795-b0e8-9e32-d317-7951a83b0b31.png)
- Object Pageで他の項目を入力して適用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/2334edaa-3458-d53e-cfad-d440a506281d.png)

### このブログで実施すること
このブログでは、上記のヘルプを参考にアプリケーションを作成し、追加で以下のことができるようにします。
①行追加をインラインで行う
②List Reportを経由せず、直接Object Pageを編集モードで開く

①はRAP BO側の設定で、②はBuild Work Zoneのパラメータ設定で行います。

## 1. 行追加をインラインで行う
### 1.1. Creation ModeにInlineを設定
行追加をインラインで行うには、Page Mapからテーブルを選択し、Cration Modeに`Inline`を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/e91667be-df35-e1a3-e614-026899dab492.png)

ただし、単に`Inline`を設定しただけでは行追加をクリックしたときに必須項目であるキー項目が未入力のため、エラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/50bd0ca0-8673-ebb8-b55b-73d685fc7af4.png)

:::note 
もともとのアプリケーションでは、テーブルのキーはUUIDではなく、ユーザが入力する項目になっています。そのためBehavior Definitionで`mandatory : create`が設定されています。
```
field ( mandatory : create, readonly : update ) AirlineID;
```
:::

単に`mandatory`とした場合はキーがブランクの状態でドラフトが登録され、2回目以降はキーの重複でエラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c042a865-e3df-c262-3ecd-730a6aaaea36.png)

### 1.2. UUIDをキーにする
エラーを出さないためには、キーを自動採番にする必要があります。今回、ビジネス上のキーはユーザが入力するので、技術的なキーをUUIDとして自動採番させるようにします。以下のテーブルはヘルプの例とは違いますが、UUIDをキーとし、`division_code`をユーザが入力する項目としています。

```
@EndUserText.label : 'Division Code Master'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zyasu_division {

  key client            : abap.clnt not null;
  key uuid              : sysuuid_x16 not null;
  division_code         : abap.char(2) not null;
  name                  : text100;
  local_created_by      : abp_creation_user;
  local_created_at      : abp_creation_tstmpl;
  local_last_changed_by : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}
```

### 1.3. UUIDを自動採番とし、ビジネス上のキーを"mandatory"にする
Behavior DefinitionでUUIDを自動採番にし、ビジネス上のキーを`mandatory`に設定します。
```
  field ( numbering: managed, readonly ) ID;
  field ( mandatory ) DivisionCode;
```
こうすることで、ビジネス上のキーにはアスタリスクがつき、必須項目であることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b7751b4c-a87e-8c1b-c6be-5871a2266637.png)

### 1.4. オプション：バリデーションと機能制御
オプションで以下のロジックを追加します。今回は実装していません。

- バリデーション：必須項目が未入力のまま保存した場合、エラーにする
- 機能制御：ビジネス上のキーは、登録時のみ入力可能とする

## 2. List Reportを経由せず、直接Object Pageを編集モードで開く
List Reportを開く際、URLパラメータに親のエンティティをキーを渡すと直接Object Pageが開きます。これに加えて`preferredMode=edit`を指定すると、Object Pageが編集モードで開きます。
例：`#?DivisionSingletonID=1&Division-edit`
参考：[Handling of the preferredMode Parameter](https://sapui5.hana.ondemand.com/#/topic/bfaf3ccf3d6d4735990cc793b21f5529)

SAP Build Work Zone, standard editionの場合、アプリケーションの"Visualization"タブでパラメータを設定します。親のエンティティは必ず1件なので、固定のキーを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/04ff1b9b-bd1a-db1e-4b84-59af2ae20883.png)

以上で、タイルをクリックしたときに直接Object Pageが編集モードで開くようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d2eebdf4-a273-a2ce-c039-f8a20777e9b2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6663fa53-bdb0-3432-8403-e1de55feabb3.png)

## おわりに
これでSM30に近いテーブル更新画面ができました。
なお、BTP ABAP EnvironmentおよびS/4HANA（オンプレミスの場合、2022～）には[Business Configuration Maintenance Object](https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/business-configuration-maintenance-object)という類似の機能がありますので、そちらを使うこともできます。