Pieter Rijlaarsdam
Read all my blogsAs mentioned in one of the previous posts, you can customize actions to be triggered in transactions, based on the context of the transaction. For instance starting a workflow, or triggering a letter to a customer when the status of the transaction changes or when a certain date is reached.
Standard SAP offers some very usefull options, such as:
• Starting campaign automation
• COPY_DOCUMENT: Creating a followup document (for instance a planned phonecall after a visit, or when a contract is about to expire)
• Creating a printout using a smartform
• Creating a reminder mail
• Creating a confirmation mail to the customer
Beside these standard possibilities, you might be interested in creating your own action logic which you want to assign to the business transaction.
Some examples of custom created actions are:
• Change Status: Changing the status of the current document (Nice if you want to auto close a document, or if you want to automatically change a status based on a date)
• Current Date: Enter the current date in a date type (Nice if you want to enter the date of for instance a status change)
• Copy Document and Change Status: A copy of the copy_document & changing the status (The copy_document creates a follow_up document). If you want the current document to get the status “followup created” for instance, you can use this method. This enables you to have different follow-up actions based on the context and still be sure there will be only exactly one followup (so for instance either an email to the customer OR a letter to the customer)
• Write file: This enable you to feed a file with data for for instance an interface or an extract. Particularly usefull for for instance lead interfaces and automated marketing campaigns.
How is this done?
As an example, I will show you how to create the change status action and add it to an action profile.
The coding in the example enables you to both use the action on header as well as on item level.
Create the action definition as defined here.
When defining the action, choose “Method Call”.
In the popup, again do not choose an existing class, but create a new one (like ZSET_STATUS).
Now create the class. Note that the class will be created in definition EXEC_METHODCALL_PPF, and that it has an interface to IF_EX_EXEC_METHODCALL_PPF.
Implement the method EXECUTE.
Note that there are a few parameters you can use in the method:
IP_PREVIEW is occupied with an X in case the user pressed the Preview button.
The II_CONTAINTER contains the name-value pairs that have been added in the action customizing.
The RP_STATUS returns a code, which can be either of the following:
0 = Not Processed
1 = Successfully Processed
2 = Incorrectly Processed.
During the coding of the class it is important that you check the IP_PREVIEW, and it is important that you correctly set the RP_STATUS to make sure actions are not reprocessed while they shouldn’t.
And never put a commit in an action, but call the method register_for_save in class cl_action_execute.
As an example for the ZSET_STATUS. Note that in the example, 2 parameters are read from the ii_container: ‘STAT_PROC’ and ‘STATUS’.
Good luck!
Method IF_EX_EXEC_METHODCALL_PPF~EXECUTE.
lv_guid_ref TYPE crmt_object_guid,
lv_kind_ref TYPE crmt_object_kind,
lt_input_fields TYPE crmt_input_field_tab,
ls_input_fields TYPE crmt_input_field,
lt_field_names TYPE CRMT_INPUT_FIELD_NAMES_TAB,
ls_field_names TYPE CRMT_INPUT_FIELD_NAMES,
lv_message(255) type c.
CALL METHOD lcl_action_execute->get_ref_object
EXPORTING
io_appl_object = io_appl_object
ip_action = ip_action
ii_container = ii_container
IMPORTING
ev_guid_ref = lv_guid_ref
ev_kind_ref = lv_kind_ref.
*———————————
* Get new status.
DATA: lv_subrc type sysubrc,
lv_status type char5,
lv_stat_proc type char8,
lv_problemclass TYPE bal_s_msg-probclass.
lv_subrc = 1.
ELSE.* Get user status proc.
CALL METHOD ii_container->get_value
EXPORTING
element_name = ‘STAT_PROC’
IMPORTING
data = lv_stat_proc
retcode = lv_subrc.
MESSAGE ID ‘CRM_SUR’ TYPE ‘E’ NUMBER ‘005’
WITH ‘STAT_PROC’
INTO lv_message.
lv_problemclass = ‘2’. “important
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass = lv_problemclass
ip_handle = ip_application_log.
rp_status = ‘2’. “Incorrectly processed
EXIT.
ENDIF.*Get user status.
CALL METHOD ii_container->get_value
EXPORTING
element_name = ‘STATUS’
IMPORTING
data = lv_status
retcode = lv_subrc.
MESSAGE ID ‘CRM_SUR’ TYPE ‘E’ NUMBER ‘005’
WITH ‘STATUS’
INTO lv_message.
lv_problemclass = ‘2’. “important
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass = lv_problemclass
ip_handle = ip_application_log.
rp_status = ‘2’. “Incorrectly processed
EXIT.
ENDIF.
LS_STATUS TYPE CRMT_STATUS_COM.
CONCATENATE lv_status lv_stat_proc into LS_INPUT_FIELDS-LOGICAL_KEY.
ls_field_names-fieldname = ‘ACTIVATE’.
APPEND LS_FIELD_NAMES TO LT_FIELD_NAMES.
LS_INPUT_FIELDS-FIELD_NAMES = LT_FIELD_NAMES.
APPEND LS_INPUT_FIELDS TO LT_INPUT_FIELDS.
EXPORTING
IT_STATUS = LT_STATUS
CHANGING
CT_INPUT_FIELDS = LT_INPUT_FIELDS
EXCEPTIONS
ERROR_OCCURRED = 1
DOCUMENT_LOCKED = 2
NO_CHANGE_ALLOWED = 3
NO_AUTHORITY = 4
OTHERS = 5
.
IF SY-SUBRC <> 0.* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ELSE.
RP_STATUS = 1.
ENDIF.DATA LV_GUID_TO_SAVE TYPE CRMT_OBJECT_GUID.IF lv_kind_ref = ‘A’.
LV_GUID_TO_SAVE = LV_GUID_REF.ELSEIF lv_kind_ref = ‘B’.
EXPORTING
IV_GUID = LV_GUID_REF
IMPORTING
EV_HEADER_GUID = LV_GUID_TO_SAVE
EXCEPTIONS
ITEM_NOT_FOUND = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.ENDIF.* Save the document
CALL METHOD lcl_action_execute->register_for_save
EXPORTING
iv_source_header_guid = LV_GUID_TO_SAVE
ip_application_log = ip_application_log
IMPORTING
rp_status = rp_status.
DATA: lcl_action_execute TYPE REF TO cl_action_execute,
lv_guid_ref TYPE crmt_object_guid,
lv_kind_ref TYPE crmt_object_kind,
lt_input_fields TYPE crmt_input_field_tab,
ls_input_fields TYPE crmt_input_field,
lt_field_names TYPE CRMT_INPUT_FIELD_NAMES_TAB,
ls_field_names TYPE CRMT_INPUT_FIELD_NAMES,
lv_message(255) type c.
INCLUDE crm_direct.
CREATE OBJECT lcl_action_execute.* get parameter from reference object
CALL METHOD lcl_action_execute->get_ref_object
EXPORTING
io_appl_object = io_appl_object
ip_action = ip_action
ii_container = ii_container
IMPORTING
ev_guid_ref = lv_guid_ref
ev_kind_ref = lv_kind_ref.
rp_status =
‘2’. “Set Action ends in error as default*———————————
* Get new status.
DATA: lv_subrc type sysubrc,
lv_status type char5,
lv_stat_proc type char8,
lv_problemclass TYPE bal_s_msg-probclass.
IF ii_container IS INITIAL.
lv_subrc = 1.
ELSE.* Get user status proc.
CALL METHOD ii_container->get_value
EXPORTING
element_name = ‘STAT_PROC’
IMPORTING
data = lv_stat_proc
retcode = lv_subrc.
IF lv_subrc <> 0.
MESSAGE ID ‘CRM_SUR’ TYPE ‘E’ NUMBER ‘005’
WITH ‘STAT_PROC’
INTO lv_message.
lv_problemclass = ‘2’. “important
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass = lv_problemclass
ip_handle = ip_application_log.
rp_status = ‘2’. “Incorrectly processed
EXIT.
ENDIF.*Get user status.
CALL METHOD ii_container->get_value
EXPORTING
element_name = ‘STATUS’
IMPORTING
data = lv_status
retcode = lv_subrc.
IF lv_subrc <> 0.
MESSAGE ID ‘CRM_SUR’ TYPE ‘E’ NUMBER ‘005’
WITH ‘STATUS’
INTO lv_message.
lv_problemclass = ‘2’. “important
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass = lv_problemclass
ip_handle = ip_application_log.
rp_status = ‘2’. “Incorrectly processed
EXIT.
ENDIF.
ENDIF.
DATA: LT_STATUS TYPE CRMT_STATUS_COMT,
LS_STATUS TYPE CRMT_STATUS_COM.
LS_STATUS-REF_GUID = lv_guid_ref.
LS_STATUS-REF_KIND = lv_kind_ref.
LS_STATUS-STATUS = lv_status.
LS_STATUS-USER_STAT_PROC = lv_stat_proc.
LS_STATUS-ACTIVATE =
LS_INPUT_FIELDS-REF_GUID = lv_guid_ref.
LS_INPUT_FIELDS-REF_KIND = lv_kind_ref.
LS_INPUT_FIELDS-OBJECTNAME =
CONCATENATE lv_status lv_stat_proc into LS_INPUT_FIELDS-LOGICAL_KEY.
ls_field_names-fieldname = ‘ACTIVATE’.
APPEND LS_FIELD_NAMES TO LT_FIELD_NAMES.
LS_INPUT_FIELDS-FIELD_NAMES = LT_FIELD_NAMES.
APPEND LS_INPUT_FIELDS TO LT_INPUT_FIELDS.
APPEND ls_status to lt_status.
CALL FUNCTION ‘CRM_ORDER_MAINTAIN’
EXPORTING
IT_STATUS = LT_STATUS
CHANGING
CT_INPUT_FIELDS = LT_INPUT_FIELDS
EXCEPTIONS
ERROR_OCCURRED = 1
DOCUMENT_LOCKED = 2
NO_CHANGE_ALLOWED = 3
NO_AUTHORITY = 4
OTHERS = 5
.
IF SY-SUBRC <> 0.* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ELSE.
RP_STATUS = 1.
ENDIF.DATA LV_GUID_TO_SAVE TYPE CRMT_OBJECT_GUID.IF lv_kind_ref = ‘A’.
LV_GUID_TO_SAVE = LV_GUID_REF.ELSEIF lv_kind_ref = ‘B’.
CALL FUNCTION ‘CRM_ORDERADM_I_READ_OW’
EXPORTING
IV_GUID = LV_GUID_REF
IMPORTING
EV_HEADER_GUID = LV_GUID_TO_SAVE
EXCEPTIONS
ITEM_NOT_FOUND = 1
OTHERS = 2
.
IF SY-SUBRC <> 0.* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.ENDIF.* Save the document
CALL METHOD lcl_action_execute->register_for_save
EXPORTING
iv_source_header_guid = LV_GUID_TO_SAVE
ip_application_log = ip_application_log
IMPORTING
rp_status = rp_status.
endmethod.
2 responses to “Creating your own Action Methods”
Guy,
Great blog. Congratulations for sharing your learnings to the globe.
Regards,
Rodolfo ( BRAZIL SAP CRM consultant )
Hi,
There is one point that is not clear for me. You put the message into a variable lv_message but it seems like it's not used then in the rest of the code. I mean it's not transfered to the application log.
Is that normal ?
Thanks for the note by the way 🙂