CAPとSAP Fiori toolsでコーディングなしのプロトタイプを作る（2）CAPプロジェクトの作成

##はじめに
この記事は、[SAP Inside Track 2021](https://blogs.sap.com/2020/12/01/sap-inside-track-tokyo-2021/)で発表した「CAPとSAP Fiori toolsでコーディングなしのプロトタイプを作る」に関する補足資料のパート2です。

##ステップ
1. [SAP Business Application Stuidoのセットアップ](https://qiita.com/tami/items/49bc470bf62224a467bc)
2. CAPプロジェクトの作成（今回の記事）
3. [Fioriプロジェクトの作成](https://qiita.com/tami/items/26f4f235daf212395137)

##準備
Gitリポジトリからサンプルデータをダウンロードします。
https://github.com/miyasuta/InsideTrack-cap-fiori/tree/main/data

##CAPプロジェクトの作成
SAP Business Application Studio(BAS)のスペースに入り、プロジェクトを作成します。

###1. テンプレートからCAPプロジェクトを生成
- File>New Project from Templateをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/1cd69d93-24bb-a9eb-d98d-eec0413cd4a1.png)
- **CAP Project**を選択し、**Start**をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/479ee384-232d-b5f7-b919-0a3f94dc8e8d.png)
- プロジェクト名を入力し、**Basic Sample Files**にチェックを入れて**Finish**をクリック

※ここにチェックを入れることでサンプルファイルが作成されるので、それを上書きして使うことができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/db1914b5-3a80-1c35-699d-389f4efe1d8c.png)

- 右下に以下のポップアップが現れたら、**Open in New Workspace**をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/edab1fcd-1dd1-c408-044f-69125175aea9.png)
プロジェクトが開く。Basic Sample Filesにチェックを入れたので、赤枠のファイルが作成されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c0f3ae2e-9083-badb-a6ce-f80ecccd1881.png)

###2. ODataサービスを実行
サンプルファイルがあるので、すでにこのプロジェクトはODataサービスとして実行することができます。

- Terminsl>New Terminslをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/52c50392-f013-6d19-4901-f174fd0ac2ca.png)
- ターミナルが開いたら`npm install`と打って必要なモジュールをローカルにインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b8b074b0-f5d9-9e6a-cb7f-b9178e764f79.png)
- `cds watch`でサービスを実行し、ポップアップが出たら**Open in New Tab**をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5d8c7ba5-f9b0-812b-f22f-117c1293ad14.png)
ブラウザが開く。ここからメタデータやエンティティにアクセスできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c7de60de-d88d-0ad9-2c54-11365b19e365.png)

###3. db/data-model.cdsを編集
data-model.cdsファイルを以下の内容で上書きします。

```
namespace insidetrack.sample;

entity Projects {
    key projectCode : String                   @title : 'Project Code';
        projectName : String                   @title : 'Project Name';
        toCustomer  : Association to Customers @title : 'Customer';
        toManager   : Association to Users     @title : 'Manager';
        startsAt    : DateTime                 @title : 'Starts At';
        endsAt      : DateTime                 @title : 'Ends At';
        toStatus    : Association to Status    @title : 'Status';
        toTasks     : Composition of many Tasks
                          on toTasks.projectCode = $self.projectCode;
}
```
####解説
- **namespace**：エンティティをデータベースにテーブルやビューとして登録するときのプリフィックスになるものです。また、サービス定義からエンティティを参照するときにも使います。
- **title**：項目のラベルを定義しています。@マークがついているのはアノテーションで、項目に情報を付加するために使います。
- **Association**：他のエンティティへの関連（参照）を定義します。例えば`Association to Customers`は、このあとで定義するCustomerというエンティティとの関連を表します。関連を持たせることで、Customerエンティティから名称を取得したりすることができます。
- **Composition**：Associationと似ていますが、Compositionはヘッダ-明細のように、親のエンティティに子のエンティティが従属する関係を表します（親がなければ子も存在しない）。

詳しく知りたい方は、[公式ドキュメント](https://cap.cloud.sap/docs/cds/cdl)を参照してください。

その他のエンティティも追加します。

```
entity Tasks {
    key projectCode : String                @title : 'Project Code';
    key taskId      : Integer               @title : 'Task Id';
        description : String                @title : 'Description';
        startsAt    : DateTime              @title : 'Starts At';
        endsAt      : DateTime              @title : 'Ends At';
        toStatus    : Association to Status @title : 'Status';
        toMembers   : Composition of many Members
                          on  toMembers.projectCode = $self.projectCode
                          and toMembers.taskId      = $self.taskId;
        toProject   : Association to Projects
                          on toProject.projectCode = $self.projectCode;
}

entity Members {
    key projectCode : String               @title : 'Project Code';
    key taskId      : Integer              @title : 'Task Id';
    key toMember    : Association to Users @title : 'Member';
        toTask      : Association to Tasks
                          on  toTask.projectCode = $self.projectCode
                          and toTask.taskId      = $self.taskId;
        toProject   : Association to Projects
                          on toProject.projectCode = $self.projectCode;
}

entity Customers {
    key customer : String @title : 'Customer';
        name     : String @title : 'Name';
}

entity Users {
    key user      : String @title : 'User ID';
        firstName : String @title : 'First Name';
        lastName  : String @title : 'Last Name';
        fullName  : String @title : 'Full Name';
}

entity Status {
    key status : Integer @title : 'Status';
        text   : String  @title : 'Text';
}
```

###4. srv/cat-service.cdsを編集
cat-service.cdsを以下の内容で上書きします。

```
using insidetrack.sample as sample from '../db/data-model';

service CatalogService {
    entity Projects  as projection on sample.Projects;
    entity Tasks     as projection on sample.Tasks;
    entity Members   as projection on sample.Members;
    entity Customers as projection on sample.Customers;
    entity Users     as projection on sample.Users;
    entity Status    as projection on sample.Status;
}
```

####解説

- **using insidetrack.sample as sample...**：data-modeファイルの`insidetrack.sample`というnamespaceを、ここでは`sample`という名前で参照するという宣言をしています。
- **service CatalogService{...}**：data-modeファイルで定義したエンティティを、ODataのエンティティとして公開することを宣言しています。`entity Projects  as projection on sample.Projects`は、data-modeファイルのProjectsというエンティティを、そのまま（項目を絞ったりはせずに）Projectsという名前で公開することを表しています。ODataとして公開するときにエンティティの名前を変えても問題ありません。

###5. サンプルファイルをインポート
準備のステップでダウンロードしておいたサンプルファイルをdb/dataフォルダにドラッグ&ドロップでインポートします。ファイル名は`<namespace>-<エンティティ名>.csv`とします。
※もともと入っていたmy.bookshop-Books.csvというファイルは不要なので削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/78ba91e7-f05c-9d81-c64a-20166f1c1237.png)

サンプルファイルの中身を見てみましょう。アソシエーション、またはコンポジションしている項目は、項目名が<エンティティで定義した項目名>_<アソシエーション先のキー項目>となります。（例：_toCustomer_customer）

```:insidetrack.sample-Projects.csv
projectCode;projectName;toCustomer_customer;toManager_user;startsAt;endsAt;toStatus_status
PJA00101;排水管交換;CST001;MANAGER01;2020-01-25;2020-02-4;3
PJA00102;エアコン導入;CST002;MANAGER02;2020-01-30;2020-02-14;3
PJA00103;エアコン清掃;CST003;MANAGER02;2020-11-01;2020-11-01;3
PJA00104;掃除ロボット導入;CST004;MANAGER03;2020-12-01;2021-01-31;2
PJA00105;ドローンテスト;CST004;MANAGER03;2021-04-02;2021-05-02;1
```
###6. ODataサービスのテスト
ブラウザをリフレッシュすると、以下のように追加したエンティティが表示されます。$metadataをクリックすると、メタデータを見ることができます。このメタデータがFiori toolsで必要になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c4c1a8a6-f637-30b3-4d1d-eb3d2f4dd000.png)
次に、各エンティティが取得できるかどうかテストしてみましょう。

####6.1. Projectエンティティを取得
上の画面でProjectsのリンクをクリックすると、Projectのデータが取得できます。
URI: `.../catalog/Projects`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/73d6a85a-51e8-c32c-0178-ee830f6232e4.png)

####6.2. アソシエーションでTasksエンティティを取得
以下をアドレスバーに入力すると、PJA00101にひもづくタスクが取得できます。
URI: `.../catalog/Projects('PJA00101')/toTasks`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d09aa1c2-8199-ffdd-a913-8ef2f3b61fc5.png)

####6.3. アソシエーションでMembersエンティティを取得
さらに、2番目のタスクにアサインされたメンバーを取得してみましょう。
URI: `.../catalog/Projects('PJA00101')/toTasks(projectCode='PJA00101',taskId=2)/toMembers`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6da2ecf6-9160-d764-7067-6b8857f6a9db.png)

ここまででODataサービスは完成です。次回はFioriのUIを作成していきます。

##参考（CAPについて）
- [Open SAP : Building Applications with SAP Cloud Application Programming Model](https://open.sap.com/courses/cp7)
- [ドキュメント](https://cap.cloud.sap/docs/)
- [チュートリアル](https://developers.sap.com/tutorial-navigator.html?sort=latest_asc&search=application%20programming%20model&tag=software-product-function:sap-cloud-application-programming-model)