Skip to Content
Author's profile photo Konstantin Anikeev

Custom Workflow – Developer view – Part 2 – Process Schema and Implementation

First part of this post: Custom Workflow – Developer view – Part 1 – Idea and preparation

Process Schema Evaluation

First start the transaction /SAPSRM/WF_PROCESS

image2013-4-28 17-58-34.png

Create new expression for schema evaluation

image2013-5-1 20-31-29.png

image2013-5-1 20-33-26.png

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.

image2013-5-1 20-39-2.png

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.

image2013-5-1 20-50-27.png

Create new event for schema evaluation

image2013-5-1 21-2-5.png

image2013-5-1 21-3-5.png

Provide event name ZSRM_EV_SC_START.

ZSRM – Group Name

EV – Event

SC – Shopping cart

START – Shopping cart event

image2013-5-1 21-6-52.png

Save Event. Then select Event->Change.

image2013-5-1 21-8-42.png

In the change mode you can add a new rule.

image2013-5-1 21-10-4.png

Here you should add a created expression.

image2013-5-1 21-11-25.png

Save the changes.

Setting all together

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.

image2013-8-2 0-12-9.png

Set the created evaluation id.

image2013-8-2 0-13-9.png

Then go to Process Schema Definition and create a new entry.

image2013-8-2 0-14-10.png

Provide following customizing.

image2013-8-2 0-19-26.png

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.

Implementation

Implementing agent determination strategies

image2013-8-1 22-26-50.png

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.

image2013-8-1 22-29-39.png

Step 1

image2013-8-1 22-34-23.png

image2013-8-1 22-35-7.png

In the created Implementation double click on filter values.

image2013-8-1 22-37-32.png

and create a new combination.

image2013-8-1 22-38-27.png

Select all entries.

image2013-8-1 22-38-57.png

Set the values as shown and acivate implementation.

image2013-8-1 22-39-57.png

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

Step 2

image2013-8-1 23-23-27.png

image2013-8-1 23-24-56.png

image2013-8-1 23-26-9.png

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.

Implementation of Expression function ZSRM_WF_EX_CUST_APPR_REL.

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.

Implementation of Expression function ZSRM_WF_SCHEMA_DET.

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.

Result

/wp-content/uploads/2013/08/ap_256938.png

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.

Assigned Tags

      9 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Thanks for the detailed blog

      Author's profile photo Konstantin Anikeev
      Konstantin Anikeev
      Blog Post Author

      Thanks, Praveen

      Author's profile photo Former Member
      Former Member

      Hi Konstantin,

      thanks a lot for the detailed blog!!! I would have needed this 1,5 years ago ;-).


      Author's profile photo Konstantin Anikeev
      Konstantin Anikeev
      Blog Post Author

      me too 🙂

      Author's profile photo Vinita Kasliwal
      Vinita Kasliwal

      really nice one !

      Author's profile photo Former Member
      Former Member

      Can I ask you complicated question ?

      I met a very difficult requirement.

      The Requirement is :

      The contract needs the approval from two departments:

      --Procurement Dept.:  Line manager A1 or Line manager A2; then superior A3;

      --Financial Dept.:        Financial controller B1 or financial controller B2; then Financial manager B3.

      There is no special sequence between approval process A and B.

      But in A or B, there is a sequence.

      Please suggest how I can realize it easily.

      Thanks a lot.

      Author's profile photo Konstantin Anikeev
      Konstantin Anikeev
      Blog Post Author

      Hi,

      I suppose you'll have to define sequence for processes A and B.

      PCW is basen on approval levels, SC goes to the next level only if current approved.

      What you can do, to speed up the process is parallel approval for A1, A2 and B1, B2 as a first step and parallel approval for A3 and B3 as a second step.

      But 2 completely independent processes are not possible.

      Regards

      Konstantin

      Author's profile photo Former Member
      Former Member

      Konstantin

      Thanks a lot fro your reply.

      Do you think if I can realize it as:

      The first level: agent A1,A2,B1,B2,

      Then , if A1 approved.

      The second level: agent A3,B1,B2,

      Then, if A3 approved,

      The third level : agent B1,B2.

      It goes like this way.

      Do you think I can realize that?

      Actually, the agent determination is dynmatic.

      Do you think it can be realized?

      Thanks very much.

      Regards,

      Hayashi.

      Author's profile photo airwave airwave
      airwave airwave

      Konstantin really a greate performance.

      For me it is not very clear how this works:

      How is the relation made with a respons. Resolver e.g RR_MANAGER, RR_EMPLOYEE etc.
      and a user or person who has been determined/found  as approver.

       

      Thank you in advance

      airwave