Introduction
This blog provides a step-by-step guide on creating a Inventory Management and archiving the Determine action using RAP in a managed scenario. In RAP, determinations and validations are typically executed implicitly during save operations.
In this blog, where I will calculate the total value in an Inventory object only after the lastchangeat timestamp was set. We’ll solve this challenge using a Determine Action. Determine action allows to execute Determination and validation on request. Whenever a determine action is executed.
Scenario for Determine action:
When a user creates an Inventory entry with product details, the following must happen:
A default RAP determination should calculate total_value during create. The total_value should be calculated after the lastchangeat field is populated (which happens after the entity is saved). To achieve this, a custom Determine Action should be used post-save to trigger the actual determination.
Procedure:
Created one database table ‘ZDP_inventory
@EndUserText.label : ‘inventory table’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zdp_inventory {
key product_id : abap.int1 not null;
product_name : abap.char(50);
quantity : zdp_de_pdt_quantity;
@Semantics.amount.currencyCode : ‘zdp_inventory.currency_code’
unit_price : zdp_de_unit_price;
currency_code : abap.cuky;
@Semantics.amount.currencyCode : ‘zdp_inventory.currency_code’
total_value : abap.curr(13,2);
last_change_at : timestampl;
}
Now we need to create an interface view on top of DB table.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface entity view for inventory’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@Metadata.allowExtensions: true
define root view entity zdp_i_cds_inventory as
select from zdp_inventory
{
key product_id as ProductId,
product_name as ProductName,
quantity as Quantity,
@Semantics.amount.currencyCode : ‘currencycode’
unit_price as UnitPrice,
currency_code as CurrencyCode,
@Semantics.amount.currencyCode : ‘currencycode’
total_value as totalvalue,
@Semantics.systemDateTime.lastChangedAt: true
last_change_at as lastchangeat
}
Now we need to create a projection view on top of Interface view.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘projection view on inventory’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
define root view entity zdp_p_cds_inventory
provider contract transactional_query
as projection on zdp_i_cds_inventory
{
key ProductId,
ProductName,
Quantity,
@Semantics.amount.currencyCode : ‘currencycode’
UnitPrice,
CurrencyCode,
@Semantics.amount.currencyCode : ‘currencycode’
totalvalue,
lastchangeat
}
Now we need to create the behavior definition on top of interface view.
managed implementation in class zbp_dp_i_cds_inventory unique;
strict ( 2 );
define behavior for zdp_i_cds_inventory //alias <alias_name>
persistent table zdp_inventory
lock master
authorization master ( none )
{
create ;
update ( authorization : none );
delete ;
field ( readonly ) lastchangeat;
action Trigger_detmine_action result[1] $self;
determine action calc_total
{
determination ( always ) totalCalc;
validation checkQuantity;
}
determination totalCalc
on save
{ field lastchangeat; create; }
validation checkQuantity
on save
{ field Quantity; }
mapping for zdp_inventory
{
ProductId = product_id;
ProductName = product_name;
Quantity = quantity;
UnitPrice = unit_price;
CurrencyCode = currency_code;
totalvalue = total_value;
lastchangeat = last_change_at;
}
}
Now create a behavior definition on top of consumption view:
Code of Behavior Definition of Projection:
projection;
strict ( 2 );
define behavior for zdp_p_cds_inventory //alias <alias_name>
{
use create;
use update;
use delete;
use action Trigger_detmine_action;
use action calc_total;
}
To declare Determine action in Behavior Definition.
To trigger Determine action :
The determine action calc_total is executed with the statement MODIFY ENTITIES for entity instances.
Behavior implementation.
CLASS lhc_zdp_i_cds_inventory DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS checkquantity FOR VALIDATE ON SAVE
IMPORTING keys FOR zdp_i_cds_inventory~checkquantity.
METHODS trigger_detmine_action FOR MODIFY
IMPORTING keys FOR ACTION zdp_i_cds_inventory~trigger_detmine_action RESULT result.
METHODS totalcalc FOR DETERMINE ON SAVE
IMPORTING keys FOR zdp_i_cds_inventory~totalcalc.
ENDCLASS.
CLASS lhc_zdp_i_cds_inventory IMPLEMENTATION.
METHOD checkQuantity.
READ ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
FIELDS ( quantity )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result_qua).
DATA(ls_res_qua) = lt_result_qua[ 1 ].
IF ls_res_qua-Quantity IS INITIAL.
APPEND VALUE #( %tky = ls_res_qua-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = ‘Please provide quantity’
) ) TO reported-zdp_i_cds_inventory.
ENDIF.
ENDMETHOD.
METHOD Trigger_detmine_action.
READ ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
FIELDS ( ProductId )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result_prdt).
LOOP AT lt_result_prdt INTO DATA(ls_result).
MODIFY ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
EXECUTE calc_total
FROM VALUE #( ( ProductId = ls_result-ProductId ) )
MAPPED FINAL(lt_mapped)
FAILED FINAL(lt_failed)
REPORTED FINAL(lt_reported).
mapped-zdp_i_cds_inventory = lt_mapped-zdp_i_cds_inventory.
* COMMIT ENTITIES.
ENDLOOP.
ENDMETHOD.
METHOD totalCalc.
READ ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
FIELDS ( quantity unitprice )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result).
LOOP AT keys ASSIGNING FIELD-SYMBOL(<fs_keys>).
LOOP AT lt_result INTO DATA(ls_result).
IF ls_result-%tky = <fs_keys>-%tky.
ls_result-totalvalue = ls_result-quantity * ls_result-unitprice.
MODIFY ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
UPDATE
FIELDS ( totalvalue ) WITH VALUE #( ( %tky = <fs_keys>-%tky
totalvalue = ls_result-totalvalue ) ).
ENDIF.
ENDLOOP.
ENDLOOP.
.
ENDMETHOD.
ENDCLASS.
Output:
When we click on the action button at that time, determine action will trigger the total value is calculated.
Introduction This blog provides a step-by-step guide on creating a Inventory Management and archiving the Determine action using RAP in a managed scenario. In RAP, determinations and validations are typically executed implicitly during save operations.In this blog, where I will calculate the total value in an Inventory object only after the lastchangeat timestamp was set. We’ll solve this challenge using a Determine Action. Determine action allows to execute Determination and validation on request. Whenever a determine action is executed. Scenario for Determine action: When a user creates an Inventory entry with product details, the following must happen: A default RAP determination should calculate total_value during create. The total_value should be calculated after the lastchangeat field is populated (which happens after the entity is saved). To achieve this, a custom Determine Action should be used post-save to trigger the actual determination. Procedure: Created one database table ‘ZDP_inventory@EndUserText.label : ‘inventory table’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zdp_inventory {
key product_id : abap.int1 not null;
product_name : abap.char(50);
quantity : zdp_de_pdt_quantity;
@Semantics.amount.currencyCode : ‘zdp_inventory.currency_code’
unit_price : zdp_de_unit_price;
currency_code : abap.cuky;
@Semantics.amount.currencyCode : ‘zdp_inventory.currency_code’
total_value : abap.curr(13,2);
last_change_at : timestampl;
}Now we need to create an interface view on top of DB table. @AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface entity view for inventory’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@Metadata.allowExtensions: true
define root view entity zdp_i_cds_inventory as
select from zdp_inventory
{
key product_id as ProductId,
product_name as ProductName,
quantity as Quantity,
@Semantics.amount.currencyCode : ‘currencycode’
unit_price as UnitPrice,
currency_code as CurrencyCode,
@Semantics.amount.currencyCode : ‘currencycode’
total_value as totalvalue,
@Semantics.systemDateTime.lastChangedAt: true
last_change_at as lastchangeat
} Now we need to create a projection view on top of Interface view. @AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘projection view on inventory’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
define root view entity zdp_p_cds_inventory
provider contract transactional_query
as projection on zdp_i_cds_inventory
{
key ProductId,
ProductName,
Quantity,
@Semantics.amount.currencyCode : ‘currencycode’
UnitPrice,
CurrencyCode,
@Semantics.amount.currencyCode : ‘currencycode’
totalvalue,
lastchangeat
}Now we need to create the behavior definition on top of interface view. managed implementation in class zbp_dp_i_cds_inventory unique;
strict ( 2 );
define behavior for zdp_i_cds_inventory //alias <alias_name>
persistent table zdp_inventory
lock master
authorization master ( none )
{
create ;
update ( authorization : none );
delete ;
field ( readonly ) lastchangeat;
action Trigger_detmine_action result[1] $self;
determine action calc_total
{
determination ( always ) totalCalc;
validation checkQuantity;
}
determination totalCalc
on save
{ field lastchangeat; create; }
validation checkQuantity
on save
{ field Quantity; }
mapping for zdp_inventory
{
ProductId = product_id;
ProductName = product_name;
Quantity = quantity;
UnitPrice = unit_price;
CurrencyCode = currency_code;
totalvalue = total_value;
lastchangeat = last_change_at;
}
}Now create a behavior definition on top of consumption view: Code of Behavior Definition of Projection: projection;
strict ( 2 );
define behavior for zdp_p_cds_inventory //alias <alias_name>
{
use create;
use update;
use delete;
use action Trigger_detmine_action;
use action calc_total;
}To declare Determine action in Behavior Definition.To trigger Determine action :The determine action calc_total is executed with the statement MODIFY ENTITIES for entity instances.Behavior implementation. CLASS lhc_zdp_i_cds_inventory DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS checkquantity FOR VALIDATE ON SAVE
IMPORTING keys FOR zdp_i_cds_inventory~checkquantity.
METHODS trigger_detmine_action FOR MODIFY
IMPORTING keys FOR ACTION zdp_i_cds_inventory~trigger_detmine_action RESULT result.
METHODS totalcalc FOR DETERMINE ON SAVE
IMPORTING keys FOR zdp_i_cds_inventory~totalcalc.
ENDCLASS.
CLASS lhc_zdp_i_cds_inventory IMPLEMENTATION.
METHOD checkQuantity.
READ ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
FIELDS ( quantity )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result_qua).
DATA(ls_res_qua) = lt_result_qua[ 1 ].
IF ls_res_qua-Quantity IS INITIAL.
APPEND VALUE #( %tky = ls_res_qua-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = ‘Please provide quantity’
) ) TO reported-zdp_i_cds_inventory.
ENDIF.
ENDMETHOD.
METHOD Trigger_detmine_action.
READ ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
FIELDS ( ProductId )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result_prdt).
LOOP AT lt_result_prdt INTO DATA(ls_result).
MODIFY ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
EXECUTE calc_total
FROM VALUE #( ( ProductId = ls_result-ProductId ) )
MAPPED FINAL(lt_mapped)
FAILED FINAL(lt_failed)
REPORTED FINAL(lt_reported).
mapped-zdp_i_cds_inventory = lt_mapped-zdp_i_cds_inventory.
* COMMIT ENTITIES.
ENDLOOP.
ENDMETHOD.
METHOD totalCalc.
READ ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
FIELDS ( quantity unitprice )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result).
LOOP AT keys ASSIGNING FIELD-SYMBOL(<fs_keys>).
LOOP AT lt_result INTO DATA(ls_result).
IF ls_result-%tky = <fs_keys>-%tky.
ls_result-totalvalue = ls_result-quantity * ls_result-unitprice.
MODIFY ENTITIES OF zdp_i_cds_inventory IN LOCAL MODE
ENTITY zdp_i_cds_inventory
UPDATE
FIELDS ( totalvalue ) WITH VALUE #( ( %tky = <fs_keys>-%tky
totalvalue = ls_result-totalvalue ) ).
ENDIF.
ENDLOOP.
ENDLOOP.
.
ENDMETHOD.
ENDCLASS. Output: When we click on the action button at that time, determine action will trigger the total value is calculated. Read More Application Development and Automation Blog Posts articles
#SAP