【RAP】Late Numbering

## はじめに
[前回](https://qiita.com/tami/items/e152bad7f82bce45ba7d)の記事に引き続きRAP(ABAP RESTful Application Programming Model)でのキーの採番(Numbering)についてみていきます。今回のテーマは**Late Numbering**です。Late NumberingはDBへの保存の直前に採番を行う方法で、キーに抜けが発生しないのが利点です。

シリーズの先頭はこちら☞ [【RAP】ADTのRAP Generatorを使ってみる](https://qiita.com/tami/items/a9f3d2d4afb28d53919b#%E7%B6%9A%E7%B7%A8)

## Late Numberingを実装
以下のステップで実装を行います。

1. UUIDでないキーを持つテーブルを登録
2. RAP GeneratorでBOを生成
3. Late Numberingの実装

ステップ1, 2については[前回](https://qiita.com/tami/items/e152bad7f82bce45ba7d)の記事と同じなので割愛し、以下ではLate Numberingの実装の部分を説明します。

### Late Numberingの実装
#### 1. Behavior Definitionの設定
Behavior Definitionの先頭にlate numberingの指定を追加します。また、キー項目であるPersonIDをreadonlyに設定します。

```abap
define behavior for ZI_PERSON_LNUM_M alias Person
persistent table zperson_lnum_m
draft table zperson_lnum_m_d
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master( global )
late numbering //追加

{
  field ( readonly )
   CreatedAt,
   CreatedBy,
   LastChangedAt,
   LocalLastChangedAt,
   LastChangedBy,
   PersonID; //追加
```
late numberingにした場合、ドラフトテーブルに"draftuuid"の項目が必要になります。このため、Quick Fix (Ctrl + 1)でドラフトテーブルを再生成します。
参考：[Unmanaged Internal Late Numbering](https://help.sap.com/viewer/923180ddb98240829d935862025004d6/Cloud/en-US/754482eb5e624aada5d17696a6ab11b6.html)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/032e74f1-0261-529e-dbf2-b728b271bb59.png)

keyにdraftuuidが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/21a4f988-754b-af02-15a1-95dfb8428332.png)

再生成するとなぜか"client"の項目が"mandt"に変わってしまうため、"client"に戻して有効化します。

#### 2. Behavior Implementationの実装
late numberingのところにカーソルを当て、Quick Fixでメソッドを生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/dc9e182a-15cd-fcfe-c2ba-96a345cc937f.png)

Behavior ImplementationクラスのLocal Typesに`adjust numbers`というメソッドが追加されました。

```abap
CLASS lsc_zi_person_lnum_m DEFINITION INHERITING FROM cl_abap_behavior_saver.

  PROTECTED SECTION.

    METHODS adjust_numbers REDEFINITION.

ENDCLASS.

CLASS lsc_zi_person_lnum_m IMPLEMENTATION.

  METHOD adjust_numbers.
  ENDMETHOD.

ENDCLASS.
```

`adjust_numbers`はSave Sequenceの中で、saveの直前に呼ばれるメソッドです。ここまで来るとエラーは起こりえない、"point of no return"の位置で呼ばれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0d8d73ee-42b8-aa2d-f8a8-0250501bab04.png)

`adjust_numbers`でやることはEarly Numberingのときと同じく、changingパラメータのmappedに仮のキー(%pky)と実際のキーとのマッピングを返します。mappedには以下のように%pidが設定された状態で入ってくるので、キーを設定して返せばよいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/51e95d2e-e942-db14-8269-d1025278d118.png)

```abap
  METHOD adjust_numbers.

    "Get max person id from db
    SELECT MAX( person_id ) FROM zperson_lnum_m INTO @DATA(new_id).

    LOOP AT mapped-person ASSIGNING FIELD-SYMBOL(<person>).
      new_id += 1.
      <person>-PersonID = new_id.
    ENDLOOP.

  ENDMETHOD.
```
なお、`adjust_numbers`メソッドは登録時だけでなく、更新や削除のときも呼ばれましたが登録以外ではmappedが空でした。よって上記のようにmapped-personをループする実装にしておけば問題ないと思います。

### 動作確認
新規データを登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/fdfbadf4-2c05-340d-5106-9bdbbdb88e48.png)
ドラフト状態ではキーは採番されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/521448f3-842d-f9d1-1249-d4580e4315d8.png)
"Create"を押して保存すると、キーが採番されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/762ea942-692a-bd83-2827-68519647b625.png)

##Late Numberingが使える環境
Late Numberingは比較的新しい機能で、オンプレのS/4HANAでは以下のバージョンから使えるようになっています。

- Unmanaged BOの場合：2020 FPS01 
- Managed BOの場合：2021 FPS01　ソース：[Guidance for developing RAP applications in ABAP](https://youtu.be/AHEkbCDkn-E?t=3082)