Global Feature Contron in RAP, Feature control in RAP

Estimated read time 13 min read

Hello Everyone, 

 In this blog post we are going to Learn about Global Feature Control in RAP.   

Global feature control in the RAP (RESTful Application Programming) model is used to enable or disable specific features for all users at once, regardless of individual data records or instances. It defines whether a particular operation (like create, update, or delete) is globally allowed or restricted. To do this, we extend the operation in the behavior definition as we did earlier for the instance feature.   

Delete (features: global); 

To implement a global feature, the “get_global_features” method must be implemented. As previously described, there is no transfer of the keys from the outside. The derivation of the various features must be based on other criteria. 

Procedure:

Here we are defining a Custom table (ZKK_DT_TRAVEL). 

The table zkk_dt_travel is a transparent table in SAP that stores travel-related information. It includes details such as travel ID, agency ID, customer ID, travel dates, booking fees, total price, currency, status and a description. It also tracks the creation and modification details like created by, created at, last changed by, and last changed at. 

@EndUserText.label : ‘Travel table’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zkk_dt_travel {

key client : abap.clnt not null;
key travel_id : /dmo/travel_id not null;
agency_id : /dmo/agency_id;
customer_id : /dmo/customer_id;
begin_date : /dmo/begin_date;
end_date : /dmo/end_date;
@Semantics.amount.currencyCode : ‘/dmo/travel_m.currency_code’
booking_fee : abap.curr(16,2);
@Semantics.amount.currencyCode : ‘/dmo/travel_m.currency_code’
total_price : /dmo/total_price;
currency_code : /dmo/currency_code;
description : /dmo/description;
status : abap_boolean;
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
last_changed_at : abp_locinst_lastchange_tstmpl;

}

The Above table holds the records which are given below 

For this database table(ZKK_DT_TRAVEL) we are defining the Basic view/Interface view. 

The ZKK_I_TRAVEL is a CDS view based on the zkk_dt_travel  table. It provides a structured way to access travel data, including fields like travel ID, agency ID, customer ID, travel dates, booking fees, total price, currency, and timestamps. It uses annotations to enhance usability, such as semantic tags for amounts, currencies, and metadata for created/changed users and timestamps. 

@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Interface view for Travelling’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity ZKK_I_TRAVEL
as select from zkk_dt_travel
{
key travel_id as TravelId,
agency_id as AgencyId,
customer_id as CustomerId,
begin_date as BeginDate,
end_date as EndDate,
@Semantics.amount.currencyCode: ‘CurrencyCode’
booking_fee as bookingfee,
@Semantics.amount.currencyCode: ‘CurrencyCode’
total_price as TotalPrice,
currency_code as CurrencyCode,
description as Description,
status as status,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt
}

 Now I am defining the Projection view on top of interface view. 

@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘projection view for Travel’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity ZKK_C_TRAVEL
as projection on ZKK_I_TRAVEL as Travel
{
key TravelId,
AgencyId,
CustomerId,
BeginDate,
EndDate,
@Semantics.amount.currencyCode: ‘CurrencyCode’
bookingfee,
@Semantics.amount.currencyCode: ‘CurrencyCode’
TotalPrice,
CurrencyCode,
Description,
status,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt
}

Now I am defining the Metadata Extension for projection View.

@Metadata.layer: #PARTNER
annotate entity ZKK_C_TRAVEL with
{
@ui.facet: [{
purpose: #STANDARD,
position: 10,
type : #IDENTIFICATION_REFERENCE,
label: ‘Travel Details’
}]

@ui.identification: [{ position: 10, label: ‘Travel Id’ }]
@ui.lineItem: [{ label: ‘Travel Id’ }]
TravelId;

@ui.identification: [{ position: 20, label: ‘Agency Id’ }]
@ui.lineItem: [{ label: ‘Agency Id’ }]
AgencyId;

@ui.identification: [{ position: 30, label: ‘Customer Id’ }]
@ui.lineItem: [{ label: ‘Customer Id’ }]
CustomerId;

@ui.identification: [{ position: 40, label: ‘Begin Date’ }]
@ui.lineItem: [{ label: ‘Begin Date’ }]
BeginDate;

@ui.identification: [{ position: 50, label: ‘End Date’ }]
@ui.lineItem: [{ label: ‘End Date’ }]
EndDate;

@ui.identification: [{ position: 60, label: ‘Booking Fee’ }]
@ui.lineItem: [{ label: ‘Booking Fee’ }]
bookingfee;

@ui.identification: [{ position: 70, label: ‘Total Price’ }]
@ui.lineItem: [{ label: ‘Total Price’ }]
TotalPrice;

@ui.identification: [{ position: 80, label: ‘Status Confirm’ },
{ type: #FOR_ACTION, dataAction: ‘status’, label: ‘Status Confirm’ } ]
@ui.lineItem: [{ label: ‘Status’ },
{ type: #FOR_ACTION, dataAction: ‘status’, label: ‘Confirm Status’ }]
status;

@ui.identification: [{ position: 100, label: ‘Currency’ }]
@ui.lineItem: [{ label: ‘Currency’ }]
CurrencyCode;

@ui.identification: [{ position: 90, label: ‘Description’ }]
@ui.lineItem: [{ label: ‘Description’ }]
Description;

@ui.identification: [{ position: 110, label: ‘Created By’ }]
@ui.lineItem: [{ label: ‘Created By’ }]
CreatedBy;

@ui.identification: [{ position: 120, label: ‘Created At’ }]
@ui.lineItem: [{ label: ‘Created At’ }]
CreatedAt;

@ui.identification: [{ position: 130, label: ‘Last Changed By’ }]
@ui.lineItem: [{ label: ‘Last Changed By’ }]
LastChangedBy;

@ui.identification: [{ position: 140, label: ‘Last Changed At’ }]
@ui.lineItem: [{ label: ‘Last Chnaged at’ }]
LastChangedAt;
}

Lets Define the Behaviour Definition.

managed implementation in class zbp_kk_i_travel unique;
strict ( 2 );

define behavior for ZKK_I_TRAVEL alias Travel //alias <alias_name>
persistent table zkk_dt_travel
lock master
authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete ( features : global );
field ( readonly : update ) TravelId;
field ( readonly ) LastChangedAt, LastChangedBy, CreatedAt, CreatedBy;
field ( mandatory : create ) AgencyId, CustomerId, BeginDate, EndDate, bookingfee, CurrencyCode;
action ( features : instance ) status result [1] $self;

mapping for ZKK_DT_TRAVEL {
TravelId = travel_id;
AgencyId = agency_id;
CustomerId = customer_id;
BeginDate = begin_date;
EndDate = end_date;
bookingfee = booking_fee;
TotalPrice = total_price;
CurrencyCode = currency_code;
Description = description;
status = status;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}
}

Here in Behavior definition, we have to specify 

delete (features: global); 

as we are performing delete operation 

After that we will get a warning as given below 

When we double click on that warning GET_GLOBAL_FEATURE method will get automatically. 

You can observe there is no KEYS parameter, that means we cannot read the details of selected record from here, we will get only the global data. 

Now we have to implement our custom logic inside the above given method. 

METHOD get_global_features.

if requested_features-%delete = if_abap_behv=>mk-on.
Data(lv_result) = COND #( when cl_abap_context_info=>get_user_alias( ) = ‘xyz@gmail.com’
then if_abap_behv=>mk-on
else if_abap_behv=>mk-off
).

result-%delete = lv_result.

ENDIF.

ENDMETHOD.

 Here we have to take the username or mail id which is registed on your SAP Universal ID, so for example i have taken ‘xyz@gmail.com’.

Above logic is to make delete button enable or disable 

When the user is xyz@gmail.com then the delete button will be enabled  

(Requested features contains the actions which are specified with (features: global))  

Preview the data 

The user logged-in is xyz@gmail.com 

The delete button is enabled 

Rewriting the code 

When the user is xyz@gmail.com then i want the delete button to be disabled 

METHOD get_global_features.

if requested_features-%delete = if_abap_behv=>mk-on.
Data(lv_result) = COND #( when cl_abap_context_info=>get_user_alias( ) = ‘xyz@gmail.com’
then if_abap_behv=>mk-off
else if_abap_behv=>mk-on
).

result-%delete = lv_result.

ENDIF.

ENDMETHOD.

When we RUN the application. 

We dont get Delete option as enables, here it is disable for that particular user.

Conclusion: 

Global feature control in RAP provides a centralized way to enable or disable specific operations across the entire application, regardless of individual records or user roles. It ensures consistent enforcement of business rules by globally restricting actions like create, update, or delete. This approach simplifies feature management, enhances data security, and ensures uniform behavior, making it an effective mechanism for controlling access and operations at the application level. 

 

 

​ Hello Everyone,  In this blog post we are going to Learn about Global Feature Control in RAP.   Global feature control in the RAP (RESTful Application Programming) model is used to enable or disable specific features for all users at once, regardless of individual data records or instances. It defines whether a particular operation (like create, update, or delete) is globally allowed or restricted. To do this, we extend the operation in the behavior definition as we did earlier for the instance feature.   Delete (features: global); To implement a global feature, the “get_global_features” method must be implemented. As previously described, there is no transfer of the keys from the outside. The derivation of the various features must be based on other criteria. Procedure:Here we are defining a Custom table (ZKK_DT_TRAVEL). The table zkk_dt_travel is a transparent table in SAP that stores travel-related information. It includes details such as travel ID, agency ID, customer ID, travel dates, booking fees, total price, currency, status and a description. It also tracks the creation and modification details like created by, created at, last changed by, and last changed at. @EndUserText.label : ‘Travel table’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zkk_dt_travel {

key client : abap.clnt not null;
key travel_id : /dmo/travel_id not null;
agency_id : /dmo/agency_id;
customer_id : /dmo/customer_id;
begin_date : /dmo/begin_date;
end_date : /dmo/end_date;
@Semantics.amount.currencyCode : ‘/dmo/travel_m.currency_code’
booking_fee : abap.curr(16,2);
@Semantics.amount.currencyCode : ‘/dmo/travel_m.currency_code’
total_price : /dmo/total_price;
currency_code : /dmo/currency_code;
description : /dmo/description;
status : abap_boolean;
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
last_changed_at : abp_locinst_lastchange_tstmpl;

}The Above table holds the records which are given below For this database table(ZKK_DT_TRAVEL) we are defining the Basic view/Interface view. The ZKK_I_TRAVEL is a CDS view based on the zkk_dt_travel  table. It provides a structured way to access travel data, including fields like travel ID, agency ID, customer ID, travel dates, booking fees, total price, currency, and timestamps. It uses annotations to enhance usability, such as semantic tags for amounts, currencies, and metadata for created/changed users and timestamps. @AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Interface view for Travelling’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity ZKK_I_TRAVEL
as select from zkk_dt_travel
{
key travel_id as TravelId,
agency_id as AgencyId,
customer_id as CustomerId,
begin_date as BeginDate,
end_date as EndDate,
@Semantics.amount.currencyCode: ‘CurrencyCode’
booking_fee as bookingfee,
@Semantics.amount.currencyCode: ‘CurrencyCode’
total_price as TotalPrice,
currency_code as CurrencyCode,
description as Description,
status as status,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt
} Now I am defining the Projection view on top of interface view. @AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘projection view for Travel’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity ZKK_C_TRAVEL
as projection on ZKK_I_TRAVEL as Travel
{
key TravelId,
AgencyId,
CustomerId,
BeginDate,
EndDate,
@Semantics.amount.currencyCode: ‘CurrencyCode’
bookingfee,
@Semantics.amount.currencyCode: ‘CurrencyCode’
TotalPrice,
CurrencyCode,
Description,
status,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt
}Now I am defining the Metadata Extension for projection View.@Metadata.layer: #PARTNER
annotate entity ZKK_C_TRAVEL with
{
@ui.facet: [{
purpose: #STANDARD,
position: 10,
type : #IDENTIFICATION_REFERENCE,
label: ‘Travel Details’
}]

@ui.identification: [{ position: 10, label: ‘Travel Id’ }]
@ui.lineItem: [{ label: ‘Travel Id’ }]
TravelId;

@ui.identification: [{ position: 20, label: ‘Agency Id’ }]
@ui.lineItem: [{ label: ‘Agency Id’ }]
AgencyId;

@ui.identification: [{ position: 30, label: ‘Customer Id’ }]
@ui.lineItem: [{ label: ‘Customer Id’ }]
CustomerId;

@ui.identification: [{ position: 40, label: ‘Begin Date’ }]
@ui.lineItem: [{ label: ‘Begin Date’ }]
BeginDate;

@ui.identification: [{ position: 50, label: ‘End Date’ }]
@ui.lineItem: [{ label: ‘End Date’ }]
EndDate;

@ui.identification: [{ position: 60, label: ‘Booking Fee’ }]
@ui.lineItem: [{ label: ‘Booking Fee’ }]
bookingfee;

@ui.identification: [{ position: 70, label: ‘Total Price’ }]
@ui.lineItem: [{ label: ‘Total Price’ }]
TotalPrice;

@ui.identification: [{ position: 80, label: ‘Status Confirm’ },
{ type: #FOR_ACTION, dataAction: ‘status’, label: ‘Status Confirm’ } ]
@ui.lineItem: [{ label: ‘Status’ },
{ type: #FOR_ACTION, dataAction: ‘status’, label: ‘Confirm Status’ }]
status;

@ui.identification: [{ position: 100, label: ‘Currency’ }]
@ui.lineItem: [{ label: ‘Currency’ }]
CurrencyCode;

@ui.identification: [{ position: 90, label: ‘Description’ }]
@ui.lineItem: [{ label: ‘Description’ }]
Description;

@ui.identification: [{ position: 110, label: ‘Created By’ }]
@ui.lineItem: [{ label: ‘Created By’ }]
CreatedBy;

@ui.identification: [{ position: 120, label: ‘Created At’ }]
@ui.lineItem: [{ label: ‘Created At’ }]
CreatedAt;

@ui.identification: [{ position: 130, label: ‘Last Changed By’ }]
@ui.lineItem: [{ label: ‘Last Changed By’ }]
LastChangedBy;

@ui.identification: [{ position: 140, label: ‘Last Changed At’ }]
@ui.lineItem: [{ label: ‘Last Chnaged at’ }]
LastChangedAt;
}Lets Define the Behaviour Definition.managed implementation in class zbp_kk_i_travel unique;
strict ( 2 );

define behavior for ZKK_I_TRAVEL alias Travel //alias <alias_name>
persistent table zkk_dt_travel
lock master
authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete ( features : global );
field ( readonly : update ) TravelId;
field ( readonly ) LastChangedAt, LastChangedBy, CreatedAt, CreatedBy;
field ( mandatory : create ) AgencyId, CustomerId, BeginDate, EndDate, bookingfee, CurrencyCode;
action ( features : instance ) status result [1] $self;

mapping for ZKK_DT_TRAVEL {
TravelId = travel_id;
AgencyId = agency_id;
CustomerId = customer_id;
BeginDate = begin_date;
EndDate = end_date;
bookingfee = booking_fee;
TotalPrice = total_price;
CurrencyCode = currency_code;
Description = description;
status = status;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}
}Here in Behavior definition, we have to specify delete (features: global); as we are performing delete operation After that we will get a warning as given below When we double click on that warning GET_GLOBAL_FEATURE method will get automatically. You can observe there is no KEYS parameter, that means we cannot read the details of selected record from here, we will get only the global data. Now we have to implement our custom logic inside the above given method.  METHOD get_global_features.

if requested_features-%delete = if_abap_behv=>mk-on.
Data(lv_result) = COND #( when cl_abap_context_info=>get_user_alias( ) = ‘xyz@gmail.com’
then if_abap_behv=>mk-on
else if_abap_behv=>mk-off
).

result-%delete = lv_result.

ENDIF.

ENDMETHOD. Here we have to take the username or mail id which is registed on your SAP Universal ID, so for example i have taken ‘xyz@gmail.com’.Above logic is to make delete button enable or disable When the user is xyz@gmail.com then the delete button will be enabled  (Requested features contains the actions which are specified with (features: global))  Preview the data The user logged-in is xyz@gmail.com The delete button is enabled Rewriting the code When the user is xyz@gmail.com then i want the delete button to be disabled  METHOD get_global_features.

if requested_features-%delete = if_abap_behv=>mk-on.
Data(lv_result) = COND #( when cl_abap_context_info=>get_user_alias( ) = ‘xyz@gmail.com’
then if_abap_behv=>mk-off
else if_abap_behv=>mk-on
).

result-%delete = lv_result.

ENDIF.

ENDMETHOD.When we RUN the application. We dont get Delete option as enables, here it is disable for that particular user.Conclusion: Global feature control in RAP provides a centralized way to enable or disable specific operations across the entire application, regardless of individual records or user roles. It ensures consistent enforcement of business rules by globally restricting actions like create, update, or delete. This approach simplifies feature management, enhances data security, and ensures uniform behavior, making it an effective mechanism for controlling access and operations at the application level.     Read More Application Development and Automation Blog Posts articles 

#SAP

You May Also Like

More From Author