First part of this post: Custom Workflow - Developer view - Part 1 - Idea and preparation
First start the transaction /SAPSRM/WF_PROCESS
Provide expression name ZSRM_EX_SC_START.
ZSRM - Group Name
EX - Expression
SC - Shopping cart
START - Shopping cart event
As Implementation class you should select OCF001 - Function module. A new expression will be created.
Result type should be defined as C(30), it is a type of Workflow schema. Function module interface can be coped from function module BRF_CALL_FUNCTION_TEMPLATE.
Provide event name ZSRM_EV_SC_START.
ZSRM - Group Name
EV - Event
SC - Shopping cart
START - Shopping cart event
Save Event. Then select Event->Change.
In the change mode you can add a new rule.
Here you should add a created expression.
Save the changes.
Worfklow setting are defined in the transaction /SAPSRM/WF_PROCESS.
Go to transaction /SAPSRM/WF_PROCESS and select object BUS2121, then double click on process schema evaluation.
Set the created evaluation id.
Then go to Process Schema Definition and create a new entry.
Provide following customizing.
Step 1:
Approval with completion.
Decision if the step relevant or not determined via ZSRM_EV_BOB.
Approver determined with rule ZRR_REQUESTER.
Workflow Task 99907917 deliver task description.
Step 2:
Approval with decision.
Decision if the step relevant or not determined via ZSRM_EV_CUST_APPR.
Approver determined with rule ZRR_APPROVER_C.
Workflow Task 99907918 deliver task description.
Last step is automatic and obligatory.
Save settings.
For agent determination we need to create a BADI implementation(s). In this case 2 implementations will be created.
To implement the BADI go to:
SPRO->SAP Supplier Relationship Management->SRM Server->Business Add-Ins->Business Workflow->Process-Controlled Workflow->Define Agents
and create a new BADI Implementation.
In the created Implementation double click on filter values.
and create a new combination.
Select all entries.
Set the values as shown and acivate implementation.
The most 2 important methods for this implementation are /SAPSRM/IF_EX_WF_RESP_RESOLVER~GET_AREA_TO_ITEM_MAP and /SAPSRM/IF_EX_WF_RESP_RESOLVER~GET_APPROVERS_BY_AREA_GUID.
The method GET_AREA_TO_ITEM_MAP called before GET_APPROVERS_BY_AREA_GUID and here you must already know your approvers. For the first step it is always requester for all positions.
Here is an implementation example
METHOD /sapsrm/if_ex_wf_resp_resolver~get_area_to_item_map.
DATA lv_guid TYPE /sapsrm/wf_area_guid.
DATA ls_map TYPE /sapsrm/s_bd_wf_item_to_area.
DATA ls_partner TYPE bbp_pds_partner.
DATA lt_partner TYPE bbpt_pds_partner.
DATA lo_sc TYPE REF TO /sapsrm/if_pdo_bo_sc_adv.
* get requester guid.
TRY .
lo_sc = /sapsrm/cl_pdo_factory_sc_adv=>get_buffered_instance( is_document-document_guid ).
IF lo_sc IS NOT BOUND.
lo_sc = /sapsrm/cl_pdo_factory_sc_adv=>get_instance( iv_header_guid = is_document-document_guid
iv_mode = /sapsrm/if_pdo_constants_gen_c=>gc_mode_display ).
ENDIF.
lo_sc->/sapsrm/if_pdo_do_partner~get_partners_of_type(
EXPORTING
iv_partner_fct = '00000016'
IMPORTING
et_partner = lt_partner
).
READ TABLE lt_partner INTO ls_partner INDEX 1.
lv_guid = ls_partner-partner_no.
CATCH /sapsrm/cx_pdo_wf_mode_ban. " transaction mode not allowed with respect to workflow status
CATCH /sapsrm/cx_pdo_wrong_bus_type. " Inconsistent Object Types
CATCH /sapsrm/cx_pdo_pd_read_error. " No result during PD Layer read access
CATCH /sapsrm/cx_pdo_lock_failed. " The document could not be locked
CATCH /sapsrm/cx_pdo_no_authorizatio. " No authorization for this action
CATCH /sapsrm/cx_pdo_parameter_error. " Inconsistent Parameter
CATCH /sapsrm/cx_pdo_status_error. " No change mode allowed
CATCH /sapsrm/cx_pdo_incons_user. " The user attributes are not defined in the right way
CATCH /sapsrm/cx_pdo_abort. " Fatal error caught by PDO Layer
CATCH /sapsrm/cx_pdo_error. " PDO General Exception
ENDTRY.
* get mapping table
ls_map-area_guid = /sapsrm/cl_wf_area=>/sapsrm/if_wf_area~create_instance(
iv_area_type = /sapsrm/if_wf_process_c=>gc_area_type_employee
iv_leading_object_id = lv_guid )->get_guid( ).
CLEAR ls_map-item_guid. " means for all positions
APPEND ls_map TO rt_item_to_area_map.
ENDMETHOD.
METHOD /sapsrm/if_ex_wf_resp_resolver~get_approvers_by_area_guid.
rt_approver = /sapsrm/cl_wf_area=>/sapsrm/if_wf_area~get_instance_by_guid(
iv_area_type = /sapsrm/if_wf_process_c=>gc_area_type_employee
iv_area_guid = is_area-area_guid
)->get_responsible_approvers( ).
ENDMETHOD.
Activate Class and Implementation
And here is Implementation.
METHOD /sapsrm/if_ex_wf_resp_resolver~get_area_to_item_map.
DATA lv_guid TYPE /sapsrm/wf_area_guid.
DATA ls_map TYPE /sapsrm/s_bd_wf_item_to_area.
TRY .
lv_guid = cl_bbp_es_enterprise=>get_person_by_username( 'MANAGER_01' )->get_primarykey( ).
CATCH cx_bbp_es_not_a_person. " Exception: Person Unknown
CATCH cx_bbp_es_not_found. " No data found
ENDTRY.
* get mapping table
ls_map-area_guid = /sapsrm/cl_wf_area=>/sapsrm/if_wf_area~create_instance(
iv_area_type = /sapsrm/if_wf_process_c=>gc_area_type_employee
iv_leading_object_id = lv_guid )->get_guid( ).
CLEAR ls_map-item_guid. " means for all positions
APPEND ls_map TO rt_item_to_area_map.
ENDMETHOD.
MANAGER_01 is a hard coded value of existing and integrated user.
Implementation for /SAPSRM/IF_EX_WF_RESP_RESOLVER~GET_APPROVERS_BY_AREA_GUID is the same.
Here is a source code of the function module.
FUNCTION zsrm_wf_ex_cust_appr_rel.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IT_EXPRESSIONS) TYPE SBRF260A_T
*" REFERENCE(IO_EVENT) TYPE REF TO IF_EVENT_BRF
*" REFERENCE(IO_EXPRESSION) TYPE REF TO IF_EXPRESSION_BRF
*" EXPORTING
*" REFERENCE(EV_VALUE) TYPE BRF_RESULT_VALUE
*" REFERENCE(EV_TYPE) TYPE BRF_RESULT_TYPE
*" REFERENCE(EV_LENGTH) TYPE BRF_RESULT_LENGTH
*" REFERENCE(EV_CURRENCY) TYPE BRF_CURRENCY
*" REFERENCE(EV_OUTPUT_LENGTH) TYPE BRF_RESULT_OUTPUT_LENGTH
*" REFERENCE(EV_DECIMALS) TYPE BRF_RESULT_DECIMALS
*" REFERENCE(EV_DATA_MISSING) TYPE BRF_DATA_MISSING
*"----------------------------------------------------------------------
DATA lv_msg TYPE string.
DATA lv_document_guid TYPE /sapsrm/wf_document_guid.
DATA lv_document_type TYPE /sapsrm/wf_document_type.
DATA ls_header TYPE bbp_pds_sc_header_d.
DATA lo_wf_brf_event TYPE REF TO /sapsrm/cl_wf_brf_event.
DATA lo_context_provider TYPE REF TO /sapsrm/if_wf_context_provider.
DATA lo_sc TYPE REF TO /sapsrm/if_pdo_bo_sc_adv.
ev_type = /sapsrm/if_wf_rule_c=>type_bool.
ev_length = 1.
CLEAR ev_currency.
ev_output_length = 1.
ev_decimals = 0.
ev_value = /sapsrm/if_wf_rule_c=>brf_result_bool_ok. " no processing
CLEAR ev_data_missing.
* get event object
IF NOT io_event IS BOUND.
* BRF event Object not bound. No further execution possible.
MESSAGE e089(/sapsrm/brf) INTO lv_msg.
TRY.
CALL METHOD /sapsrm/cl_wf_brf_ccms=>send_message( ).
CATCH /sapsrm/cx_wf_abort.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDTRY.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDIF.
*----------------------------------------------------------------
* get document data by context provider
*----------------------------------------------------------------
lo_wf_brf_event ?= io_event.
lo_context_provider = lo_wf_brf_event->get_context_provider( ).
* get Content Container from BRF event
IF NOT lo_context_provider IS BOUND.
* BRF Context Container Object not bound. No further execution possible.
MESSAGE e090(/sapsrm/brf) INTO lv_msg.
TRY.
CALL METHOD /sapsrm/cl_wf_brf_ccms=>send_message( ).
CATCH /sapsrm/cx_wf_abort.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDTRY.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDIF.
CALL METHOD lo_context_provider->get_document
IMPORTING
ev_document_guid = lv_document_guid
ev_document_type = lv_document_type.
CASE lv_document_type .
WHEN /sapsrm/if_pdo_obj_types_c=>gc_pdo_shop.
TRY.
lo_sc = /sapsrm/cl_pdo_factory_sc_adv=>get_buffered_instance( lv_document_guid ).
IF lo_sc IS NOT BOUND.
lo_sc = /sapsrm/cl_pdo_factory_sc_adv=>get_instance( iv_header_guid = lv_document_guid
iv_mode = /sapsrm/if_pdo_constants_gen_c=>gc_mode_display ).
ENDIF.
lo_sc->/sapsrm/if_pdo_bo_sc~get_header_detail( IMPORTING es_header = ls_header ).
IF ls_header-created_by <> 'MANAGER_01'.
ev_value = /sapsrm/if_wf_rule_c=>brf_result_bool_noprocessing. " processing
ENDIF.
CATCH /sapsrm/cx_pdo_wf_mode_ban /sapsrm/cx_pdo_wrong_bus_type
/sapsrm/cx_pdo_pd_read_error /sapsrm/cx_pdo_lock_failed
/sapsrm/cx_pdo_no_authorizatio /sapsrm/cx_pdo_parameter_error
/sapsrm/cx_pdo_status_error /sapsrm/cx_pdo_incons_user
/sapsrm/cx_pdo_abort /sapsrm/cx_pdo_error .
MESSAGE e101(/sapsrm/brf) INTO lv_msg.
TRY.
CALL METHOD /sapsrm/cl_wf_brf_ccms=>send_message( ).
CATCH /sapsrm/cx_wf_abort.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDTRY.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDTRY.
ENDCASE.
ENDFUNCTION.
Here is an exmaple content of function module.
FUNCTION zsrm_wf_schema_det.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IT_EXPRESSIONS) TYPE SBRF260A_T
*" REFERENCE(IO_EVENT) TYPE REF TO IF_EVENT_BRF
*" REFERENCE(IO_EXPRESSION) TYPE REF TO IF_EXPRESSION_BRF
*" EXPORTING
*" REFERENCE(EV_VALUE) TYPE BRF_RESULT_VALUE
*" REFERENCE(EV_TYPE) TYPE BRF_RESULT_TYPE
*" REFERENCE(EV_LENGTH) TYPE BRF_RESULT_LENGTH
*" REFERENCE(EV_CURRENCY) TYPE BRF_CURRENCY
*" REFERENCE(EV_OUTPUT_LENGTH) TYPE BRF_RESULT_OUTPUT_LENGTH
*" REFERENCE(EV_DECIMALS) TYPE BRF_RESULT_DECIMALS
*" REFERENCE(EV_DATA_MISSING) TYPE BRF_DATA_MISSING
*"----------------------------------------------------------------------
DATA lv_msg TYPE string.
DATA lv_document_guid TYPE /sapsrm/wf_document_guid.
DATA lv_document_type TYPE /sapsrm/wf_document_type.
DATA lt_item TYPE bbpt_pd_sc_item_d.
DATA lo_wf_brf_event TYPE REF TO /sapsrm/cl_wf_brf_event.
DATA lo_context_provider TYPE REF TO /sapsrm/if_wf_context_provider.
DATA lo_sc TYPE REF TO /sapsrm/if_pdo_bo_sc_adv.
FIELD-SYMBOLS: <fs_item> TYPE bbp_pds_sc_item_d.
ev_value = ''.
ev_type = 'C'.
ev_length = 30.
CLEAR ev_currency.
ev_output_length = 30.
ev_decimals = 0.
CLEAR ev_data_missing.
* get event object
IF NOT io_event IS BOUND.
* BRF event Object not bound. No further execution possible.
MESSAGE e089(/sapsrm/brf) INTO lv_msg.
TRY.
CALL METHOD /sapsrm/cl_wf_brf_ccms=>send_message( ).
CATCH /sapsrm/cx_wf_abort.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDTRY.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDIF.
*----------------------------------------------------------------
* get document data by context provider
*----------------------------------------------------------------
lo_wf_brf_event ?= io_event.
lo_context_provider = lo_wf_brf_event->get_context_provider( ).
* get Content Container from BRF event
IF NOT lo_context_provider IS BOUND.
* BRF Context Container Object not bound. No further execution possible.
MESSAGE e090(/sapsrm/brf) INTO lv_msg.
TRY.
CALL METHOD /sapsrm/cl_wf_brf_ccms=>send_message( ).
CATCH /sapsrm/cx_wf_abort.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDTRY.
ev_data_missing = /sapsrm/if_wf_rule_c=>brf_data_missing.
EXIT.
ENDIF.
CALL METHOD lo_context_provider->get_document
IMPORTING
ev_document_guid = lv_document_guid
ev_document_type = lv_document_type.
CASE lv_document_type .
WHEN /sapsrm/if_pdo_obj_types_c=>gc_pdo_shop.
CALL FUNCTION 'BBP_PD_SC_GETDETAIL'
EXPORTING
i_guid = lv_document_guid
TABLES
e_item = lt_item.
LOOP AT lt_item ASSIGNING <fs_item> WHERE del_ind IS INITIAL
AND catalogid IS INITIAL
AND product IS INITIAL
AND itm_type <> 'LIMI'.
ev_value = 'ZSRM_WF_SC_CUST'. " Custom Workflow
EXIT.
ENDLOOP.
ENDCASE.
IF ev_value IS INITIAL.
ev_value = '9C_BUS2121_EX99'. " No Workflow
ENDIF.
ENDFUNCTION.
First part of this post: Custom Workflow - Developer view - Part 1 - Idea and preparation
P.S.: English language is not my native language, and any person is not insured from mistakes and typing errors. If you have found an error in the text, please let me know - I'll correct the post.
P.P.S.: If you have some ideas, how to correct/improve this post - please don't hesitate to leave a comment.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.