This post talks about RAP BO Operations. RAP BO can have standard operations and non-standard operations.

Standard Operations

The behavior for standard operations can be provided by the RAP framework automatically.

  • Create, update, and delete – these are the primary standard operations. These are also called as modify operations
  • Create by Association – this is an update operation that creates new instances of an associated entity
  • Lock – this is a standard operation that locks instances of a business object entity

Nonstandard Operations

These operations are used to provide customized behavior based on business requirements.

  • Actions – this is a non-standard modifying operation
  • Functions – this is a custom read-operation

Actions

You can provide action buttons for the action on the list report or an object page. For example, In the travel app that is built earlier, we can add a set status button to change the status to booked.

The action can be triggered in one of the three ways mentioned below,

  • From the service consumer i.e. by the application user interface
  • Internally by another action or by a determination via EML
  • By other business objects via EML

Add the action to Behavior Definition

action SetStatusToBooked result [1] $self;

Activate the behavior definition and create the implementation using Eclipse quick-fix. This is demonstrated below.

Implement the code in the corresponding method

Once the method is created, implement the code in the method.

    MODIFY ENTITIES OF zi_fe_travel_001811 IN LOCAL MODE
           ENTITY travel
              UPDATE FROM VALUE #( FOR key IN keys
              ( traveluuid = key-traveluuid
                overallstatus = 'B' " Booked
                %control-overallstatus = if_abap_behv=>mk-on ) )
              FAILED failed
              REPORTED reported.

    "Read changed data for action result
    READ ENTITIES OF zi_fe_travel_001811 IN LOCAL MODE
      ENTITY travel
      ALL FIELDS WITH
      CORRESPONDING #( keys )
      RESULT DATA(travels).

    result = VALUE #( FOR travel IN travels
             ( %tky   = travel-%tky
               %param = travel ) ).

Activate the class.

Add the action in the projection behavior definition

use action SetStatusToBooked;

Activate the behavior definition.

Add the action in the metadata extension

Update the metadata extension for the field OverallStatus to add action.

  @UI.lineItem: [{ position: 80 },
                 { type: #FOR_ACTION,
                   dataAction: 'setstatustobooked' ,
                   label: 'Set to Booked'}]
  @UI.selectionField: [{ position: 40 }]
  @UI.textArrangement: #TEXT_ONLY
  @UI.dataPoint: { qualifier: 'StatusData', title: 'Status' }
  OverallStatus;

Activate and test the application.

Test Application

Launch the application and click on go. The button is visible and is grayed out.

The button will be enabled as soon as the checkbox is selected.

Click on the settings and select fewer columns with the overall status column selected to ensure that the column is visible.

Now, click on the button and see the status changed to ‘Booked’.

Note: The code sets the status to value ‘B’. However, the value shown is Booked as the field has value help attached and the annotation @UI.textArrangement: #TEXT_ONLY is used in the metadata extension, and @ObjectModel.text.element: ['TravelStatusText'] in the projection CDS root entity.

For this to work, it is important to have the value B added to the help table.

Feature Control

Operations can be enabled or disabled using the feature control. There are two variants available:

  • Instance feature control – Operations of a business object can be enabled or disabled depending on instance-specific criteria. This is helpful in the scenario where the button needs to be enabled based on object status.
  • Global feature control – Operations of a business object can be enabled or disabled globally. This is useful for scenarios where a global setting can disable or enable a feature/action/button.

Here, we will see an example of instance control to enable the SetStatusToBooked button only when the status is not already booked.

Add the code to the behavior definition i.e. just update the existing action line.

action(features : instance) SetStatusToBooked result [1] $self;

A feature handler method needs to be added. The method definition looks like below.

METHODS get_instance_features FOR INSTANCE FEATURES 
    IMPORTING keys REQUEST requested_features FOR entityName 

    RESULT result. 

The actual method definition is as below.

METHODS get_instance_features FOR INSTANCE FEATURES
  IMPORTING keys   REQUEST requested_features FOR travel

  RESULT    result.

Code for method implementation.

  METHOD get_instance_features.

    READ ENTITIES OF zi_fe_travel_001811 IN LOCAL MODE
      ENTITY travel
         FIELDS (  traveluuid overallstatus )
         WITH CORRESPONDING #( keys )
       RESULT DATA(travels)
       FAILED failed.

    result =
      VALUE #( FOR travel IN travels
        ( %key = travel-%key
          %features-%action-setstatustobooked = COND #( WHEN travel-overallstatus = 'B'
                                                        THEN if_abap_behv=>fc-o-disabled
                                                        ELSE if_abap_behv=>fc-o-enabled )
         ) ).

  ENDMETHOD.

The condition on which the feature is to be controlled is highlighted.

Refresh the app page and see the feature control working.

Note that in case you select multiple records, then if at least one record is not set to ‘booked', the button will be enabled.

Internal Action

Internal action is the operation that can only be accessed from within the behavior pool i.e. classes that implement the behavior. This scenario is covered in the earlier post Determinations and Side Effects.

internal action ReCalcTotalPrice;

Method definition

  METHODS recalctotalprice FOR MODIFY
    IMPORTING keys FOR ACTION travel~recalctotalprice.

Method implementation

  METHOD recalctotalprice.

    READ ENTITIES OF zi_fe_travel_001811 IN LOCAL MODE
      ENTITY travel
        FIELDS ( bookingfee )
           WITH CORRESPONDING #( keys )
         RESULT DATA(lt_travels).

    LOOP AT lt_travels ASSIGNING FIELD-SYMBOL(<fs_travel>).
      <fs_travel>-totalprice = <fs_travel>-bookingfee.

      READ ENTITIES OF zi_fe_travel_001811 IN LOCAL MODE
          ENTITY travel
          BY \_booking
          FIELDS ( flightprice )
           WITH VALUE #( ( %tky = <fs_travel>-%tky ) )
           RESULT DATA(lt_bookings).

      LOOP AT lt_bookings ASSIGNING FIELD-SYMBOL(<fs_booking>).
        <fs_travel>-totalprice = <fs_travel>-totalprice + <fs_booking>-flightprice.
      ENDLOOP.

    ENDLOOP.

    "update involved instances
    MODIFY ENTITIES OF zi_fe_travel_001811 IN LOCAL MODE
      ENTITY travel
        UPDATE FIELDS ( totalprice )
        WITH VALUE #( FOR travel IN lt_travels  (
                           %tky      = travel-%tky
                           totalprice  = travel-totalprice ) ).

  ENDMETHOD.

Factory Actions

Factory actions are used to create RAP BO entity instances. The instance can be created based on another instance or in a static way with default values. The syntax is as below.

factory action copy_instance [1]; 
static factory action new_instance [1]; 

The working example for this will be covered in another post in detail.

Visit ABAP RESTful Application Programming Model to explore all articles on ABAP RAP Model.


If you like the content, please subscribe…

Join 4,010 other subscribers

Discovering ABAP YouTube Channel