Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
patrick_winkler
Product and Topic Expert
Product and Topic Expert

Introduction

In this blog post, you will learn how to create a Fiori Elements app for a Time-Dependent RAP Business Object.
Time dependency means that the underlying table has a date that represents the start or end of the record validity as a key field.
Our goal is to create a Fiori Elements app where

  • The user can filter the data based on record validity to display current, past, or future valid entries
  • The user can use a delimit action to split an existing time slice
  • Validations ensure that only one time slice is valid at any time and that there are no gaps between time slices

To follow this blog, you should be familiar with

  • ABAP RESTful Programming Model
  • Fiori Elements

This blog is relevant for:

  • SAP S/4HANA On-Premises 2023 or higher
  • SAP S/4HANA Cloud, Public Edition
  • SAP S/4HANA Cloud, Private Edition
  • SAP BTP, ABAP Environment

Generate RAP BO for time-dependent customizing table

The time-dependent table has the following definition:

 

 

@EndUserText.label : 'Time depend.'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #C
@AbapCatalog.dataMaintenance : #ALLOWED
define table ztimedep {
  key client              : abap.clnt not null;
  key numc1               : abap.numc(1) not null;
  key validity_begin_date : abap.dats not null;
  validity_end_date       : abap.dats;
  content                 : abap.char(30);
  last_changed_at         : abp_lastchange_tstmpl;
  local_last_changed_at   : abp_locinst_lastchange_tstmpl;
}

 


With the BC Maintenance Object ADT Wizard, you generate the RAP BO for this table. This way, you can also use the Custom Business Configurations app, so you don't need to create a custom Fiori Elements app. You can also create your own custom Fiori app based on the generated service binding if you don't want to use this app. For more information, see this blog. The following modifications can also be made to any existing RAP BO and can be implemented independently of each other.

Time slice validation

Add the following validation to the table entity in the behavior definition. By using the validity date fields as trigger fields, you can ensure that all changes to the time slice are validated. Also add this validation to the preparation action because a draft-enabled BO has been generated and this validation should be executed for the draft instance.

 

validation ValidateTimeSlice on save { field ValidityBeginDate, ValidityEndDate; }

draft determine action Prepare {
  validation TimeDepend ~ ValidateTimeSlice;
}

 

Note the comments in the code for a detailed explanation:

 

  METHOD ValidateTimeSlice.
    DATA check_date TYPE d.
    CONSTANTS c_state_area TYPE string VALUE `TimeValidity`.
    "Entities can only be read if the key is specified in full
    "Validation requires not only the modified entity, but all others with the same initial key
    "Therefore, we use the parent entity to retrieve all sibling entities and additionally read ValidityEndDate
    READ ENTITIES OF zi_timedepend_s IN LOCAL MODE
      ENTITY timedependall BY \_timedepend
      FROM VALUE #( ( %tky-singletonid = 1
                      %tky-%is_draft = keys[ 1 ]-%is_draft ) )
      RESULT FINAL(all_keys).
    READ ENTITY IN LOCAL MODE zi_timedepend
      FIELDS ( ValidityEndDate ) WITH CORRESPONDING #( all_keys )
      RESULT DATA(all_entities).
    "Sort by ValidityBeginDate
    SORT all_entities BY numc1 ValidityBeginDate ASCENDING.

    LOOP AT keys ASSIGNING FIELD-SYMBOL(<key>).
      "We are using state messages: https://help.sap.com/docs/abap-cloud/abap-rap/state-messages?version=sap_btp
      "Therefore, invalidate existing messages first
      INSERT VALUE #( %tky        = <key>-%tky
                      %state_area = c_state_area ) INTO TABLE reported-timedepend.
      READ TABLE all_entities WITH KEY %tky = <key>-%tky BINARY SEARCH INTO DATA(entity).
      DATA(tabix) = sy-tabix.
      "Check1: If ValidityEndDate is set, it must be before ValidityBeginDate
      IF entity-ValidityEndDate IS NOT INITIAL AND entity-ValidityEndDate < entity-ValidityBeginDate.
        INSERT VALUE #( %tky = <key>-%tky ) INTO TABLE failed-timedepend.
        INSERT VALUE #( %tky = <key>-%tky
                        %state_area = c_state_area
                        %path-timedependall-singletonid = 1
                        %path-timedependall-%is_draft = <key>-%is_draft
                        %element-ValidityEndDate = if_abap_behv=>mk-on "to highlight the affected cell
                        %msg = new_message_with_text( text = `End date is before Begin date` ) ) INTO TABLE reported-timedepend.
        CONTINUE.
      ENDIF.
      "Check2: Since we sorted by ValidityBeginDate, we can read the preceding chronological entity and check for gaps or overlaps.
      READ TABLE all_entities INDEX tabix - 1 ASSIGNING FIELD-SYMBOL(<prev_entity>).
      IF sy-subrc = 0 AND <prev_entity>-numc1 = <key>-numc1.
        check_date = entity-ValidityBeginDate - 1.
        IF <prev_entity>-ValidityEndDate <> check_date.
          IF <prev_entity>-ValidityEndDate > check_date.
            DATA(text) = `Time slices overlap`.
          ELSE.
            text = `Gap between time slices`.
          ENDIF.
          INSERT VALUE #( %tky = <key>-%tky ) INTO TABLE failed-timedepend.
          INSERT VALUE #( %tky = <key>-%tky
                          %state_area = c_state_area
                          %path-timedependall-singletonid = 1
                          %path-timedependall-%is_draft = <key>-%is_draft
                          %element-ValidityBeginDate = if_abap_behv=>mk-on
                          %msg = new_message_with_text( text = text ) ) INTO TABLE reported-timedepend.
        ENDIF.
      ENDIF.
      "Check3: check the following chronological entity
      READ TABLE all_entities INDEX tabix + 1 ASSIGNING FIELD-SYMBOL(<next_entity>).
      IF sy-subrc = 0 AND <next_entity>-numc1 = <key>-numc1.
        check_date = entity-ValidityEndDate + 1.
        IF <next_entity>-ValidityBeginDate <> check_date.
          IF <next_entity>-ValidityBeginDate < check_date.
            text = `Time slices overlap`.
          ELSE.
            text = `Gap between time slices`.
          ENDIF.
          INSERT VALUE #( %tky = <key>-%tky ) INTO TABLE failed-timedepend.
          INSERT VALUE #( %tky = <key>-%tky
                          %state_area = c_state_area
                          %path-timedependall-singletonid = 1
                          %path-timedependall-%is_draft = <key>-%is_draft
                          %element-ValidityEndDate = if_abap_behv=>mk-on
                          %msg = new_message_with_text( text = text ) ) INTO TABLE reported-timedepend.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.

 


In the following example, a new record is added, but its time slice overlaps with the existing records. Note that the validation is executed when you save.

Validation example

Delimit action

A typical task is to split or delimit an existing time-dependent record. We provide the user with an action where a record is selected and a new ValididyEndDate is provided by the user. The existing data record is adjusted with the specified date and a new data record is also created.

Create a new abstract entity for parameterizing the action:

 

@EndUserText.label: 'Delimit'
define abstract entity ZD_DELIMITTP
{
  @EndUserText.label: 'New Validity End Date'
  ValidityEndDate : abap.dats;
}

 


Add the following action to the table entity in the behavior definition and, if applicable, the behavior projection. Also, add a side effect so that the table is refreshed when the action is applied to multiple rows.

 

"behavior definition
factory action ( features: instance ) Delimit parameter ZD_DELIMITTP [1];
side effects
  { action Delimit affects entity _TimeDependAll; }
"behavior projection
projection;
strict;
use draft;
use side effects;

use action Delimit;

 

Add the action to the metadata extension:

 

  @UI.identification: [ {
    position: 1 , 
    label: 'Numc1'
  } ]
  @UI.lineItem: [ {
    position: 1 , 
    label: 'Numc1'
  },
  {
    type: #FOR_ACTION, 
    dataAction: 'Delimit', 
    label: 'Delimit Selected Entry'
  } ]
  @UI.facet: [ {
    id: 'ZI_TimeDepend', 
    purpose: #STANDARD, 
    type: #IDENTIFICATION_REFERENCE, 
    label: 'Time depend.', 
    position: 1 
  } ]
  Numc1;

 

Note the comments in the code for a detailed explanation:

 

  METHOD get_global_authorizations.
    AUTHORITY-CHECK OBJECT 'S_TABU_NAM' ID 'TABLE' FIELD 'ZI_TIMEDEPEND' ID 'ACTVT' FIELD '02'.
    DATA(is_authorized) = COND #( WHEN sy-subrc = 0 THEN if_abap_behv=>auth-allowed
                                  ELSE if_abap_behv=>auth-unauthorized ).
    result-%action-delimit = is_authorized.
  ENDMETHOD.

  METHOD get_instance_features.
    "The delimitation action shall only be possible for draft entities as the transport selection logic requires a draft entity
    result = VALUE #( FOR <key> IN keys (
               %tky = <key>-%tky
               %action-delimit = COND #( WHEN <key>-%is_draft = if_abap_behv=>mk-on
                                         THEN if_abap_behv=>fc-o-enabled
                                         ELSE if_abap_behv=>fc-o-disabled ) ) ).
  ENDMETHOD.

  METHOD delimit.
    DATA new_timedepend TYPE TABLE FOR CREATE zi_timedepend_s\_timedepend.
    DATA modify_timedepend TYPE TABLE FOR UPDATE zi_timedepend.

    CHECK lines( keys ) > 0.
    READ ENTITIES OF zi_timedepend_s IN LOCAL MODE
      ENTITY timedepend
        ALL FIELDS WITH CORRESPONDING #( keys )
        RESULT FINAL(ref_timedepends).
    APPEND VALUE #( %is_draft = keys[ 1 ]-%is_draft
                    singletonid = 1 )
      TO new_timedepend ASSIGNING FIELD-SYMBOL(<new_timedepend>).

    LOOP AT keys ASSIGNING FIELD-SYMBOL(<key>).
      READ TABLE ref_timedepends WITH TABLE KEY draft COMPONENTS %tky = <key>-%tky INTO DATA(ref_timedepend).
      "The new ValidityEndDate must be between the current ValidityBeginDate and ValidityEndDate.
      IF <key>-%param-ValidityEndDate < ref_timedepend-ValidityBeginDate OR <key>-%param-ValidityEndDate >= ref_timedepend-ValidityEndDate.
        INSERT VALUE #( %tky = <key>-%tky ) INTO TABLE failed-timedepend.
        INSERT VALUE #( %tky = <key>-%tky
                        %path-timedependall-singletonid = 1
                        %path-timedependall-%is_draft = <key>-%is_draft
                        %msg = new_message_with_text( text = |{ <key>-%param-ValidityEndDate DATE = USER } is not a valid date for delimit action| ) ) INTO TABLE reported-timedepend.
        CONTINUE.
      ENDIF.
      "new record-ValidityBeginDate = user selected date + 1 day
      "new record-ValidityEndDate = reference record-ValidityEndDate
      ref_timedepend-ValidityBeginDate = <key>-%param-ValidityEndDate + 1.
      INSERT VALUE #( %cid = <key>-%cid
                      %is_draft = <key>-%is_draft
                      %data = CORRESPONDING #( ref_timedepend EXCEPT lastChangedAt localLastChangedAt singletonid ) "don't copy technical fields
       ) INTO TABLE <new_timedepend>-%target.
      "reference record-ValidityEndDate = user selected date
      INSERT VALUE #( %tky = <key>-%tky
                      ValidityEndDate = <key>-%param-ValidityEndDate
                      %control-ValidityEndDate = if_abap_behv=>mk-on ) INTO TABLE modify_timedepend.
    ENDLOOP.
    IF new_timedepend[ 1 ]-%target IS NOT INITIAL.
      MODIFY ENTITIES OF zi_timedepend_s IN LOCAL MODE
        ENTITY timedependall CREATE BY \_timedepend
        FIELDS ( numc1
                 ValidityBeginDate
                 ValidityEndDate
                 content ) WITH new_timedepend
        ENTITY  timedepend  UPDATE FIELDS  ( ValidityEndDate ) WITH modify_timedepend
          MAPPED FINAL(mapped_create).
      mapped-timedepend = mapped_create-timedepend.
    ENDIF.
  ENDMETHOD.

 

In the following example, the record valid for October is delimited:

Delimit Selected Entry

Delimit Action Result

Validity View Variants

The user should be able to filter the entries by their validity regarding a key date:

  • Currently valid
  • Valid in the past
  • Valid in the future

There are two alternative solutions:

  • View settings variants
  • Calculated or Virtual validity field

View settings variants

The user can use the table view settings to create the required filter conditions.

Filter Conditions for Effective Date Today


For this approach, you must ensure that both ValidityBeginDate and ValidityEndDate are within a reasonable period of time so that Today +/- can be applied. You can change the time slice validation by changing the first check:

 

      "Check1: ValidityBeginDate and ValidityEndDate must be within a reasonable timeframe
      DATA(max_date) = CONV d( cl_abap_context_info=>get_system_date( ) + 99999 ).
      DATA(min_date) = CONV d( cl_abap_context_info=>get_system_date( ) - 99999 ).
      IF entity-ValidityEndDate < entity-ValidityBeginDate
        OR entity-ValidityEndDate > max_date.
        IF entity-ValidityEndDate < entity-ValidityBeginDate.
          DATA(err_text) = `End date must be greather than Begin date`.
        ELSE.
          err_text = |End date must not be greather than {  max_date DATE = USER }|.
        ENDIF.
        INSERT VALUE #( %tky = <key>-%tky ) INTO TABLE failed-timedepend.
        INSERT VALUE #( %tky = <key>-%tky
                        %state_area = c_state_area
                        %path-timedependall-singletonid = 1
                        %path-timedependall-%is_draft = <key>-%is_draft
                        %element-ValidityEndDate = if_abap_behv=>mk-on "to highlight the affected cell
                        %msg = new_message_with_text( text = err_text ) ) INTO TABLE reported-timedepend.
        CONTINUE.
      ENDIF.
      IF entity-ValidityBeginDate < min_date.
        INSERT VALUE #( %tky = <key>-%tky ) INTO TABLE failed-timedepend.
        INSERT VALUE #( %tky = <key>-%tky
                        %state_area = c_state_area
                        %path-timedependall-singletonid = 1
                        %path-timedependall-%is_draft = <key>-%is_draft
                        %element-ValidityBeginDate = if_abap_behv=>mk-on
                        %msg = new_message_with_text( text = |Begin date must be greather than { min_date DATE = USER }| ) ) INTO TABLE reported-timedepend.
        CONTINUE.
      ENDIF.

 

The user now has the option to set this view as the default view for all and create other view variants, for example, for Valid in the future.

Default view

Calculated or virtual validity field


A field "Validity" is added to the data model that calculates the validity of each record with the system date as the key date. The user can use this field in the filter conditions.

Create a custom domain that represents the different validity values:

Validity domain

Create a custom value help entity for the domain:

 

"for use in SAP BTP, ABAP Environment or S/4HANA Cloud Public Edition
@ObjectModel.dataCategory: #VALUE_HELP
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Validity'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.resultSet.sizeCategory: #XS
define view entity ZI_ValidityVH
  as select from DDCDS_CUSTOMER_DOMAIN_VALUE( p_domain_name : 'ZVALIDITY' ) as Id
  association [0..1] to DDCDS_CUSTOMER_DOMAIN_VALUE_T as _Text on  _Text.value_low   = $projection.Validity
                                                               and _Text.language    = $session.system_language
                                                               and _Text.domain_name = Id.domain_name
                                                               and _Text.value_position = Id.value_position
{
         @ObjectModel.text.element: ['Description']
  key    value_low                                 as Validity,
         @Semantics.text: true
         _Text( p_domain_name : 'ZVALIDITY' ).text as Description
}

"for use in S/4HANA Cloud Private Edition and S/4HANA On-Premises
@ObjectModel.dataCategory: #VALUE_HELP
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Validity'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.resultSet.sizeCategory: #XS
define view entity ZI_ValidityVH
  as select from dd07l as id
  association [0..1] to dd07t as _text on  _text.domname    = id.domname
                                       and _text.ddlanguage = $session.system_language
                                       and _text.as4local   = id.as4local
                                       and _text.valpos     = id.valpos
                                       and _text.as4vers    = id.as4vers
{
      @ObjectModel.text.element: ['Description']
  key domvalue_l   as Validity,
      @Semantics.text: true
      _text.ddtext as Description
}
where
      id.domname  = 'ZVALIDITY'
  and id.as4local = 'A'
  and id.as4vers  = '0000'

 

Add a calculated field to the base CDS Entity of the table. It calculates the validity value based on the system date. Use the custom value help entity for value help definition. If you want to add an additional visual indicator for the validity, you can use the criticality annotation.

If you have a projection layer, also add the new field to the projection CDS entity.

In this case, you also have the option to define a virtual element in the projection view instead of the calculated field in the base view. The advantage is that you don't need to define a determination with the same logic as in the CDS view, because the calculation is executed for both the active instance and the draft instance via the annotated ABAP class.

 

@EndUserText.label: 'Time depend.'
@AccessControl.authorizationCheck: #CHECK
define view entity ZI_TimeDepend
  as select from ztimedep
  association to parent ZI_TimeDepend_S as _TimeDependAll on $projection.SingletonID = _TimeDependAll.SingletonID
{
  key numc1                 as Numc1,
  key validity_begin_date   as ValidityBeginDate,
      content               as Content,
      validity_end_date     as ValidityEndDate,
      @Semantics.systemDateTime.lastChangedAt: true
      last_changed_at       as LastChangedAt,
      @Semantics.systemDateTime.localInstanceLastChangedAt: true
      local_last_changed_at as LocalLastChangedAt,
      1                     as SingletonID,
      @Consumption.valueHelpDefinition: [{  entity:
      {name: 'ZI_ValidityVH' , element: 'Validity' }
      }]
      case
         when validity_begin_date <= $session.system_date and ( validity_end_date >= $session.system_date or validity_end_date is initial ) then 'C'
         when validity_begin_date > $session.system_date then 'F'
      else 'P'
      end                   as Validity,
      _TimeDependAll
}

 

Adapt the draft table by adding the calculated field:

 

@EndUserText.label : 'ZI_TimeDepend - Draft'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table ztimedep_d {
  key mandt             : mandt not null;
  key numc1             : abap.numc(1) not null;
  key validitybegindate : abap.dats not null;
  content               : abap.char(30);
  validityenddate       : abap.dats;
  lastchangedat         : abp_lastchange_tstmpl;
  locallastchangedat    : abp_locinst_lastchange_tstmpl;
  singletonid           : abap.int1;
  validity              : abap.char(1);
  "%admin"              : include sych_bdl_draft_admin_inc;
}

 

Add the following determination to the table entity in the behavior definition to update the validity value when the validity dates are changed. A side effect is used so that the validity change is reflected on the UI. If you have a projection layer, reuse the side effect in the behavior projection. If you already have a side effect for the delimit action, simply extend the side effect list.

 

"behavior definition  
  determination setValidity on modify { field ValidityEndDate; }

  side effects
  { field ValidityEndDate affects field Validity; }

"behavior projection
  use side effects;

 

Implement the determination:

 

  METHOD setvalidity.
    DATA modify_timedepend TYPE TABLE FOR UPDATE zi_timedepend.
    CHECK lines( keys ) > 0.
    READ ENTITIES OF zi_timedepend_s IN LOCAL MODE
      ENTITY timedepend
        ALL FIELDS WITH CORRESPONDING #( keys )
        RESULT FINAL(ref_timedepends).
    LOOP AT ref_timedepends ASSIGNING FIELD-SYMBOL(<timedepends>).
      INSERT VALUE #( %tky = <timedepends>-%tky
                      validity = COND #( WHEN <timedepends>-ValidityBeginDate <= cl_abap_context_info=>get_system_date( )
                                              AND ( <timedepends>-ValidityEndDate >= cl_abap_context_info=>get_system_date( ) OR <timedepends>-ValidityEndDate IS INITIAL ) THEN 'C'
                                         WHEN <timedepends>-ValidityBeginDate > cl_abap_context_info=>get_system_date( ) THEN 'F'
                                         ELSE 'P' )
                      %control-validity = if_abap_behv=>mk-on ) INTO TABLE modify_timedepend.
    ENDLOOP.
    MODIFY ENTITIES OF zi_timedepend_s IN LOCAL MODE
      ENTITY timedepend
      UPDATE FIELDS  ( validity )
      WITH modify_timedepend.
  ENDMETHOD.

 

Set the new field Validity as readonly in the behavior definition:

 

field ( readonly )
   Validity,
   SingletonID,
   LastChangedAt,
   LocalLastChangedAt;

 

The user can now filter the records in the view settings based on the validity value:

Validity Filter

The user now has the option to set this view as the default view for all:

Default view

If the user expands the ValidityEndDate for an outdated entry, the validity column value is updated once the focus is moved from the ValidityEndDate cell.

10 Comments
WRoeckelein
Active Participant
0 Kudos
Hi patrick.winkler ,

thanks for the helpful blog.

Some remarks:

  • This would a wonderful use case for my idea in providing a sensible semantic filter for the date range, eg filter for "This Week" and also get entries which have started last week but extend into this or even beyond this week. Hello Readers, if you agree, please vote for this idea.

  • A Semantic date filter can be saved in a variant (ie today is always today and not the date on which the variant was saved) and starting from UI5 1.120.x can even be used in creating a tile (cf. release notes)

  • Is is a bit unclear to me why the logic for validity needs to be duplicated in CDS and ABAP.  IMHO "READ ENTITIES" should retrieve the Validity from the CDS, or?


Regards,

Wolfgang
patrick_winkler
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi Wolfgang,

thank you

  • Please do vote

  • Yes, but for example, the semantic filter "today" is resolved into a constant with an operator like "greater than" when saved in a variant. However, the semantic filter "today +/-" can be used, so I updated the blog

  • I don't understand what you mean


Regards,

Patrick
WRoeckelein
Active Participant
0 Kudos
Hi Patrick,

  • This might be dependent on the UI5 Version, but in our FLP a "Today" saved in the variant is still "Today" and not "Date dd.mm.yyyy" when the variant is retrieved

  • You have the logic for determining the validity once in the CDS ZI_TimeDepend and once in the ABAP Method setValidity . IMHO the logic in the ABAP Method resp the whole determination is not needed and the CDS logic should be enough as the CDS will be used "above" the draft table


Regards,

Wolfgang
ThomasSchneider
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi Patrick,

thank you for the nice blog, like it!

Thomas

.

 
patrick_winkler
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi Wolfgang,

  • Ultimately, it is about pointing out to the community that there are semantic filters for date fields that you can also save as a variant

  • I agree with you that it is not optimal, but at the moment the usual procedure.
    For the exact background, we must ask the RAP colleagues


Regards,

Patrick
WRoeckelein
Active Participant
0 Kudos
Hi Patrick,

yes, would be interesting to know when this is really needed.

In our case (also with Business Configuration) this is not needed as also the draft entities are retrieved through the CDS View und thus the calculated field gets filled.

Regards,

Wolfgang
DanielG
Explorer
0 Kudos
Hi Patrick,

thanks for the blog, interesting stuff.

The sector I'm working in has lots and lots of time dependencies in the data models, and usually it has to be a timestamp and not just a date, so there's the additional bonus of having fun with time zones, etc.

I'll see if I can incorporate some of your ideas into my future projects - I only recently started with RAP, so there's still much to learn.

BR

Daniel
patrick_winkler
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hello Wolfgang,

After consulting the RAP colleagues, I have updated the blog with the following information.

When you define a calculated field in the base CDS view, you actually need a determination with the same logic as in the CDS view to update the draft entity if necessary.

If you have a projection layer and the field in question is not persisted in the database table, you also have the option to define a virtual element in the projection view instead of the calculated field in the base view. The advantage is that you don't need to define a determination with the same logic as in the CDS view, because the calculation is executed for both the active instance and the draft instance via the annotated ABAP class.

Best regards,

Patrick
WRoeckelein
Active Participant
0 Kudos
Hi Patrick,

ok, you seem to be right and this a bit unfortunate IMHO.

And if you have a DCL, you even need a Draft Query View with also the virtual element I assume...

Regards,

Wolfgang
ajith
Associate
Associate
0 Kudos
Liked the blog.