2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CDS Viewで相対的な日付の差を計算し、Criticalityを設定する方法

Last updated at Posted at 2024-10-01

シナリオ

RAPで簡単なTo-Doアプリを作成します。期限(Due Date)までの日数によって、期限にCiriticalityを設定し、色を変えて表示します。

image.png

実装のポイントは以下の4点です。

  1. 現在の日付を取得する
  2. 期限日との差を計算する
  3. 期限日までの日数によってCriticalityの値を設定する
  4. 期限日の項目に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で各オブジェクトを生成します。
image.png

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
image.png

F8キーを押して出力を確認すると、以下のようになります。
image.png

4. ドラフトテーブルを再生成

ビューに計算項目を追加したあとは、ドラフトテーブルにも同じ項目を追加する必要があります。このためBehavior Definitionを開き、ドラフトテーブルにカーソルを合わせてQuick Fix(Ctrl + 1)を実行します。

image.png

以下は再生成されたドラフトテーブルです。

@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での検索の条件にしたいというケースがあるかもしれません。計算項目での検索はパフォーマンスが落ちるため、特にデータが大量の場合は注意が必要です。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?