CDS Aspectsを使って再利用可能な項目のセットを定義する

## はじめに
以下の記事で、CDS Viewの日付項目と実行日の差を計算する方法を紹介しました。このような計算はほかのViewでも使う可能性があるので、再利用する方法について考えます。

https://qiita.com/tami/items/30de35917d4c7c029395

## CDS Aspects
CDS Aspectsは、項目や計算項目などをセットで定義しておき、他のViewからも利用できるようにするものです。SAP BTP ABAP environment 2402およびSAP S/4HANA Cloud 2402から利用可能になりました。
[Version 3.40 | What's New](https://help.sap.com/docs/abap-cloud/abap-cds-tools-user-guide/version-3-40?q=cds+aspects)

CDS Aspectsについて、以下の動画で紹介されていました。
[Data Modeling with the latest features of ABAP Core Data Services | Youtube](https://www.youtube.com/watch?v=s8i44J4t7J0)

## CDS Aspectsで日付項目と実行日の差を計算する再利用部品を作る
Aspectを使用する前のViewの定義は以下のようになっています。

```
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: '###GENERATED Core Data Service Entity'
define root view entity ZR_TODO
  as select from ztodo as Todo
{
  key id as Id,
  title as Title,
  detail as Detail,
  due_date as DueDate,
  
  //計算項目
  tstmp_current_utctimestamp() as TimeStampToday,
  tstmp_to_dats($projection.TimeStampToday, 'JAPAN', $session.client, 'NULL') as DateToday,
  dats_days_between($projection.DateToday, $projection.DueDate) as DateDifference,
  
  case
    when $projection.DateDifference < 0 then 1 //negative: overdue
    when $projection.DateDifference < 3 then 2 //critical
    else 3 end as Criticality, 
  //
  
  @Semantics.user.createdBy: true
  created_by as CreatedBy,
  @Semantics.systemDateTime.createdAt: true
  created_at as CreatedAt,
  @Semantics.user.localInstanceLastChangedBy: true
  last_changed_by as LastChangedBy,
  @Semantics.systemDateTime.localInstanceLastChangedAt: true
  local_last_changed_at as LocalLastChangedAt,
  @Semantics.systemDateTime.lastChangedAt: true
  last_changed_at as LastChangedAt
}
```
以下のステップでCDS Aspectを作成し、それを元のCDS Viewに組み込みます。
1. Aspectの定義
1. CDS ViewでAspectを利用

:::note
BTP ABAP Environment（トライアル）で検証を行っています。
:::

### 1. Aspectの定義
Core Data Services > Aspect を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/56b85362-0958-cbcf-18ca-6cb2dd431a65.png)

名前と説明を指定して登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/3f14370c-9925-187f-8e6c-0cd0685c3ed2.png)

初期状態は以下のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8277ebcf-31fd-b141-d668-3579d02ac433.png)

以下のようにAspectを定義しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/633c7de6-5f87-062e-69f2-646bfe1c1a50.png)

```:コード
@EndUserText.label: 'Date Difference from today'
define aspect z_date_difference_from_today {
    //inputs
    TimeZoneIn: timezone;
    TargetDate: abap.dats;
    //calculation
    TimeStampToday = tstmp_current_utctimestamp();
    DateToday = tstmp_to_dats(TimeStampToday, TimeZoneIn, $session.client, 'NULL');
    DateDifference = dats_days_between(DateToday, TargetDate);
}
```
Aspectには、入力項目と計算項目を定義することができます。

**入力項目**
入力項目は`<項目名>:<データ型>`という形式で定義します。ここではタイムゾーンと、計算対象の日付をインプットとします。

**計算項目**
計算項目は、`<項目名> = <計算式>`という形式で定義します。計算式では、Aspectの中で定義した他の項目を参照することができます。

### 2. CDS ViewでAspectを利用
CDS Viewにもともとあった計算項目をコメントアウトし、Aspectを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ef0ddea1-0a27-8044-8246-b263ea2085ee.png)

まず、`bind aspect`という構文でAspectをバインドし、引数を渡します。
```
  bind aspect z_date_difference_from_today( 
    TargetDate => Todo.due_date, TimeZoneIn => $projection.TimeZoneIn )
    as _DateDifference
```

上記の例で、TimeZoneInにはリテラルで'JAPAN'を設定したかったのですが、リテラルが指定できなかったため、Viewの中で項目として定義し、それを参照するようにしました。

```
  cast('JAPAN' as timezone) as TimeZoneIn,
```
次に、以下の構文でAspectで定義した項目をViewに持ち込みます。この意味するところは、「アスペクトにある項目をすべて持ち込むが、バインドで指定した引数は除外する」ということです。"*"の代わりに具体的な項目名を指定することもできますが、計算で使用する項目はすべて含める必要があります。
※ADTで`excluding`のキーワードが赤くハイライトされていますが、エラーではありません
```
  include _DateDifference.* excluding {$bound_elements},
```
プレビューで見ると、Aspectで定義した項目がViewに含まれていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9ac8b0bc-ab64-38be-4282-ff2187db90b4.png)

## 参考
Aspectのドキュメントを[ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap.htm)で探したのですが見つからず、情報としては今のところ冒頭で紹介した[動画](https://www.youtube.com/watch?v=s8i44J4t7J0)と、以下のヘルプに作成の手順が載っているのみでした。

[Creating CDS Aspects | Help Portal](https://help.sap.com/docs/abap-cloud/abap-cds-tools-user-guide/creating-cds-aspects)