
Hello SAP Community,
In this post, I will walk you through a technical solution for triggering workflow events from the save action of a Restful ABAP Programming (RAP) application. We aim to assign a buyer to each Purchase Requisition and send a workflow confirmation dialog to the buyer's inbox for necessary actions, such as creating a purchase order.
The main idea here is to utilize the unmanaged save in the behavior definition to call a function module in the background.
Using a managed save, the 'save' implementation method restricts you from calling functions, performing rollbacks, commits, or using classic ABAP statements. In contrast, an unmanaged save provides the 'save_modified' method, which allows you to call a function module in a background task and addresses the limitations of classic ABAP statements.
For more information, you can refer to this Q&A thread.
Let's dive into the implementation details.
We need to assign a buyer to each Purchase Requisition. Once the buyer is assigned, a workflow confirmation dialog is sent to their inbox, prompting them to take necessary actions, such as creating a purchase order.
To achieve this, we'll use an unmanaged save in the behavior definition to call a function module in the background. Here's a step-by-step guide on how to implement this solution.
Note: I will include my complete solution. You might notice several options in the behavior definition. such as:
authorization master (instance);
update (features: instance, precheck);
These instance options enable you to check for edit authority (i.e., who has the edit role).
Additionally, the validation ensures that the Buyer field is validated upon the save action.
validation validateBuyer on save { field Buyer; create; update; }
1. Apend the field Buyer which is from type same as system user (char12)
Note: I prefer to create a new z table without appending the field to standard table EBAN, but I used this case because I was searching for a way to add this editable field in standard screen of Purchase requisition ME53N .. anyway lets complete the structure ZEBAN is append structure for standard table EBAN
2. Implement the RAP Application Logic:
Create CDS View: we will use standard cds I_PurchaseReqnItem as reference because our app is most like the standard fiori app Process Purchase Requisitions (App ID F1048)
@EndUserText.label: 'PR Buyer Assign'
@Metadata.allowExtensions: true
@ObjectModel.modelCategory: #BUSINESS_OBJECT
@ObjectModel.compositionRoot: true
@ObjectModel.transactionalProcessingEnabled: true
@ObjectModel.writeActivePersistence: 'ZMM_PR_BUYER_BO'
@ObjectModel:{
createEnabled: true,
updateEnabled: true,
deleteEnabled: true
}
@Search.searchable: true
define root view entity ZCDS_PR_Buyer_Assign
as select from I_PurchaseReqnItem as header
inner join eban on eban.banfn = header.PurchaseRequisition and eban.bnfpo = header.PurchaseRequisitionItem
association [0..1] to I_PurchasingGroup as _PurchasingGroup on $projection.PurchasingGroup = _PurchasingGroup.PurchasingGroup
association [0..1] to pa0001 as pa on $projection.RequisitionerName = pa.pernr
{
//@Consumption.valueHelpDefinition: [{entity:{name:'C_PurchaseReqnHeader' , element: 'PurchaseRequisition'}}]
@Consumption.valueHelpDefinition: [{entity:{name:'ZCDS_PR_SEARCH_VALUE' , element: 'PurchaseRequisition'}}]
@Consumption.semanticObject: 'PurchaseRequisition'
//semanticObjectAction : 'displayAdvanced'
key header.PurchaseRequisition,
@ObjectModel.readOnly: true
header.PurchaseRequisitionItem,
@Consumption.valueHelpDefinition: [{entity:{name:'/BSNAGT/P_USR21' , element: 'bname'}}]
@ObjectModel.readOnly: false
eban.buyer as Buyer,
@ObjectModel.readOnly: false
eban.comments as Comments,
@ObjectModel.readOnly: true
header.PurchaseRequisitionType,
@Consumption.filter.hidden:true
@ObjectModel.readOnly: true
@ObjectModel.virtualElement : true
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_PURCHASEREQN_PROF_TRA_EXT'
// cast('' as batxt) as PurchasingDocumentTypeName,
cast('' as abap.char( 20 )) as PurchasingDocumentTypeName,
@ObjectModel.readOnly: true
@Consumption.semanticObject: 'Supplier'
header.Supplier,
@ObjectModel.virtualElement : true
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_PURCHASEREQN_PROF_TRA_EXT'
@ObjectModel.readOnly: true
@EndUserText.label: 'Number of Items'
cast(0 as abap.int8 ) as NumberOfItems,
header.PurchasingDocumentSubtype,
@EndUserText.label: 'Total Value'
@Semantics.amount: {currencyCode: 'Currency'}
@ObjectModel.readOnly: true
@ObjectModel.virtualElement : true
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_PURCHASEREQN_PROF_TRA_EXT'
cast ( ('00') as abap.curr(15,2) ) as TotalNetAmount,
@EndUserText.label: 'Currency'
@ObjectModel.readOnly: true
@ObjectModel.virtualElement : true
@ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_PURCHASEREQN_PROF_TRA_EXT'
cast ( ('') as abap.cuky( 5 ) ) as Currency,
@ObjectModel.readOnly: true
header.Material,
@ObjectModel.readOnly: true
header.PurchaseRequisitionItemText,
//@Semantics.businessDate.at:true
//header.CreationDate, //this is BADAT field originally
@ObjectModel.readOnly: true
eban.creationdate as CreationDate,
@ObjectModel.readOnly: true
header.Plant,
@ObjectModel.readOnly: true
header.PurReqnReleaseStatus,
@ObjectModel.readOnly: true
header.PurchasingGroup,
@ObjectModel.readOnly: true
_PurchasingGroup.PurchasingGroupName as PurchasingGroupName,
@ObjectModel.readOnly: true
header.ProcessingStatus,
@ObjectModel.readOnly: true
header.RequisitionerName,
//pa0001.ename as RequisitionerNameFull
@ObjectModel.readOnly: true
header.CreatedByUser,
@ObjectModel.readOnly: true
pa.ename as CreatedByFullName
}
where
header.PurchaseRequisitionItem = '00010'
and header.ProcessingStatus = 'N'
and header.PurReqnReleaseStatus = '05'
and header.PurchaseRequisitionType <> 'NB'
2.class for virtual elemets ZCL_PURCHASEREQN_PROF_TRA_EXT
class ZCL_PURCHASEREQN_PROF_TRA_EXT definition
public
final
create public .
public section.
interfaces IF_SADL_EXIT .
interfaces IF_SADL_EXIT_CALC_ELEMENT_READ .
protected section.
private section.
data MO_PURCHASEREQN_API type ref to CL_PURCHASEREQN_PROF_BOPF_API .
ENDCLASS.
CLASS ZCL_PURCHASEREQN_PROF_TRA_EXT IMPLEMENTATION.
METHOD IF_SADL_EXIT_CALC_ELEMENT_READ~CALCULATE.
DATA lt_calculated_purchasereqn TYPE tt_cpurreqn.
DATA lt_calculated_purchasereqn2 TYPE table of ZCDS_PR_Buyer_Assign.
DATA(lo_purchasereqn_api) = cl_purchasereqn_prof_bopf_api=>get_instance( ).
"proceed only if atleast one row of data was read
IF it_original_data IS NOT INITIAL.
"only if atleast one of the transient fields are requested
IF line_exists( it_requested_calc_elements[ table_line = 'PURREQNHEADERDESCRIPTION' ] )
OR line_exists( it_requested_calc_elements[ table_line = 'TOTALNETAMOUNT' ] )
OR line_exists( it_requested_calc_elements[ table_line = 'CURRENCY' ] )
"Added in 1908 Dev code as a part of refactoring
OR line_exists( it_requested_calc_elements[ table_line = 'NUMBEROFITEMS' ] )
OR line_exists( it_requested_calc_elements[ table_line = 'PURCHASINGDOCUMENTTYPENAME' ] )
.
***************performance improvement code*************************
CALL METHOD lo_purchasereqn_api->calc_header_transient_fields
EXPORTING
it_original_data = it_original_data
IMPORTING
et_purchasereqn_header = lt_calculated_purchasereqn.
***************performance improvement code*************************
MOVE-CORRESPONDING lt_calculated_purchasereqn TO lt_calculated_purchasereqn2.
MOVE-CORRESPONDING lt_calculated_purchasereqn2 TO ct_calculated_data.
ENDIF.
ENDIF.
ENDMETHOD.
METHOD IF_SADL_EXIT_CALC_ELEMENT_READ~GET_CALCULATION_INFO.
ENDMETHOD.
ENDCLASS.
As you notice it is also copy from the standard one for virtual elements.
3.Create Metadata Extension:
Use the annotation in main CDS @Metadata.allowExtensions: true to allow extensions.
This extension manages the object page in fiori element app.
@Metadata.layer: #PARTNER
@Search.searchable: true
annotate view ZCDS_PR_Buyer_Assign with
{
@Search: {defaultSearchElement: true, ranking: #MEDIUM, fuzzinessThreshold: 0.8}
: {
lineItem: [ { position: 10, importance: #HIGH } ],
selectionField: [ { position: 10 } ],
identification:[ { position: 10 } ]
}
PurchaseRequisition;
: {
lineItem: [ { position: 20, importance: #HIGH } ],
selectionField: [ { position: 20 } ],
identification:[ { position: 20 } ]
}
Buyer;
: {
lineItem: [ { position: 30, importance: #HIGH } ],
// selectionField: [ { position: 30 } ],
identification:[ { position: 30 } ]
//multiLineText: true
}
Comments;
}
4.Behavior Definition (Unmanaged Save):
managed implementation in class zbp_cds_pr_buyer_assign unique;
define behavior for ZCDS_PR_Buyer_Assign
lock master
authorization master ( instance )
with unmanaged save
{
update ( features : instance, precheck );
delete ( features : instance, precheck );
field ( mandatory : create, readonly : update ) PurchaseRequisition;
field ( mandatory : create ) buyer;
field (readonly) PurchaseRequisitionItem;
field (readonly) PurchaseRequisitionType;
field (readonly) PurchasingDocumentTypeName;
field (readonly) NumberOfItems;
field (readonly) PurchasingDocumentSubtype;
field (readonly) Currency;
field (readonly) TotalNetAmount;
field (readonly) Material;
field (readonly) PurchaseRequisitionItemText;
field (readonly) Plant;
field (readonly) PurReqnReleaseStatus;
field (readonly) PurchasingGroup;
field (readonly) PurchasingGroupName;
field (readonly) RequisitionerName;
field (readonly) CreatedByUser;
field (readonly) CreatedByFullName;
validation validateBuyer on save { field Buyer; create;update; }
}
5.Implement Behavior Class:
CLASS zbp_cds_pr_buyer_assign DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zcds_pr_buyer_assign.
ENDCLASS.
CLASS zbp_cds_pr_buyer_assign IMPLEMENTATION.
ENDCLASS.
CLASS lhc_ZCDS_PR_Buyer_Assign DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS validateBuyer FOR VALIDATE ON SAVE
IMPORTING keys FOR ZCDS_PR_Buyer_Assign~validateBuyer.
METHODS get_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR ZCDS_PR_Buyer_Assign RESULT result.
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR ZCDS_PR_Buyer_Assign RESULT result.
METHODS is_update_granted
RETURNING VALUE(update_granted) TYPE abap_bool.
ENDCLASS.
CLASS lhc_ZCDS_PR_Buyer_Assign IMPLEMENTATION.
METHOD validateBuyer.
" Read relevant data
READ ENTITIES OF zcds_pr_buyer_assign IN LOCAL MODE
ENTITY ZCDS_PR_Buyer_Assign
FIELDS ( Buyer ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_buyer_assign)
FAILED DATA(lt_failed).
failed = CORRESPONDING #( DEEP lt_failed ).
DATA lt_buyer TYPE SORTED TABLE OF demo_sales_bupa
WITH UNIQUE KEY id.
lt_buyer = CORRESPONDING #( lt_buyer_assign
MAPPING id = Buyer EXCEPT * ).
DATA ls_buyer_assign LIKE LINE OF lt_buyer_assign.
DATA ls_buyer LIKE LINE OF lt_buyer.
DATA lo_message TYPE REF TO if_abap_behv_message.
READ TABLE lt_buyer_assign INTO ls_buyer_assign INDEX 1.
READ TABLE lt_buyer INTO ls_buyer INDEX 1.
data(has_error) = abap_false.
data message_number type numchar3.
IF ls_buyer-id IS INITIAL.
has_error = abap_true.
message_number = 002.
ELSE.
select single BNAME from usr21 into (lv_BNAME) where BNAME = _buyer-id.
if sy-subrc <> 0.
has_error = abap_true.
message_number = 003.
endif.
ENDIF.
if has_error = abap_true.
" If so we are loading a message from the global message class ZCONNECTION_MESSAGES.
lo_message = me->new_message(
id = 'ZFIORI'
number = message_number "002
severity = ms-error
).
" Appending the message to the RAP runtime to show it to the user.
APPEND VALUE #(
%tky = ls_buyer_assign-%tky
%msg = lo_message
) TO reported-zcds_pr_buyer_assign.
" Abort the save by adding an entry to the failed component.
APPEND VALUE #(
%tky = ls_buyer_assign-%tky
) TO failed-zcds_pr_buyer_assign.
endif.
ENDMETHOD.
METHOD get_authorizations.
DATA update_grtanted TYPE abap_bool.
"update_grtanted = abap_false.
DATA lo_message TYPE REF TO if_abap_behv_message.
READ ENTITIES OF zcds_pr_buyer_assign IN LOCAL MODE
ENTITY ZCDS_PR_Buyer_Assign
FIELDS ( Buyer ) WITH CORRESPONDING #( keys )
RESULT DATA(ZCDS_PR_Buyer_Assign_Edit)
FAILED failed.
CHECK ZCDS_PR_Buyer_Assign_Edit is not initial.
data(update_requested) = COND #( WHEN requested_authorizations-%update = if_abap_behv=>mk-on
THEN abap_true ELSE abap_false ).
data(delete_requested) = COND #( WHEN requested_authorizations-%delete = if_abap_behv=>mk-on
THEN abap_true ELSE abap_false ).
loop at ZCDS_PR_Buyer_Assign_Edit ASSIGNING FIELD-SYMBOL(<lfs_Buyer_Assign>).
if update_requested = abap_true or delete_requested = abap_true.
update_grtanted = is_update_granted( ).
if update_grtanted = abap_false.
lo_message = me->new_message(
id = 'ZFIORI'
number = 004
severity = ms-error
).
APPEND VALUE #( %tky = <lfs_Buyer_Assign>-%tky ) to failed-ZCDS_PR_Buyer_Assign.
APPEND VALUE #( %tky = keys[ 1 ]-%tky
%msg = lo_message
) to reported-ZCDS_PR_Buyer_Assign.
ENDIF.
endif.
endloop.
ENDMETHOD.
METHOD get_instance_features.
READ ENTITIES OF zcds_pr_buyer_assign IN LOCAL MODE
ENTITY ZCDS_PR_Buyer_Assign
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(entities).
data(lv_update_delete) = COND #( WHEN is_update_granted( ) IS INITIAL
THEN if_abap_behv=>fc-o-disabled
ELSE if_abap_behv=>fc-o-enabled ).
result = VALUE #( FOR entity IN entities
( %tky = entity-%tky
%update = lv_update_delete
%delete = lv_update_delete
) ).
ENDMETHOD.
METHOD is_update_granted.
"For instance auth
AUTHORITY-CHECK OBJECT 'ZMM_BUYER'
ID 'ACTVT' FIELD '02'.
update_granted = COND #( WHEN sy-subrc = 0 THEN abap_true ELSE abap_false ).
ENDMETHOD.
ENDCLASS.
CLASS lsc_ZCDS_PR_Buyer_Assign DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS save_modified REDEFINITION .
ENDCLASS.
CLASS lsc_ZCDS_PR_Buyer_Assign IMPLEMENTATION.
METHOD save_modified.
DATA ls_PR_BUYER_BO TYPE zmm_PR_BUYER_BO.
DATA lt_PR_BUYER_BO TYPE TABLE OF zmm_PR_BUYER_BO.
DATA(trigger_wf) = abap_true.
IF create IS NOT INITIAL.
"Populate the values
lt_PR_BUYER_BO = CORRESPONDING #( create-zcds_pr_buyer_assign ).
READ TABLE lt_PR_BUYER_BO INTO ls_PR_BUYER_BO INDEX 1.
GET TIME STAMP FIELD ls_PR_BUYER_BO-crea_date_time.
ls_PR_BUYER_BO-crea_uname = sy-uname.
GET TIME STAMP FIELD ls_PR_BUYER_BO-lchg_date_time.
ls_PR_BUYER_BO-lchg_uname = sy-uname.
MODIFY zmm_pr_buyer_bo FROM ls_PR_BUYER_BO.
UPDATE eban
SET buyer = ls_PR_BUYER_BO-buyer
comments = ls_PR_BUYER_BO-comments
WHERE banfn = ls_PR_BUYER_BO-purchaserequisition AND
bnfpo = '00010'.
ELSEIF update IS NOT INITIAL.
lt_PR_BUYER_BO = CORRESPONDING #( update-zcds_pr_buyer_assign ).
READ TABLE lt_PR_BUYER_BO INTO ls_PR_BUYER_BO INDEX 1.
GET TIME STAMP FIELD ls_PR_BUYER_BO-lchg_date_time.
ls_PR_BUYER_BO-lchg_uname = sy-uname.
MODIFY zmm_pr_buyer_bo FROM ls_PR_BUYER_BO.
IF ls_PR_BUYER_BO-buyer IS NOT INITIAL.
UPDATE eban
SET buyer = ls_PR_BUYER_BO-buyer
comments = ls_PR_BUYER_BO-comments
WHERE banfn = ls_PR_BUYER_BO-purchaserequisition AND
bnfpo = '00010'.
ELSE.
UPDATE eban
SET comments = ls_PR_BUYER_BO-comments
WHERE banfn = ls_PR_BUYER_BO-purchaserequisition AND
bnfpo = '00010'.
ENDIF.
ELSEIF delete IS NOT INITIAL.
trigger_wf = abap_false.
lt_PR_BUYER_BO = CORRESPONDING #( delete-zcds_pr_buyer_assign ).
READ TABLE lt_PR_BUYER_BO INTO ls_PR_BUYER_BO INDEX 1.
GET TIME STAMP FIELD ls_PR_BUYER_BO-lchg_date_time.
ls_PR_BUYER_BO-lchg_uname = sy-uname.
MODIFY zmm_pr_buyer_bo FROM ls_PR_BUYER_BO.
UPDATE eban
SET buyer = ''
comments = ''
WHERE banfn = ls_PR_BUYER_BO-purchaserequisition AND
bnfpo = '00010'.
ENDIF.
IF trigger_wf = abap_true.
IF ls_PR_BUYER_BO IS INITIAL.
ENDIF.
CALL FUNCTION 'ZMM_WF_PR_ASSIGN_NOT' IN BACKGROUND TASK
EXPORTING
i_pr_buyer = ls_PR_BUYER_BO.
ENDIF.
ENDMETHOD.
ENDCLASS.
6.Create FM zmm_wf_pr_assign_not
FUNCTION zmm_wf_pr_assign_not
IMPORTING
VALUE(i_pr_buyer) TYPE zmm_pr_buyer_bo.
* Data Declaration for Class
DATA lr_wf_pgr TYPE REF TO zmm_wf_pr_assign_notification.
DATA ls_pr_buyer TYPE zmm_pr_buyer_bo.
CREATE OBJECT lr_wf_pgr.
MOVE-CORRESPONDING i_pr_buyer TO ls_pr_buyer.
* Trigger Workflow
CONCATENATE 'US' ls_pr_buyer-buyer INTO ls_pr_buyer-buyer.
lr_wf_pgr->register_buyer( EXPORTING i_pr_buyer = ls_pr_buyer ).
ENDFUNCTION.
Table zmm_pr_buyer_bo:
3. Create Workflow: (Class based workflow)
1. Workflow template
2. Workflow Class
class ZMM_WF_PR_ASSIGN_NOTIFICATION definition
public
final
create public .
public section.
interfaces BI_OBJECT .
interfaces BI_PERSISTENT .
interfaces IF_WORKFLOW .
events REGISTER
exporting
value(I_PR_BUYER) type ZMM_PR_BUYER_BO .
methods REGISTER_BUYER
importing
!I_PR_BUYER type ZMM_PR_BUYER_BO .
methods NOTIFICATION
importing
!I_PR_BUYER type ZMM_PR_BUYER_BO .
protected section.
private section.
ENDCLASS.
CLASS ZMM_WF_PR_ASSIGN_NOTIFICATION IMPLEMENTATION.
method NOTIFICATION.
endmethod.
METHOD REGISTER_BUYER.
* Data Declarations
DATA: lv_objtype TYPE sibftypeid,
lv_event TYPE sibfevent,
lv_objkey TYPE sibfinstid,
lr_event_parameters TYPE REF TO if_swf_ifs_parameter_container.
* lv_param_name TYPE swfdname,
** lv_id TYPE char10.
* lv_id TYPE zmm_pgr_not_log.
* Setting values of Event Name
lv_objtype = 'ZMM_WF_PR_ASSIGN_NOTIFICATION'. " Your Class Name
lv_event = 'REGISTER'. " Event Name.
* Instantiate an empty event container
CALL METHOD cl_swf_evt_event=>get_event_container
EXPORTING
im_objcateg = cl_swf_evt_event=>mc_objcateg_cl
im_objtype = lv_objtype
im_event = lv_event
RECEIVING
re_reference = lr_event_parameters.
** Set up the name/value pair to be added to the container
* lv_param_name = 'I_PGR_LOG'. " parameter name of the event
* lv_id = i_pgr_log.
* Add the name/value pair to the event conainer
TRY.
CALL METHOD lr_event_parameters->set
EXPORTING
name = 'I_PR_BUYER'
value = I_PR_BUYER.
CATCH cx_swf_cnt_cont_access_denied .
CATCH cx_swf_cnt_elem_access_denied .
CATCH cx_swf_cnt_elem_not_found .
CATCH cx_swf_cnt_elem_type_conflict .
CATCH cx_swf_cnt_unit_type_conflict .
CATCH cx_swf_cnt_elem_def_invalid .
CATCH cx_swf_cnt_container .
ENDTRY.
* Raise the event passing the prepared event container
TRY.
CALL METHOD cl_swf_evt_event=>raise
EXPORTING
im_objcateg = cl_swf_evt_event=>mc_objcateg_cl
im_objtype = lv_objtype
im_event = lv_event
im_objkey = lv_objkey
im_event_container = lr_event_parameters.
CATCH cx_swf_evt_invalid_objtype .
CATCH cx_swf_evt_invalid_event .
ENDTRY.
COMMIT WORK.
ENDMETHOD.
ENDCLASS.
Action the Complete button of this specific task in
Create Enhancement implementation for badi /IWWRK/ES_WF_WI_BEFORE_UPD_IB
make sure to map filter values correctly as below
class ZCL_MM_WF_PGR_NOT definition
public
final
create public .
public section.
interfaces /IWWRK/IF_WF_WI_BEFORE_UPD_IB .
interfaces IF_BADI_INTERFACE .
protected section.
private section.
ENDCLASS.
CLASS ZCL_MM_WF_PGR_NOT IMPLEMENTATION.
method /IWWRK/IF_WF_WI_BEFORE_UPD_IB~BEFORE_UPDATE.
* Local Data Declaration
DATA: lv_subrc TYPE sy-subrc,
lv_status TYPE sww_wistat.
CLEAR: lv_subrc,
lv_status.
IF iv_decision_key EQ '0001'.
* Status: Ready to Committed Status
CALL FUNCTION 'SAP_WAPI_WORKITEM_COMPLETE'
EXPORTING
workitem_id = is_wi_details-wi_id
IMPORTING
return_code = lv_subrc
new_status = lv_status.
IF lv_subrc EQ 0
AND lv_status NE 'COMPLETED'.
CLEAR: lv_status.
* Status: Committed to Completed Status
CALL FUNCTION 'SAP_WAPI_WORKITEM_COMPLETE'
EXPORTING
workitem_id = is_wi_details-wi_id
IMPORTING
return_code = lv_subrc
new_status = lv_status.
ENDIF.
ENDIF.
endmethod.
ENDCLASS.
4.Publish app to Fiori Launchpad
I went with the minimum option (without SAP Business Application Studio) as follows:
published the cds view in SEGW project and created a project from template (List Report) in webide then deploy it to server under name zmm_pr_assign
Target mapping
I'm sure you will manage to create tile, catalog, group, and pfcg role. 🙂
5.Output:
Once saved here you find wf item in my inbox with binded details of PR.. with the complete button visible
I've included all the important details in sequence, but there may still be some missing information.
Please feel free to ask about any additional details you'd like me to include.
Regards,
Abdelrahman Zaki
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
11 | |
10 | |
9 | |
8 | |
6 | |
6 | |
5 | |
5 | |
5 | |
5 |