In the previous exercise, you've had a look at your exercise package ZRAP110_###
, where ###
is your assigned suffix (see Exercise 1).
In this exercise, you will enhance the CDS data model of the base BO and the BO projection. These enhancements include enabling OData Stream in the base BO data model and adding new elements by associations, virtual elements, and adjusting the value help definitions in the BO data model projection.
- 2.1 - Enhance the Data Model of the Base Travel BO Entity
- 2.2 - Enhance the Data Model of the Projected Travel BO Entity
- 2.3 - Enhance the Data Model of the Projected Booking BO Entity
- 2.4 - Preview and Test the Enhanced Travel App
- Summary
Reminder: Do not forget to replace the suffix placeholder
###
with your assigned suffix in the exercise steps below.
ℹ Further reading: CDS Annotations | Working with Large Objects | Using Virtual Elements in CDS Projection Views
Click to expand!
Virtual elements represent transient fields in business applications. They are used to define additional CDS elements that are not persisted on the database, but calculated during runtime using ABAP classes that implement the virtual element interface. They are defined at the level of CDS projection views as additional elements within the SELECT list.
The OData service metadata do not differentiate between regular CDS elements with database persistence and virtual elements. Consequently, a virtual element appears in an application UI equal to any other element.
Enhance the CDS data model of the base travel BO entity to support to enable the handling of large objects (aka OData stream).
🔵 Click to expand!
Adjust the CDS data model of the base Travel BO entity in view entity
ZRAP110_R_TravelTP_###
to enable the handling of large objects in your Fiori elements app.By doing that, you will give end-users the option to upload and download images from your Travel app.
🟣 Click to expand!
-
Go to the Project Explorer, open the CDS data definiton
ZRAP110_R_TravelTP_###
. -
Enable the OData Stream by adding the appropriate annotations to the elements
Attachment
andMimeType
as shown on the screenshot. Use the code snippets provided below .- For the element
Attachment
- which is used to store the LOB (aka stream) and must be bound to a MIME type:
@Semantics.largeObject: { mimeType: 'MimeType', //case-sensitive fileName: 'FileName', //case-sensitive //acceptableMimeTypes: ['image/png', 'image/jpeg'], contentDispositionPreference: #ATTACHMENT }
- For the element
MimeType
- which is used to indicates the content type of the attachment:
@Semantics.mimeType: true
About the annotation `@Semantics.largeObject`
Here is a short explanation of the attributes of the element annotation
@Semantics.largeObject
:mimeType
: It is a mandatory attribute which indicates the name of the field containing the type of a MIME object. The value is-case sentitive.fileName
: It is an optional attribute which indicates the name of the field containing the file name of a MIME object. The value is-case sentitive.acceptableMimeTypes
: It provides the list of acceptable MIME types for the related stream property to restrict or verify the user entry accordingly. If any subtype is accepted, this can be indicated by *.contentDispositionPreference
: It is used to define whether, depending on the browser settings, the file attachment is either displayed in the browser (setting #INLINE) or downloaded when selected (option #ATTACHMENT).
- For the element
-
Save (Ctrl+S) and activate (Ctrl+F3) the changes. Close the data definition.
-
You can check the result of this changes in the Travel app preview by refreshing the it in the browser (F5) or starting the again the Fiori elements App Preview in ADT.
You will now have the possibility to upload a file on the travel details page, aka Object Page.
Enhance the CDS data model of the projected travel BO entity with new elements from associations and defining virtual elements, adjusting the defined value help definitions to enable front-end validations, and removing use case irrelevant elements.
🔵 Click to expand!
Enhance the Travel BO projection view
ZRAP110_C_TravelTP_###
, aka consumption view.
🟣 Click to expand!
-
Performing classic adjustment tasks such as adding new elements from associations, specifying associated text elements, removing use case irrelevant elements have already been introduced and explained in RAP100.
Replace the whole data definition of the travel BO projection view
ZRAP110_C_TravelTP_###
with the source code from the document provided below.Replace all occurences of the placeholder
###
with your assigned suffix using Ctrl+F.Hint: The changed lines are marked with a comment in the provided source code.
▶📄 Source code document: CDS Projection View ZRAP110_C_TRAVELTP_###
-
Now, go ahead and define the virtual element
OverallStatusIndicator
that will be used to specify the criticality of the travel overall status in the Travel app in the metadata extension later on. The end-user label of this element isOverall Status Indicator
.The keyword
virtual
must be specified in front of the element and the name of the calculation class must be specified in the annotation@ObjectModel.virtualElementCalculatedBy
. The ABAP classZRAP110_CALC_TRAV_ELEM_###
will be used to calculate this virtual element is specified.Uncomment in the Travel BO projection view
ZRAP110_C_TravelTP_###
the code snippet below placed after the elementOverallStatusText
in the SELECT list as shown on the screenshot and replace the placeholder###
with your assigned suffix.@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZRAP110_CALC_TRAV_ELEM_###' @EndUserText.label: 'Overall Status Indicator' virtual OverallStatusIndicator : abap.int2,
ℹ Info: Due to time constraint, a skelleton of the class *
ABAP:ZRAP110_CALC_TRAV_ELEM_###
has been already generated in your exercise package. You will enhance its implementation in the step 2.4. -
Save (Ctrl+S) and activate (Ctrl+F3) the changes. Close the data definition.
Implement the logic of the virtual element
OverallStatusIndicator
in the ABAP ClassZRAP110_CALC_TRAV_ELEM_###
, where###
is your assigned suffix.
🟣 Click to expand!
-
Open your ABAP class
ZRAP110_CALC_TRAV_ELEM_###
and replace the entire code with the code provided below. Replace all occurences of the placeholder###
with your assigned suffix using Ctrl+F.CLASS zrap110_calc_trav_elem_### DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_sadl_exit_calc_element_read . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS ZRAP110_CALC_TRAV_ELEM_### IMPLEMENTATION. METHOD IF_SADL_EXIT_CALC_ELEMENT_READ~CALCULATE. IF it_requested_calc_elements IS INITIAL. EXIT. ENDIF. LOOP AT it_requested_calc_elements ASSIGNING FIELD-SYMBOL(<fs_req_calc_elements>). CASE <fs_req_calc_elements>. "virtual elements from TRAVEL entity WHEN 'OVERALLSTATUSINDICATOR'. DATA lt_trav_original_data TYPE STANDARD TABLE OF ZRAP110_C_TravelTP_### WITH DEFAULT KEY. lt_trav_original_data = CORRESPONDING #( it_original_data ). LOOP AT lt_trav_original_data ASSIGNING FIELD-SYMBOL(<fs_trav_original_data>). * <fs_trav_original_data> = zrap110_calc_trav_elem_###=>calculate_trav_status_ind( <fs_trav_original_data> ). ENDLOOP. ct_calculated_data = CORRESPONDING #( lt_trav_original_data ). ENDCASE. ENDLOOP. ENDMETHOD. METHOD IF_SADL_EXIT_CALC_ELEMENT_READ~GET_CALCULATION_INFO. IF iv_entity EQ 'ZRAP110_C_TRAVELTP_###'. "Travel BO node LOOP AT it_requested_calc_elements ASSIGNING FIELD-SYMBOL(<fs_travel_calc_element>). CASE <fs_travel_calc_element>. WHEN 'OVERALLSTATUSINDICATOR'. APPEND 'OVERALLSTATUS' TO et_requested_orig_elements. ENDCASE. ENDLOOP. ENDIF. ENDMETHOD. ENDCLASS.
Brief explanation:
Click to expand!
-
The class implements the virtual element interface
IF_SADL_EXIT_CALC_ELEMENT_READ
that must be implemented by calculation classes for virtual elements. -
The method
IF_SADL_EXIT_CALC_ELEMENT_READ~GET_CALCULATION_INFO
provides a list of all elements that are required for calculating the values of the virtual elements in the requested entity. This method is called during runtime before the retrieval of data from the database to ensure that all necessary elements for calculation are filled with data. -
The method
IF_SADL_EXIT_CALC_ELEMENT_READ~CALCULATE
executes the value calculation for the virtual element. This method is called during runtime after data is retrieved from the database. The elements needed for the calculation of the virtual elements are already inside the data table passed to this method. The method returns a table that contains the values of the requested virtual elements.
Read more: Using Virtual Elements in CDS Projection
-
-
Define the class method interface
calculate_trav_status_ind
in the public section of the class definition where the proper calculation of the virtual elementOverallStatusIndicator
will take place. The method is declared as class method to have the possibility to access it externaly, for example, from a function.For that, insert the code snippet provided below after the statement
interfaces IF_SADL_EXIT_CALC_ELEMENT_READ.
in the class definition and replace all occurences of the placeholder###
with your assigned suffix.CLASS-METHODS: calculate_trav_status_ind IMPORTING is_original_data TYPE ZRAP110_C_TravelTP_### RETURNING VALUE(result) TYPE ZRAP110_C_TravelTP_###.
Your source code should look like this:
-
Press the light bulb symbol on the left side or use the ADT Quick Fix (Ctrl+1) to add the missing method implementations. Set the cursor before your method
calculate_trav_status_ind
and press CTRL + 1, select Add implementation forcalculate_trav_status_ind
.Your source code should look like this:
-
Implement the methods
calculate_trav_status_ind
.The logic is quite simple: the criticality indicator ( 1 = red | 2 = orange | 3 = green) is bound to the overall travel status:
- If travel status is accepted, then the criticality is
3
, i.e. green. - If travel status is open, then the criticality is
2
, i.e. orange. - If travel status is rejected, then the criticality is
1
, i.e. red.
For that, replace the empty method implementation of
calculate_trav_status_ind
with the code snippet provided below.METHOD calculate_trav_status_ind. result = CORRESPONDING #( is_original_data ). "travel status indicator "(criticality: 1 = red | 2 = orange | 3 = green) CASE result-OverallStatus. WHEN 'X'. result-OverallStatusIndicator = 1. WHEN 'O'. result-OverallStatusIndicator = 2. WHEN 'A'. result-OverallStatusIndicator = 3. WHEN OTHERS. ENDCASE. ENDMETHOD.
- If travel status is accepted, then the criticality is
-
Now, uncomment the method call
calculate_trav_status_ind
within the methodCALCULATE
.<fs_trav_original_data> = zrap110_calc_trav_elem_###=>calculate_trav_status_ind( <fs_trav_original_data> ).
-
Save (Ctrl+S) and activate (Ctrl+F3) the changes. Close the ABAP class.
Enhance the CDS data model of the projected travel BO entity with new elements from associations and defining virtual elements, adjusting the defined value help definitions to fine-tune the usage of the specified additional binding, and removing use case irrelevant elements.
🔵 Click to expand!
Enhance the Booking BO projection view
ZRAP110_C_BookingTP_###
.Beside basic minor classic adjustments, you will add four (4) virtual elements to the data model:
BookingStatusIndicator
that will be used to determine the criticality of the booking status on Fiori elements UIs in the metadata extension later on. End-user label is "Overall Status Indicator".InitialDaysToFlight
that will be used to calculate the initial number of days between the flight date and the booking date (flight date - booking date). the end-user label is "Initial Days to Flight".RemainingDaysToFlight
that will be used to calculate the remaining number of days before the flight (flight date - current date). End-user label is "Remaining Days to Flight".DaysToFlightIndicator
that will be used to calculate the criticality indicator for the remaining days to flight. The end-user label is "Days to Flight Indicator".
🟣 Click to expand!
-
Similarly to Exercise 2.2.1 basic adjustments will be carried out by simply replacing the complete data definition of your Booking BO projection view with the source code provided in the source code document linked below.
Replace all occurences of the placeholder
###
with your assigned suffix using Ctrl+F.▶📄 Source code document: CDS projection view ZRAP110_C_BookingTP_###
-
Now, define the four (4) new virtual elements
BookingStatusIndicator
,InitialDaysToFlight
,RemainingDaysToFlight
, andRemainingDaysToFlight
. Their values will be determined in the ABAP classZRAP110_CALC_BOOK_ELEM_###
.For that, uncomment the code snippet below placed after the element
BookingStatusText
in the SELECT list as shown on the screenshot and replace the placeholders###
with your assigned suffix.Source code
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZRAP110_CALC_BOOK_ELEM_###' @EndUserText.label: 'Booking Status Indicator' virtual BookingStatusIndicator : abap.int2, @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZRAP110_CALC_BOOK_ELEM_###' @EndUserText.label: 'Initial Days to Flight' virtual InitialDaysToFlight : abap.int1, @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZRAP110_CALC_BOOK_ELEM_###' @EndUserText.label: 'Remaining Days to Flight' virtual RemainingDaysToFlight : abap.int1, @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZRAP110_CALC_BOOK_ELEM_###' @EndUserText.label: 'Days to Flight Indicator' virtual DaysToFlightIndicator : abap.int1,
-
Save (Ctrl+S) and activate (Ctrl+F3) the changes. Close the data definition.
Implement the logic of the different virtual elements of the booking BO entity in the ABAP Class
ZRAP110_CALC_BOOK_ELEM_###
, where###
is your assigned suffix.
🟣 Click to expand!
-
Open your ABAP class
ZRAP110_CALC_BOOK_ELEM_###
and replace the entire code with the code provided below. Replace all occurences of the placeholder###
with your assigned suffix using Ctrl+F.CLASS zrap110_calc_book_elem_### DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_sadl_exit_calc_element_read . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zrap110_calc_book_elem_### IMPLEMENTATION. METHOD if_sadl_exit_calc_element_read~calculate. IF it_requested_calc_elements IS INITIAL. EXIT. ENDIF. LOOP AT it_requested_calc_elements ASSIGNING FIELD-SYMBOL(<fs_req_calc_elements>). CASE <fs_req_calc_elements>. "virtual elements from BOOKING entity WHEN 'INITIALDAYSTOFLIGHT' OR 'REMAININGDAYSTOFLIGHT' OR 'DAYSTOFLIGHTINDICATOR' OR 'BOOKINGSTATUSINDICATOR'. DATA lt_book_original_data TYPE STANDARD TABLE OF ZRAP110_C_BookingTP_### WITH DEFAULT KEY. lt_book_original_data = CORRESPONDING #( it_original_data ). LOOP AT lt_book_original_data ASSIGNING FIELD-SYMBOL(<fs_book_original_data>). * <fs_book_original_data> = zrap110_calc_book_elem_###=>calculate_days_to_flight( <fs_book_original_data> ). ENDLOOP. ct_calculated_data = CORRESPONDING #( lt_book_original_data ). ENDCASE. ENDLOOP. ENDMETHOD. METHOD if_sadl_exit_calc_element_read~get_calculation_info. IF iv_entity EQ 'ZRAP110_C_BOOKINGTP_###'. "Booking BO node LOOP AT it_requested_calc_elements ASSIGNING FIELD-SYMBOL(<fs_booking_calc_element>). CASE <fs_booking_calc_element>. WHEN 'INITIALDAYSTOFLIGHT'. COLLECT `BOOKINGDATE` INTO et_requested_orig_elements. COLLECT `FLIGHTDATE` INTO et_requested_orig_elements. WHEN 'REMAININGDAYSTOFLIGHT'. COLLECT `FLIGHTDATE` INTO et_requested_orig_elements. WHEN 'DAYSTOFLIGHTINDICATOR'. COLLECT `FLIGHTDATE` INTO et_requested_orig_elements. WHEN 'BOOKINGSTATUSINDICATOR'. COLLECT `BOOKINGSTATUS` INTO et_requested_orig_elements. ENDCASE. ENDLOOP. ENDIF. ENDMETHOD. ENDCLASS.
-
Define the class method interface
calculate_days_to_flight
in the public section of the class definition.For that, insert the code snippet provided below after the statement
interfaces IF_SADL_EXIT_CALC_ELEMENT_READ.
in the class definition and replace all occurences of the placeholder###
with your assigned suffix.CLASS-METHODS: calculate_days_to_flight IMPORTING is_original_data TYPE ZRAP110_C_BookingTP_### RETURNING VALUE(result) TYPE ZRAP110_C_BookingTP_###.
Your source code should look like this:
-
Press the light bulb symbol on the left side or use the ADT Quick Fix (Ctrl+1) to add the missing method implementations. Set the cursor before your method
calculate_days_to_flight
and press CTRL + 1, select Add implementation forcalculate_days_to_flight
.Your source code should look like this:
-
Implement the method
calculate_days_to_flight
which calculates the value of the virtual element defined in the booking BO entity.For that, replace the empty method implementation of
calculate_days_to_flight
with the code snippet provided below.METHOD calculate_days_to_flight. DATA(today) = cl_abap_context_info=>get_system_date( ). result = CORRESPONDING #( is_original_data ). "VE InitialDaysToFlight: initial days to flight DATA(initial_days) = result-FlightDate - result-BookingDate. IF initial_days > 0 and initial_days < 999. * IF initial_days > 0 . result-InitialDaysToFlight = initial_days. ELSE. result-InitialDaysToFlight = 0. ENDIF. "VE RemainingDaysToFlight: remaining days to flight DATA(remaining_days) = result-FlightDate - today. IF remaining_days < 0 OR remaining_days > 999. result-RemainingDaysToFlight = 0. ELSE. result-RemainingDaysToFlight = result-FlightDate - today. ENDIF. "VE DaysToFlightIndicator: remaining days to flight *indicator* "(dataPoint: 1 = red | 2 = orange | 3 = green | 4 = grey | 5 = bleu) IF remaining_days >= 6. result-DaysToFlightIndicator = 3. "green ELSEIF remaining_days <= 5 AND remaining_days >= 3. result-DaysToFlightIndicator = 2. "orange ELSEIF remaining_days <= 2 AND remaining_days >= 0. result-DaysToFlightIndicator = 1. "red ELSE. result-DaysToFlightIndicator = 4. "grey ENDIF. "VE BookingStatusIndicator: booking status indicator "(criticality: 1 = red | 2 = orange | 3 = green) CASE result-BookingStatus. WHEN 'X'. result-BookingStatusIndicator = 1. WHEN 'N'. result-BookingStatusIndicator = 2. WHEN 'B'. result-BookingStatusIndicator = 3. WHEN OTHERS. ENDCASE. ENDMETHOD.
About the virtual elements
BookingStatusIndicator
: For the UI coloring - 1 = red (Cancelled) | 2 = orange (Open) | 3 = green (Booked)InitialDaysToFlight
: The initial number of days between the flight date and the booking date (flight date - booking date).RemainingDaysToFlight
: The number of days until departure from today.DaysToFlightIndicator
: The criticality/coloring for the remaining days to flight- Colors: 1 = red | 2 = orange | 3 = green | 4 = grey | 5 = bleu
-
Now, uncomment the method call
calculate_trav_status_ind
within the methodCALCULATE
.<fs_book_original_data> = zrap110_calc_book_elem_###=>calculate_days_to_flight( <fs_book_original_data> ).
-
Save (Ctrl+S) and activate (Ctrl+F3) the changes. Close the ABAP class.
Test the enhanced SAP Fiori elements application.
🔵 Click to expand!
-
Refresh your browser or start the SAP Fiori elements app preview from your service binding
ZRAP110_UI_TRAVEL_O4_###
by double-clickin the Travel entity set.If you haven't created any entries, please do one travel entry now.
-
Click Go on the app and check the result.
-
Press the respective Gear icon and check their calculated values.
Now add the missing column (virtual elements) Overall Status Indicator on the list report and click OK.
-
Now you can see the Overall Status Indicator.
-
Select your entry.
Now click Edit.
Now you can see, that you are able to upload attachement on the Travel object page.
Now that you've...
- enabled the OData stream handling in the base BO to upload files
- added elements to the selection list and element/view annotations in the consumption view,
- added and implemented virtual elements on the consumption layer
- checked the preview,
you can continue with the next exercise – Exercise 3: Enhance the BO Behavior Definition and Projection