シナリオ
RAPで簡単なTo-Doアプリを作成します。期限(Due Date)までの日数によって、期限にCiriticalityを設定し、色を変えて表示します。
実装のポイントは以下の4点です。
- 現在の日付を取得する
- 期限日との差を計算する
- 期限日までの日数によってCriticalityの値を設定する
- 期限日の項目にCriticalityを設定する
1~3はCDS Viewで計算し、4.はUIアノテーションで設定します。
実装
1. テーブル定義
@EndUserText.label : 'To-do list'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ztodo {
key client : abap.clnt not null;
key id : sysuuid_x16 not null;
title : text100;
detail : text100;
due_date : abap.dats;
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
local_last_changed_at : abp_locinst_lastchange_tstmpl;
last_changed_at : abp_lastchange_tstmpl;
}
2. RAP Generatorでオブジェクトを生成
テーブルを指定してRAP Generatorで各オブジェクトを生成します。
3. ZR_のビューに計算項目を追加
ZR_(ベース)のCDS Viewに計算項目を追加します。
計算項目はProjection Viewには追加できないという制約があるため、ベースのCDS 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
}
3.1. 現在の日付を取得する
システム日付を使用する場合は$session.system_date
を使うことができます。タイムゾーンを考慮した日付を取得する場合は、以下のように現在のタイムスタンプを取得し、それを日付型に変換するという2ステップが必要です。
①現在のタイムスタンプを取得する
tstmp_current_utctimestamp() as TimeStampToday,
tstmp_current_utctimestamp()というファンクションで現在のタイムスタンプ(UTC)を15桁のDEC型で取得します。出力は20241001205610
のような形式になります。
②タイムスタンプをdats型(yyyymmdd)に変換する
tstmp_to_dats($projection.TimeStampToday, 'JAPAN', $session.client, 'NULL')
tstmp_to_dats(tstmp,tzone,clnt,on_error)というファンクションでタイムスタンプをdats型に変換します。引数には以下を指定します。
- tstmp: タイムスタンプ(15桁のDEC型)
- tzone: タイムゾーン(※)
- clnt: 実行クライアント
- on_error: エラー時の動作。
FATAL
(例外を発生)、NULL
(NULLを設定)、INITIAL
(初期値を設定)のいずれか
※上の例ではタイムゾーンに固定値を設定していますが、abap_user_timezone, abap_system_timezoneなどのファンクションを使用して取得することもできます。
3.3. 期限日との差を計算する
dats_days_between($projection.DateToday, $projection.DueDate) as DateDifference,
dats_days_between(date1,date2)というファンクションで、date2からdate1を引いた日数を計算します。date1, date2にはdats型を指定します。
3.4. 期限日までの日数によってCriticalityの値を設定する
case
when $projection.DateDifference < 0 then 1 //negative: overdue
when $projection.DateDifference < 3 then 2 //critical
else 3 end as Criticality,
case文を使って期限日までの日数に応じたCriticalityを設定しています。ここでは、期限が過ぎたら1(Negative), 期限日まで3日を切ったら2(Critical)、それ以外の場合は3(Positive)を設定します。
Criticalityに使用できる値は以下のリポジトリで確認できます。
https://github.com/SAP/odata-vocabularies/blob/main/vocabularies/UI.md#CriticalityType
4. ドラフトテーブルを再生成
ビューに計算項目を追加したあとは、ドラフトテーブルにも同じ項目を追加する必要があります。このためBehavior Definitionを開き、ドラフトテーブルにカーソルを合わせてQuick Fix(Ctrl + 1)を実行します。
以下は再生成されたドラフトテーブルです。
@EndUserText.label : 'Draft Database Table for ZTODO_D'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ztodo_d {
key mandt : mandt not null;
key id : sysuuid_x16 not null;
title : text100;
detail : text100;
duedate : abap.dats;
timestamptoday : abap.dec(15,0);
datetoday : abap.dats;
datedifference : abap.int4;
criticality : abap.int1;
createdby : abp_creation_user;
createdat : abp_creation_tstmpl;
lastchangedby : abp_locinst_lastchange_user;
locallastchangedat : abp_locinst_lastchange_tstmpl;
lastchangedat : abp_lastchange_tstmpl;
"%admin" : include sych_bdl_draft_admin_inc;
}
5. コンサンプションビュー
コンサンプションビューにCriticalityの項目を追加します。
@Metadata.allowExtensions: true
@EndUserText.label: '###GENERATED Core Data Service Entity'
@AccessControl.authorizationCheck: #CHECK
define root view entity ZC_TODO
provider contract transactional_query
as projection on ZR_TODO
{
key Id,
Title,
Detail,
DueDate,
Criticality, //追加
CreatedBy,
CreatedAt,
LastChangedBy,
LocalLastChangedAt,
LastChangedAt
}
6. UIアノテーション
期限日(DueDate)にCriticalityを設定するため、UIアノテーションを以下のように追加します。
@UI.lineItem: [ {
position: 40,
criticality: 'Criticality',
criticalityRepresentation: #WITH_ICON
} ]
DueDate;
以上で、冒頭のような見え方になります。
補足
計算した日数の差によってステータスに値を設定し、ステータスをList Reportでの検索の条件にしたいというケースがあるかもしれません。計算項目での検索はパフォーマンスが落ちるため、特にデータが大量の場合は注意が必要です。