In this article, we will add a dynamic feature control on field “Agency ID” in our RAP application.
- Go to Behavior Definition
Add feature instance for Booking association.

We will control the creation of booking on specific condition.
Save and Activate
2. Use quick fix to generate code for dynamic feature


METHOD get_instance_features.
"Fetch Travel data with status
reaD ENTITIES OF zha_sa_travel in lOCAL MODE
enTITY Travel
fIELDS ( TravelId OverallStatus )
wITH corRESPONDING #( keys )
resULT data(lt_travel)
failed failed.
"Return the result with booking creation feature possibility
read table lt_travel intO data(ls_travel) inDEX 1.
if ( ls_travel-OverallStatus = 'X' )."rejected
data(lv_allow) = if_abap_behv=>fc-o-disabled.
else.
lv_allow = if_abap_behv=>fc-o-enabled.
endIF.
result = vaLUE #( for travel in lt_travel
( %tky = travel-%tky
%assoc-_Booking = lv_allow ) ).
ENDMETHOD.
Save and Activate
3. Full Code
Behavior Implementation Class
CLASS lhc_Travel DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result. METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION IMPORTING REQUEST requested_authorizations FOR Travel RESULT result. METHODS copyTravel FOR MODIFY IMPORTING keys FOR ACTION Travel~copyTravel. METHODS get_instance_features FOR INSTANCE FEATURES IMPORTING keys REQUEST requested_features FOR Travel RESULT result. METHODS earlynumbering_create FOR NUMBERING IMPORTING entities FOR CREATE Travel. METHODS earlynumbering_cba_Booking FOR NUMBERING IMPORTING entities FOR CREATE Travel\_Booking.ENDCLASS.CLASS lhc_Travel IMPLEMENTATION. METHOD get_instance_authorizations. ENDMETHOD. METHOD get_global_authorizations. ENDMETHOD. METHOD earlynumbering_create. DATA: entity TYPE STRUCTURE FOR CREATE zha_sa_travel, travel_id_max TYPE /dmo/travel_id. "Validate Travel ID LOOP AT entities INTO entity WHERE TravelId IS NOT INITIAL. APPEND CORRESPONDING #( entity ) TO mapped-travel. ENDLOOP. DATA(lt_entities) = entities. DELETE lt_entities WHERE TravelId IS NOT INITIAL. "Get number range from SNRO TRY. cl_numberrange_runtime=>number_get( EXPORTING nr_range_nr = '01' object = CONV #( '/DMO/TRAVL' ) quantity = CONV #( lines( lt_entities ) ) IMPORTING number = DATA(number_range_key) returncode = DATA(number_range_return_code) returned_quantity = DATA(number_range_returned_quantity) ). CATCH cx_number_ranges INTO DATA(lx_number_ranges). LOOP AT lt_entities INTO entity. APPEND VALUE #( %cid = entity-%cid %key = entity-%key %msg = lx_number_ranges ) TO reported-travel. APPEND VALUE #( %cid = entity-%cid %key = entity-%key ) TO failed-travel. ENDLOOP. EXIT. ENDTRY. CASE number_range_return_code. WHEN '1'. "Number range exceeded LOOP AT lt_entities INTO entity. APPEND VALUE #( %cid = entity-%cid %key = entity-%key %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>number_range_depleted severity = if_abap_behv_message=>severity-warning ) ) TO reported-travel. ENDLOOP. WHEN '2' OR '3'. APPEND VALUE #( %cid = entity-%cid %key = entity-%key %msg = NEW /dmo/cm_flight_messages( textid = /dmo/cm_flight_messages=>not_sufficient_numbers severity = if_abap_behv_message=>severity-warning ) ) TO reported-travel. APPEND VALUE #( %cid = entity-%cid %key = entity-%key %fail-cause = if_abap_behv=>cause-conflict ) TO failed-travel. ENDCASE. "Check all numbers ASSERT number_range_returned_quantity = lines( lt_entities ). "Assign the number range to the mapped data travel_id_max = number_range_key - number_range_returned_quantity. LOOP AT lt_entities INTO entity. travel_id_max += 1. entity-TravelId = travel_id_max. reported-%other = VALUE #( ( new_message_with_text( severity = if_abap_behv_message=>severity-success text = 'Travel id has been created.') ) ). APPEND VALUE #( %cid = entity-%cid %key = entity-%key ) TO mapped-travel. ENDLOOP. ENDMETHOD. METHOD earlynumbering_cba_Booking. DATA lv_max_booking_id TYPE /dmo/booking_id. "read Travel data READ ENTITIES OF zha_sa_travel IN LOCAL MODE ENTITY travel BY \_Booking FROM CORRESPONDING #( entities ) LINK DATA(bookings). "Loop on unique Travel Id LOOP AT entities ASSIGNING FIELD-SYMBOL(<lfs_travel_grp>) GROUP BY <lfs_travel_grp>-TravelId. "Get highest booking number LOOP AT bookings INTO DATA(ls_booking) USING KEY entity WHERE source-TravelId = <lfs_travel_grp>-TravelId. IF lv_max_booking_id < ls_booking-target-BookingId. lv_max_booking_id = ls_booking-target-BookingId. ENDIF. ENDLOOP. "Get assigned booking numbers LOOP AT entities INTO DATA(ls_entity) USING KEY entity WHERE travelId = <lfs_travel_grp>-TravelId. LOOP AT ls_entity-%target INTO DATA(ls_target). IF lv_max_booking_id < ls_target-BookingId. lv_max_booking_id = ls_target-BookingId. ENDIF. ENDLOOP. ENDLOOP. "Loop on entities LOOP AT entities ASSIGNING FIELD-SYMBOL(<lfs_travel>) USING KEY entity WHERE TravelId = <lfs_travel_grp>-TravelId. "Assign booking id to booking entity for each Travel Id LOOP AT <lfs_travel>-%target ASSIGNING FIELD-SYMBOL(<lfs_booking>). APPEND CORRESPONDING #( <lfs_booking> ) TO mapped-booking ASSIGNING FIELD-SYMBOL(<lfs_mapped_booking>). IF <lfs_mapped_booking>-BookingId IS INITIAL. lv_max_booking_id += 10. <lfs_mapped_booking>-BookingId = lv_max_booking_id. ENDIF. ENDLOOP. ENDLOOP. ENDLOOP. ENDMETHOD. METHOD copyTravel. DATA: travels TYPE TABLE FOR CREATE zha_sa_travel\\Travel, bookings_cba TYPE TABLE FOR CREATE zha_sa_travel\\Travel\_Booking, bookingsuppl_cba TYPE TABLE FOR CREATE zha_sa_travel\\Booking\_BookingSupplement. "Remove the travel instances with initial ID READ TABLE keys WITH KEY %cid = '' INTO DATA(key_with_intitial_cid). ASSERT key_with_intitial_cid IS INITIAL. "Read travel, Booking and booking supplement using EML READ ENTITIES OF zha_sa_travel IN LOCAL MODE ENTITY Travel ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(travel_read_result) FAILED failed. READ ENTITIES OF zha_sa_travel IN LOCAL MODE ENTITY Travel BY \_Booking ALL FIELDS WITH CORRESPONDING #( travel_read_result ) RESULT DATA(booking_read_result) FAILED failed. READ ENTITIES OF zha_sa_travel IN LOCAL MODE ENTITY booking BY \_BookingSupplement ALL FIELDS WITH CORRESPONDING #( booking_read_result ) RESULT DATA(booksuppl_read_result) FAILED failed. "Fill Travel internal table for Travel data creation LOOP AT travel_read_result ASSIGNING FIELD-SYMBOL(<lfs_travel>). "Travel data prepration APPEND VALUE #( %cid = keys[ %tky = <lfs_travel>-%tky ]-%cid %data = CORRESPONDING #( <lfs_travel> EXCEPT travelId ) ) TO travels ASSIGNING FIELD-SYMBOL(<lfs_new_travel>). <lfs_new_travel>-BeginDate = cl_abap_context_info=>get_system_date( ). <lfs_new_travel>-EndDate = cl_abap_context_info=>get_system_date( ) + 30. "Fill booking internal table for booking data creation APPEND VALUE #( %cid_ref = keys[ KEY entity %tky = <lfs_travel>-%tky ]-%cid ) TO bookings_cba ASSIGNING FIELD-SYMBOL(<lfs_bookings_cba>). LOOP AT booking_read_result ASSIGNING FIELD-SYMBOL(<lfs_booking>) WHERE TravelId = <lfs_travel>-TravelId. APPEND VALUE #( %cid = keys[ KEY entity %tky = <lfs_travel>-%tky ]-%cid && <lfs_booking>-BookingId %data = CORRESPONDING #( booking_read_result[ KEY entity %tky = <lfs_booking>-%tky ] EXCEPT TravelId ) ) TO <lfs_bookings_cba>-%target ASSIGNING FIELD-SYMBOL(<lfs_new_boking>). <lfs_new_boking>-BookingStatus = 'N'. "Fill booking supplement internal table for booking supplement data creation APPEND VALUE #( %cid_ref = keys[ KEY entity %tky = <lfs_travel>-%tky ]-%cid && <lfs_booking>-BookingId ) TO bookingsuppl_cba ASSIGNING FIELD-SYMBOL(<lfs_booksuppl_cba>). LOOP AT booksuppl_read_result ASSIGNING FIELD-SYMBOL(<lfs_booksuppl>) USING KEY entity WHERE TravelId = <lfs_travel>-TravelId AND BookingId = <lfs_booking>-BookingId. APPEND VALUE #( %cid = keys[ KEY entity %tky = <lfs_travel>-%tky ]-%cid && <lfs_booking>-BookingId && <lfs_booksuppl>-BookingSupplementId %data = CORRESPONDING #( <lfs_booksuppl> EXCEPT TravelId BookingId ) ) TO <lfs_booksuppl_cba>-%target. ENDLOOP. ENDLOOP. ENDLOOP. "Create a New BO instance using existing data MODIFY ENTITIES OF zha_sa_travel IN LOCAL MODE ENTITY Travel CREATE FIELDS ( AgencyId CustomerId BeginDate EndDate BookingFee TotalPrice CurrencyCode OverallStatus ) WITH travels CREATE BY \_Booking FIELDS ( Bookingid BookingDate CustomerId CarrierId ConnectionId FlightDate FlightPrice CurrencyCode BookingStatus ) WITH bookings_cba ENTITY Booking CREATE BY \_BookingSupplement FIELDS ( bookingsupplementid supplementid price currencycode ) WITH bookingsuppl_cba MAPPED DATA(mapped_create). mapped-travel = mapped_create-travel. ENDMETHOD. METHOD get_instance_features. "Fetch Travel data with status reaD ENTITIES OF zha_sa_travel in lOCAL MODE enTITY Travel fIELDS ( TravelId OverallStatus ) wITH corRESPONDING #( keys ) resULT data(lt_travel) failed failed. "Return the result with booking creation feature possibility read table lt_travel intO data(ls_travel) inDEX 1. if ( ls_travel-OverallStatus = 'X' )."rejected data(lv_allow) = if_abap_behv=>fc-o-disabled. else. lv_allow = if_abap_behv=>fc-o-enabled. endIF. result = vaLUE #( for travel in lt_travel ( %tky = travel-%tky %assoc-_Booking = lv_allow ) ). ENDMETHOD.ENDCLASS.
Behavior Definition
managed;
strict ( 2 );
define behavior for zha_sa_travel alias Travel
implementation in class zbp_ha_sa_travel unique
persistent table /dmo/travel_m
lock master
authorization master ( instance )
//To autogenerate Travel ID
early numbering
etag master LastChangedAt
{
create ( authorization : global);
update;
delete;
field ( readonly ) TravelId;
field ( mandatory ) AgencyId, CustomerId, BeginDate, EndDate, OverallStatus,BookingFee, CurrencyCode;
//Data action to create new instance
factory action copyTravel[1];
association _Booking { create ( features:instance ); }
mapping for /dmo/travel_m
{
TravelId = travel_id;
AgencyId = agency_id;
CustomerId = customer_id;
BeginDate = begin_date;
EndDate = end_date;
TotalPrice = total_price;
CurrencyCode = currency_code;
BookingFee = booking_fee;
LastChangedAt = last_changed_at;
LastChangedBy = last_changed_by;
CreatedAt = created_at;
CreatedBy = created_by;
OverallStatus = overall_status;
Description = description;
}
}
define behavior for zha_sa_booking alias Booking
implementation in class zbp_ha_sa_booking unique
persistent table /dmo/booking_m
lock dependent by _Travel
authorization dependent by _Travel
etag master LastChangedAt
early numbering
{
update;
delete;
field ( readonly ) TravelId, BookingId;
field ( mandatory ) CarrierId, ConnectionId, FlightDate, BookingStatus;
association _Travel;
association _BookingSupplement { create; }
mapping for /dmo/booking_m
{
TravelId = travel_id;
BookingId = booking_id;
BookingDate = booking_date;
CustomerId = customer_id;
CarrierID = carrier_id;
ConnectionId = connection_id;
FlightDate = flight_date;
CurrencyCode = currency_code;
BookingStatus = booking_status;
LastChangedAt = last_changed_at;
}
}
define behavior for zha_sa_booksuppl alias BookingSuppl
implementation in class zbp_ha_sa_booksuppl unique
persistent table /dmo/booksuppl_m
lock dependent by _Travel
authorization dependent by _Travel
etag master LastChangedAt
early numbering
{
update;
delete;
field ( readonly ) TravelId, BookingId;
field ( mandatory) Price, SupplementId;
association _Travel;
association _Booking;
mapping for /dmo/booksuppl_m
{
TravelId = travel_id;
BookingId = booking_id;
BookingSupplementId = booking_supplement_id;
SupplementId = supplement_id;
price = price;
CurrencyCode = currency_code;
LastChangedAt = last_changed_at;
}
}
4. Output
If the Travel request is open user will be able to create booking and if it is rejected then creation of booking is not allowed.
Click on Open Status Travel request

As you can see Create option is available for Over Status = ‘Open’

Go back and click on rejected Travel request

As you can see Create Booking option is not available for rejected Travel requests

Thanks for reading!

Leave a Reply