Summary
We have the assignment block for scheduled actions in SAP CRM where the end users could ahead and execute certain actions like generating the adobe forms/smart forms, Sending an email, Starting workflow and other mundane activities. This document is actually simulating the similar service in the form of RFC enabled function module(engulfed as/in ODATA service) which would be consumed in SAPUI5/FIORI app thus allowing to replicate the provision of action profile execution in SAP CRM.
Author(s):
Rajwin Singh Sood
Company: Mindtree
Created on: 5th July 2016

Rajwin Singh Sood is currently working as SAP CRM Technical Manager at Mindtree. He has got experience of about 10 years in SAP ABAP and SAP CRM web UI. He is
also a SAP CRM EHP2 Certified associated consultant. Prior to working with Mindtree he had worked with Atos,SAP India(SAP
Global Delivery), Capgemini , Accenture and Infosys. He worked in SAP CRM Web Ui in areas like BSP
enhancements, transaction launchers, BOL Programming, BRFPlus.
Scenario
So as specified in the summary we have the requirement wherein the end user wants to execute actions in UI5/FIORI application as its working in SAP CRM. In order to achieve this we need to :-
- Develop RFC enabled function module to first enlist the number of active actions for the particular transaction
- Develop RFC enabled function module to execute on the basis of transaction GUID and Action type(which will input coming from the above function module)
- Develop ODATA service in Netweaver gateway server using transaction SEGW transaction and call the above RFC enabled function modules.
Note:- ODATA development is not in scope of this document as RFC function modules were critical. you can refer to SCN in case you need some guide on ODATA.
Step1 RFC Enlisting the number of active actions for the particular transaction:-
Before going through the code its important to understand that as far triggering of actions are concerned there are two important SAP tables namely ppfttrigg(PPF: Actions) and crmd_action_asyn(Asynchronous Actions Monitoring). Table
ppfttrigg contains the list of actions which are suppose to be triggered/ needs to be triggered whereas crmd_action_asyn will highlight what was the end result of the execution. If you would refer to the GENIL class CL_CRM_ADMIN_ACIIL(for BOL object ACI for actions) method IF_GENIL_APPL_INTLAY~GET_DYNAMIC_QUERY_RESULT there you could a SELECT join on both these tables. This is just for your reference, Now we'll develop a Z FM which will have importing parameter as:-
where object id is nothing but the transaction id
and the exporting parameter as
its a custom table type containing the following parameters:-

now the FM logic/code with self explanatory comments is enumerated below:-
CONSTANTS : lc_dom_nm_status
TYPE domname
VALUE 'PPFDTSTAT',
lc_dom_nm_medium
TYPE domname
VALUE 'PPFDMETYPE',
lc_application
TYPE ppfdappl
VALUE 'CRM_ORDER'.
****Type declaration
TYPES :
BEGIN OF lty_action_definition,
ttype
TYPE ppfdtt,
ttypedescr
TYPE ppfdttt,
END OF lty_action_definition.
***Data declaration
DATA : lt_ppfttrigg
TYPE STANDARD TABLE OF ppfttrigg,
lt_action_definition
TYPE TABLE OF lty_action_definition,
lv_date_create
TYPE ppfdcdate,
lv_time_create
TYPE ppfdctime,
lv_time
TYPE uzeit,
lt_statusdd_value
TYPE TABLE OF dd07v,
ls_status_value
LIKE LINE OF lt_statusdd_value,
lt_statusdd_value1
TYPE TABLE OF dd07v,
lt_procmed_value
TYPE TABLE OF dd07v,
ls_procmed_value
LIKE LINE OF lt_procmed_value,
lt_procmed_value1
TYPE TABLE OF dd07v,
ls_action_definition
TYPE lty_action_definition,
ls_action_item
TYPE crmt_action_attr_aciil,
ls_ppfttrigg
TYPE ppfttrigg.
***fetch all the texts maintained for status and medium types
CALL FUNCTION 'DD_DOMA_GET'
EXPORTING
domain_name = lc_dom_nm_status
* get_state = 'M '
langu = sy-langu
prid =
0
withtext =
'X'
TABLES
dd07v_tab_a = lt_statusdd_value
dd07v_tab_n = lt_statusdd_value1
EXCEPTIONS
illegal_value =
1
op_failure =
2
OTHERS =
3.
CALL FUNCTION 'DD_DOMA_GET'
EXPORTING
domain_name = lc_dom_nm_medium
* get_state = 'M '
langu = sy-langu
prid =
0
withtext =
'X'
TABLES
dd07v_tab_a = lt_procmed_value
dd07v_tab_n = lt_procmed_value1
EXCEPTIONS
illegal_value =
1
op_failure =
2
OTHERS =
3.
****first fetch all the scheduled actions
SELECT *
FROM ppfttrigg
INTO TABLE lt_ppfttrigg
WHERE applkey = iv_object_id
AND
applctn = lc_application.
"#EC CI_NOFIRST
IF sy-subrc
IS INITIAL.
***fetch the action texts
SELECT name
text FROM ppftttcut
INTO TABLE lt_action_definition
FOR ALL ENTRIES
IN lt_ppfttrigg
WHERE name = lt_ppfttrigg-ttype
AND langu = sy-langu.
IF sy-subrc
IS INITIAL.
ENDIF.
LOOP AT lt_ppfttrigg
INTO ls_ppfttrigg.
ls_action_item-guid = ls_ppfttrigg-appl_oid.
***populate the action profile and description
READ TABLE lt_action_definition
INTO ls_action_definition
WITH KEY ttype = ls_ppfttrigg-ttype.
IF sy-subrc
IS INITIAL.
ls_action_item-ttype = ls_action_definition-ttype.
ls_action_item-ttypedescr = ls_action_definition-ttypedescr.
ENDIF.
ls_action_item-context = ls_ppfttrigg-context.
***populate status and description
READ TABLE lt_statusdd_value
INTO ls_status_value
WITH KEY domvalue_l = ls_ppfttrigg-status.
IF sy-subrc
IS INITIAL.
ls_action_item-status = ls_status_value-domvalue_l.
ls_action_item-statusdesc = ls_status_value-ddtext.
ENDIF.
***populate the medium and their description
READ TABLE lt_procmed_value
INTO ls_procmed_value
WITH KEY domvalue_l = ls_ppfttrigg-metype.
IF sy-subrc
IS INITIAL.
ls_action_item-mediumtype = ls_procmed_value-domvalue_l.
ls_action_item-mediumdesc = ls_procmed_value-ddtext.
ENDIF.
ls_action_item-is_inactiv = ls_ppfttrigg-is_inactiv.
ls_action_item-execdialog = ls_ppfttrigg-execdialog.
ls_action_item-usercreate = ls_ppfttrigg-usercreate.
*****creation date
CONVERT TIME STAMP ls_ppfttrigg-timecreate
TIME ZONE sy-zonlo
INTO DATE ls_action_item-datecreate
TIME sy-uzeit.
*****creation time
CONVERT TIME STAMP ls_ppfttrigg-timecreate
TIME ZONE sy-zonlo
INTO TIME ls_action_item-timecreate.
APPEND ls_action_item
TO et_action_item.
ENDLOOP.
ENDIF.
the above function module will get the complete list of active triggers.
- Step 2 :- Develop RFC enabled function module to execute on the basis of transaction GUID and Action type(which will input coming from the above function module)
Now we come to the RFC function module which will execute the actions on the basis of the list which will be outcome of above function module.
importing paramters are:-
If you note carefully both these parameters are actually the outcome of the first function module which in turn will act as input to this FM.
the exporting/outcome will the result of the execution:-
Finally the self explanatory code is given below:-
***constant declaration
CONSTANTS: lc_message1
TYPE string
VALUE 'Not processed',
lc_message2
TYPE string
VALUE 'Successfully processed',
lc_message3
TYPE string
VALUE 'Incorrectly processed'.
****Include
INCLUDE crm_direct.
***Data declaration
DATA lv_guid_ref
TYPE crmt_object_guid.
DATA lr_context
TYPE REF TO cl_doc_context_crm_order.
DATA lv_toolbar
TYPE boolean.
DATA lr_manager
TYPE REF TO cl_manager_ppf.
DATA lt_context
TYPE ppftctxtir.
DATA lt_trigger
TYPE ppfttrgor.
DATA ls_trigger
TYPE ppfdtrgor.
DATA lt_action
TYPE crmt_action_get_tab.
DATA ls_action
TYPE crmt_action_get.
DATA lr_object
TYPE REF TO object.
DATA lr_action
TYPE REF TO cl_trigger_ppf.
DATA lv_status
TYPE i.
DATA lt_objects_to_save
TYPE crmt_object_guid_tab.
DATA ls_objects_to_save
TYPE crmt_object_guid.
DATA lv_protocol
TYPE balloghndl.
DATA lt_guids
TYPE crmt_object_guid_tab.
DATA: ls_statistics
TYPE bal_s_scnt,
lv_contains_errors
TYPE crmt_boolean.
* 1. context create
CALL FUNCTION 'CRM_ACTION_CONTEXT_CREATE'
EXPORTING
iv_header_guid = iv_header_guid
iv_object_guid = iv_header_guid
IMPORTING
ev_context = lr_context
EXCEPTIONS
no_actionprofile_for_proc_type =
1
no_actionprofile_for_item_type =
2
order_read_failed =
3
OTHERS =
4.
IF sy-subrc
IS NOT INITIAL.
"do nothing
ENDIF.
* 2. action deterimne
IF lr_context
IS BOUND.
CALL FUNCTION 'CRM_ACTION_DETERMINE'
EXPORTING
iv_header_guid = iv_header_guid
iv_object_guid = iv_header_guid
iv_context = lr_context
iv_for_toolbar_only = lv_toolbar
iv_no_detlog = true.
INSERT lr_context
INTO TABLE lt_context.
ENDIF.
* 3. get actions from ppf manager
lr_manager = cl_manager_ppf=>get_instance( ).
IF lr_manager
IS BOUND.
CALL METHOD lr_manager->get_active_triggers
EXPORTING
it_contexts = lt_context
IMPORTING
et_triggers = lt_trigger.
ENDIF.
* 4. fill exporting parameters
LOOP AT lt_trigger
INTO ls_trigger.
ls_action-guid = ls_trigger->read_guid( ).
ls_action-def = ls_trigger->get_ttype( ).
ls_action-text = cl_view_service_ppf=>get_descrp_for_dropdown(
io_trigger = ls_trigger ).
INSERT ls_action
INTO TABLE lt_action.
ENDLOOP.
* 5 get actions from object services
CLEAR ls_action.
READ TABLE lt_action
INTO ls_action
WITH KEY def = iv_action_name.
IF sy-subrc
IS INITIAL.
CALL METHOD ca_trigger_ppf=>agent->if_os_ca_persistency~get_persistent_by_oid
EXPORTING
i_oid = ls_action-guid
RECEIVING
result = lr_object.
lr_action ?= lr_object.
ENDIF.
* 6 execute action
IF lr_action
IS BOUND.
"CALL METHOD lr_action->set_is_inactiv( space ).
CALL METHOD lr_action->set_processed_manually
EXPORTING
i_processed_manually = true.
CALL METHOD lr_action->execute
RECEIVING
rp_rc = lv_status
EXCEPTIONS
empty_medium_reference =
1
empty_appl_reference =
2
locked =
3
document_is_locked =
4
inactive =
5
startcondition_not_true =
6
OTHERS =
7.
ENDIF.
****now check for response type
* 0 Not processed
* 1 Successfully processed
* 2 Incorrectly processed
CASE lv_status.
WHEN 0.
MOVE lc_message1
TO iv_exec_result.
WHEN 1.
MOVE lc_message2
TO iv_exec_result.
WHEN 2.
MOVE lc_message3
TO iv_exec_result.
WHEN OTHERS.
ENDCASE.
*****saving the action excution result in the table otherwise the executed action won't be saved
LOOP AT lt_trigger
INTO ls_trigger.
ls_action-guid = ls_trigger->read_guid( ).
ls_action-def = ls_trigger->get_ttype( ).
ls_action-text = cl_view_service_ppf=>get_descrp_for_dropdown(
io_trigger = ls_trigger ).
IF ls_action-def
EQ iv_action_name.
IF ls_trigger->get_status( )
NE 1 OR ls_trigger->get_metype( )
NE 'MET'.
* Mark action as finished
UPDATE crmd_action_asyn
SET finished = abap_true
WHERE os_guid = ls_action-guid.
COMMIT WORK.
EXIT.
ENDIF.
********************************************************************
* get protocol
lv_protocol = ls_trigger->getm_processing_log( ).
INSERT iv_header_guid
INTO TABLE lt_guids.
* save guids and trigger new determination if needed
CALL FUNCTION 'CRM_ORDER_SAVE'
EXPORTING
it_objects_to_save = lt_guids
EXCEPTIONS
document_not_saved =
1
OTHERS =
2.
********************************************************************
* write message into ppf-log
IF sy-subrc
NE 0.
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass =
'2'
ip_handle = lv_protocol.
* set return status
CALL METHOD ls_trigger->set_status
EXPORTING
i_status =
'2'.
ENDIF.
IF ls_statistics-msg_cnt_e >
0.
lv_contains_errors = abap_true.
ENDIF.
* Mark action as finished
UPDATE crmd_action_asyn
SET finished = abap_true contains_errors = lv_contains_errors
WHERE os_guid = ls_action-guid.
COMMIT WORK.
EXIT.
ENDIF.
ENDLOOP.
This FM would not only execute the action but will also update the outcome with respect to the one order transaction.
Hope so this document will prove helpful for anyone who has the requirement of incorporating the action execution remotely.