In the previous exercise, you've enhanced the UI semantics of your Travel app by enhancing the metadata extensions (see Exercise 5).
In the present exercise, you're going to implement back-end validations, validateCustomer
, validateAgency
, and validateDates
, to respectively check if the customer ID and the agency name that is entered by the consumer are valid, and if the begin date is in the future and if the value of the end date is after the begin date. These validations are only performed in the back-end (not on the UI) and are triggered independently of the caller, i.e. Fiori UIs or EML APIs.
ℹ Similar validations were already handled in RAP100. Therefore, you will simply adopt the provided source code. We will use the validations for playing around with features such as determine actions and side effects.
- 6.1 - Implement the Validations of the Travel BO Entity 💡
- 6.2 - Implement the Validations of the Booking BO Entity
- 6.3 - Preview and Test the enhanced Travel App
- Summary
Reminder: Do not forget to replace the suffix placeholder
###
with your choosen or assigned assigned suffix in the exercise steps below.
Click to expand!
A validation is an optional part of the business object behavior that checks the consistency of business object instances based on trigger conditions.
A validation is implicitly invoked by the business object’s framework if the trigger condition of the validation is fulfilled. Trigger conditions can be MODIFY
operations and modified fields. The trigger condition is evaluated at the trigger time, a predefined point during the BO runtime. An invoked validation can reject inconsistent instance data from being saved by passing the keys of failed instances to the corresponding table in the FAILED
structure. Additionally, a validation can return messages to the consumer by passing them to the corresponding table in the REPORTED
structure.
Further reading: Validations
Enhance the behavior implementation class of the travel entity with the business logic for the validation methods
validateCustomer
,validateAgency
, andvalidateDates
.
💡 There are two (2) ways to complete exercise 6.1:
Option 1️⃣: This is the recommended option. Replace the whole content of your behavior implementation class of the travel entity ZRAP110_BP_TRAVELTP_### with the provided source code document linked below and replace the placeholder
###
with your assigned suffix. Save and activate the changes, then procedd directly with Exercise 6.2.📄 Source code document: Behavior Implementation Class ZRAP110_BP_TRAVELTP_###
Option 2️⃣: Carry out the steps described below (6.1) in sequence.
🔵 Click to expand!
Implement the validation
validateCustomer
which checks if the customer ID (CustomerID
) that is entered by the consumer is valid.
An appropriate message should be raised and displayed on the UI for each invalid value.
🟣 Click to expand!
-
In your implementation class of the travel entity
ZRAP110_BP_TRAVELTP_###
, replace the current method implementation ofvalidateCustomer
with following code snippet.Replace all occurrences of the placeholder
###
with your assigned suffix.METHOD validateCustomer. "read relevant travel instance data READ ENTITIES OF ZRAP110_R_TravelTP_### IN LOCAL MODE ENTITY Travel FIELDS ( CustomerID ) WITH CORRESPONDING #( keys ) RESULT DATA(travels). DATA customers TYPE SORTED TABLE OF /dmo/customer WITH UNIQUE KEY customer_id. "optimization of DB select: extract distinct non-initial customer IDs customers = CORRESPONDING #( travels DISCARDING DUPLICATES MAPPING customer_id = customerID EXCEPT * ). DELETE customers WHERE customer_id IS INITIAL. IF customers IS NOT INITIAL. "check if customer ID exists SELECT FROM /dmo/customer FIELDS customer_id FOR ALL ENTRIES IN @customers WHERE customer_id = @customers-customer_id INTO TABLE @DATA(valid_customers). ENDIF. "raise msg for non existing and initial customer id LOOP AT travels INTO DATA(travel). APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_CUSTOMER' ) TO reported-travel. IF travel-CustomerID IS INITIAL. APPEND VALUE #( %tky = travel-%tky ) TO failed-travel. APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_CUSTOMER' %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>enter_customer_id severity = if_abap_behv_message=>severity-error ) %element-CustomerID = if_abap_behv=>mk-on ) TO reported-travel. ELSEIF travel-CustomerID IS NOT INITIAL AND NOT line_exists( valid_customers[ customer_id = travel-CustomerID ] ). APPEND VALUE #( %tky = travel-%tky ) TO failed-travel. APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_CUSTOMER' %msg = NEW /dmo/cm_flight_messages( customer_id = travel-customerid textid = /dmo/cm_flight_messages=>customer_unkown severity = if_abap_behv_message=>severity-error ) %element-CustomerID = if_abap_behv=>mk-on ) TO reported-travel. ENDIF. ENDLOOP. ENDMETHOD.
Implement the validation
validateAgency
which checks if the agency ID (elementAgencyID
) that is entered by the consumer is valid.
An appropriate message should be raised and displayed on the UI for each invalid value.
🟣 Click to expand!
-
In your implementation class of the travel entity
ZRAP110_BP_TRAVELTP_###
, replace the current method implementation ofvalidateAgency
with following code snippet.Replace all occurrences of the placeholder
###
with your assigned suffix.METHOD validateAgency. " Read relevant travel instance data READ ENTITIES OF ZRAP110_R_TravelTP_### IN LOCAL MODE ENTITY travel FIELDS ( AgencyID ) WITH CORRESPONDING #( keys ) RESULT DATA(travels). DATA agencies TYPE SORTED TABLE OF /dmo/agency WITH UNIQUE KEY agency_id. " Optimization of DB select: extract distinct non-initial agency IDs agencies = CORRESPONDING #( travels DISCARDING DUPLICATES MAPPING agency_id = AgencyID EXCEPT * ). DELETE agencies WHERE agency_id IS INITIAL. IF agencies IS NOT INITIAL. " check if agency ID exist SELECT FROM /dmo/agency FIELDS agency_id FOR ALL ENTRIES IN @agencies WHERE agency_id = @agencies-agency_id INTO TABLE @DATA(agencies_db). ENDIF. " Raise msg for non existing and initial agency id LOOP AT travels INTO DATA(travel). APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_AGENCY' ) TO reported-travel. IF travel-AgencyID IS INITIAL OR NOT line_exists( agencies_db[ agency_id = travel-AgencyID ] ). APPEND VALUE #( %tky = travel-%tky ) TO failed-travel. APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_AGENCY' %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>agency_unkown agency_id = travel-AgencyID severity = if_abap_behv_message=>severity-error ) %element-AgencyID = if_abap_behv=>mk-on ) TO reported-travel. ENDIF. ENDLOOP. ENDMETHOD.
Implement the validation
validateDates
which checks if the begin date and the end date (elementsBeginDate
andEndDate
) that are entered by the consumer is valid.
An appropriate message should be raised and displayed on the UI for each invalid value.
🟣 Click to expand!
-
In your implementation class of the travel entity
ZRAP110_BP_TRAVELTP_###
, replace the current method implementation ofvalidateDates
with following code snippet.Replace all occurrences of the placeholder
###
with your assigned suffix.METHOD validateDates. READ ENTITIES OF ZRAP110_R_TravelTP_### IN LOCAL MODE ENTITY travel FIELDS ( BeginDate EndDate ) WITH CORRESPONDING #( keys ) RESULT DATA(travels). LOOP AT travels INTO DATA(travel). APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_DATES' ) TO reported-travel. IF travel-EndDate < travel-BeginDate. "end_date before begin_date APPEND VALUE #( %tky = travel-%tky ) TO failed-travel. APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_DATES' %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>begin_date_bef_end_date severity = if_abap_behv_message=>severity-error begin_date = travel-BeginDate end_date = travel-EndDate travel_id = travel-TravelID ) %element-BeginDate = if_abap_behv=>mk-on %element-EndDate = if_abap_behv=>mk-on ) TO reported-travel. ELSEIF travel-BeginDate < cl_abap_context_info=>get_system_date( ). "begin_date must be in the future APPEND VALUE #( %tky = travel-%tky ) TO failed-travel. APPEND VALUE #( %tky = travel-%tky %state_area = 'VALIDATE_DATES' %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>begin_date_on_or_bef_sysdate severity = if_abap_behv_message=>severity-error ) %element-BeginDate = if_abap_behv=>mk-on %element-EndDate = if_abap_behv=>mk-on ) TO reported-travel. ENDIF. ENDLOOP. ENDMETHOD.
Enhance the behavior implementation class of the booking entity with the business logic for the validation method
validateBookingStatus
.
🔵 Click to expand!
Implement the validation
validateBookingStatus
which checks if the booking status (elementBookingStatus
) that is selected by the consumer is valid.An appropriate message should be raised and displayed on the UI for each invalid value.
🟣 Click to expand!
-
In your implementation class of the booking entity
ZRAP110_BP_BOOKINGTP_###
, insert the code snippet provided below into the method implementation ofvalidateBookingStatus
as shown on the scrrenshot.Replace all occurrences of the placeholder
###
with your assigned suffix.METHOD validateBookingStatus. READ ENTITIES OF ZRAP110_R_TravelTP_### IN LOCAL MODE ENTITY booking FIELDS ( BookingStatus ) WITH CORRESPONDING #( keys ) RESULT DATA(bookings). LOOP AT bookings INTO DATA(booking). CASE booking-BookingStatus. WHEN booking_status-new. " New WHEN booking_status-canceled. " Canceled WHEN booking_status-booked. " Booked WHEN OTHERS. APPEND VALUE #( %tky = booking-%tky ) TO failed-booking. APPEND VALUE #( %tky = booking-%tky %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>status_invalid status = booking-BookingStatus severity = if_abap_behv_message=>severity-error ) %element-BookingStatus = if_abap_behv=>mk-on %path = VALUE #( travel-TravelId = booking-TravelId ) ) TO reported-booking. ENDCASE. ENDLOOP. ENDMETHOD.
Note: the local constant
booking_status
was defined in the local handler classlhc_booking
in
Exercise 3.8.2: Adjust the Behavior Implementation Class of the Booking BO entity.
Now the SAP Fiori elements app can be tested.
⚠Please note⚠ that clicking on the Accept Travel and Reject Travel buttons at this stage will lead to errors on the UI, because they are not yet implemented.
🔵 Click to expand!
-
You can either refresh your application in the browser using F5 if the browser is still open - or go to your service binding
ZRAP110_UI_TRAVEL_O4_###
and start the Fiori elements App preview for theTravel
entity set. -
Click Create to create a new entry.
-
For example, select an
Sunshine Travel (70001)
as Agency ID, select a customer by starting to add a nameTheresia
, Nov 20, 2023 as starting date and Nov 16, 2023 as end date. The draft will be updated. -
Now click Create. You should get following error messages displayed:
Begin Date 11/20/2023 must not be after End Date 11/16/2023 .
Now that you've...
- Added the logic for various validations in the behavior definition,
- previewed and tested the enhanced Fiori elements app,
you can continue with the next exercise – Exercise 7: Implement the Base BO Behavior - Actions