Trigger SAP CRM Scheduled actions(Action profiles) in SAPUI5
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.