Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
0 Kudos

Introduction

One of the core capabilities in Duet Enterprise 1.0 is Duet Enterprise workflow. The core capability allows exposing of SAP user decision workflow to Microsoft SharePoint 2010 and Outlook 2010. There are two types of work required for exposing a SAP user decision workflow task to SharePoint – configuration and custom development. The configuration steps have been covered in the release implementation document. But custom development, which accounts for the delivery of SAP business information to SharePoint task in assisting the decision making process, has not been covered in the official configuration document. The purpose of this blog is to fill the gap and explain how to implement a custom handler to transfer data from SAP ERP workflow to Duet Enterprise SharePoint and Outlook. In this blog I will show an example on how to create an outbound custom handler for a dummy purchase order approval workflow.

Implementing a new custom handler to transfer data from SAP ERP workflow to Duet Enterprise Office environment

In this example, I will demonstrate the option of customizing SharePoint workflow task body and subject to present purchase order header and item details, which will help the approver to make a decision. Again, method presented here is only an option. As this is custom development, you can choose any other methods you prefer.

Create the workflow outbound custom handler in the ERP system where your workflow resides (not the SCL system).

  • You can create the outbound custom handler by copying the delivered SAP default outbound handler S_OSP_WF_PAT_DEFAULT_CH_OB.  Go to SE37 and copy the default SAP outbound handler to your new function module.

  • Specify the new name of the function module such as Z_OUTBOUND_CUSTOM_HANDLER
  • Once the function module is created. Click the Change button.

  • Switch to the attributes tab and change the Short Text to description you prefer, such as “Duet Enterprise Workflow Custom Handler”.

  • Switch to the Source code tab and replace the existing source code with the code below. Please note the below example only set the body and subject text for “Task”, which corresponds to SharePoint task. In Duet Enterprise there is no need to set body and subject text for “Email”, as there is no direct sending of workflow item to Outlook. The workflow approval item will be sent to SharePoint as a task, and then SP server will relay the task to Exchange Server as email.

FUNCTION z_outbound_custom_handler.

*"----------------------------------------------------------------------

*"*"Local Interface:

*"  IMPORTING

*"     VALUE(IT_WORKITEM_DETAIL) TYPE  SOSP_TT_WF_RUNTIME_INFO OPTIONAL

*"  EXPORTING

*"     VALUE(EV_ERROR_FLAG) TYPE  S_OSP_DT_FLAG

*"     VALUE(ET_WORKITEM_DETAIL) TYPE  SOSP_TT_WF_RUNTIME_INFO

*"     VALUE(ET_RETURN) TYPE  BAPIRETTAB

*"----------------------------------------------------------------------

 DATA:  ls_workitem_detail  TYPE sosp_s_wf_runtime_info,

         ls_client_gpw_info  TYPE sosp_s_client_gpw_info,

         ls_subj_body_tab    TYPE sosp_s_subj_body_tab,

         lt_client_gpw_info  TYPE sosp_tt_client_gpw_info,

         lv_body_string      TYPE string.

 LOOP AT it_workitem_detail INTO ls_workitem_detail.

    CALL FUNCTION 'Z_SAMPLE_APP_CONTENT'

      EXPORTING

        workitem_detail   = ls_workitem_detail

      IMPORTING

        ev_body_html_text = lv_body_string.

     lt_client_gpw_info = ls_workitem_detail-client_gpw_info.

    LOOP AT lt_client_gpw_info INTO ls_client_gpw_info

      WHERE   recp_role_id = 'APPROVER'

      AND     gpw_object_sub_type = 'BND'.

      IF ls_client_gpw_info-gpw_object_type = 'TASK'.

*Fill the subject text information

        ls_subj_body_tab-subject = 'Please approve this PO for Hardware and Software purchase'.

*Fill the body text information

        ls_client_gpw_info-task_details-body-value = lv_body_string.

*Fill the subject text information

        ls_client_gpw_info-task_details-subject-value = ls_subj_body_tab-subject.

      ENDIF.

      MODIFY lt_client_gpw_info FROM ls_client_gpw_info.

    ENDLOOP.

***Set Client info to Workflow Pattern structure

    ls_workitem_detail-client_gpw_info = lt_client_gpw_info.

    APPEND ls_workitem_detail TO et_workitem_detail.

  ENDLOOP.

 ENDFUNCTION.

 

Looking Into the Above Outbound Custom Handler

  • Constructing the SharePoint task body with SAP business content.

The easiest way to construct SAP business content for SharePoint approval task is by using SAP standard text. This is usually not enough for content formatting and handling at SharePoint site.  The best is to display the content at SharePoint as HTML format. To achieve that, there are two options.

 

  1. Build the content as ABAP XML in SAP and transform the XML into HTML string directly in SAP by using XSLT transformation. For this approach please see my other blog for Duet 1.5 workflow

    Developing Duet time approval scenario using Workflow Template 1.0 Part 2

  2. Build the content as ABAP XML in SAP, send the XML to SharePoint and handle the XSLT transformation to HTML using SharePoint Designer

For myself, I would prefer the second approach. As this will save you from putting every single UI change into ABAP transport. Also I believe this is much cleaner approach compared to the first option. The SharePoint UI should be handled in front-end development tool - Microsoft SharePoint Designer, but not tool from SAP backend.

The sample code below demonstrates the construction of ABAP XML in SAP for PO approval business content.  The outcome XML string of the function module will be passed to your custom handler and sent over to SharePoint.

FUNCTION z_sample_app_content.

*"----------------------------------------------------------------------

*"*"Local Interface:

*"  IMPORTING

*"     REFERENCE(WORKITEM_DETAIL) TYPE  SOSP_S_WF_RUNTIME_INFO

*"  EXPORTING

*"     REFERENCE(EV_BODY_XML) TYPE  STRING

*"----------------------------------------------------------------------

 *  TYPE-POOLS: ixml.

  CLASS cl_ixml DEFINITION LOAD.

 *----Local variables

  DATA: ex                        TYPE REF TO cx_root,     

        ls_body_text              TYPE string,

        ls_document_xml           TYPE string,

        lo_ixml                   TYPE REF TO if_ixml,

        lo_document               TYPE REF TO if_ixml_document,

        lo_element                TYPE REF TO if_ixml_element,

        lo_root                   TYPE REF TO if_ixml_element,

        lo_workflow               TYPE REF TO if_ixml_element,

        lo_po                     TYPE REF TO if_ixml_element,

        lo_poitems                TYPE REF TO if_ixml_element,

        lo_poitem                 TYPE REF TO if_ixml_element.

  DATA: lv_temp_string            TYPE string.

  DATA: lt_container              TYPE sosp_tt_swr_cont.

  DATA: po_items                  TYPE STANDARD TABLE OF bapiekpo WITH HEADER LINE.

  DATA: po_header                 LIKE bapiekkol.

  DATA: po_item                   LIKE bapiekpo.

   lt_container = workitem_detail-workitem_container.

 *---Create xml structure

  lo_ixml = cl_ixml=>create( ).

  lo_document = lo_ixml->create_document( ).

  lo_root = lo_document->create_element( name = 'duet').

  lo_document->append_child( lo_root ).

  lo_workflow = lo_document->create_element( name = 'workflow').

  lo_root->append_child( lo_workflow ).

  lo_po = lo_document->create_element( name = 'poApproval').

  lo_workflow->append_child( lo_po ).

  lo_poitems = lo_document->create_element( name = 'poItems').

  lo_po->append_child( lo_poitems ).

** Here you can provide your own coding to retrieve 'real' PO information

** In below sample we will use dummy values

*  CALL FUNCTION 'BAPI_PO_GETDETAIL'

*    EXPORTING

*      PURCHASEORDER                    =

*    IMPORTING

*      PO_HEADER                        = po_header

*    TABLES

*      PO_ITEMS                         = po_items.

 * Document header

  lo_element = lo_document->create_simple_element( name = 'poNumber'

                                                   value = '4500000287'

                                                   parent = lo_po ).

* MOVE po_header-created_by TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'requestor'

                                                   value = 'Jenny Bryant'

                                                   parent = lo_po ).

* MOVE po_header-created_on TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'dateSubmitted'

                                                   value = 'Jan. 14, 2010'

                                                   parent = lo_po ).

 LOOP AT PO_ITEMS.

* PO Item list

  lo_poitem = lo_document->create_element( name = 'poItem' ).

  lo_poitems->append_child( lo_poitem ).

 * Item Number

* MOVE po_items-po_item TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'itemNumber'

                                                   value = '00010'

                                                   parent = lo_poitem ).

* Material

* MOVE po_items-material TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'material'

                                                   value = 'CH_0011'

                                                   parent = lo_poitem ).

* Short Text

* MOVE po_items-short_text TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'shortText'

                                                   value = 'CH Base'

                                                   parent = lo_poitem ).

* Quantity

* MOVE po_items-quantity TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'quantity'

                                                   value = '2000'

                                                   parent = lo_poitem ).

* Unit

* MOVE po_items-unit TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'unit'

                                                   value = 'GLL'

                                                   parent = lo_poitem ).

* Unit Price

* MOVE po_items-net_price TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'unitPrice'

                                                   value = '7.00'

                                                   parent = lo_poitem ).

* Currency

* MOVE po_header-currency TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'currency'

                                                   value = 'USD'

                                                   parent = lo_poitem ).

* Delivery Date

* MOVE po_items-plan_del TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'deliveryDate'

                                                   value = '01-20-2009'

                                                   parent = lo_poitem ).

* Material Group

* MOVE po_items-mat_grp TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'materialGroup'

                                                   value = '01'

                                                   parent = lo_poitem ).

* Plant

* MOVE po_items-plant TO lv_temp_string.

  lo_element = lo_document->create_simple_element( name = 'plant'

                                                   value = 'BP01'

                                                   parent = lo_poitem ).

 ENDLOOP.

 TRY.

      CALL TRANSFORMATION id

        SOURCE XML lo_document

        RESULT XML ls_document_xml.

    CATCH cx_transformation_error INTO ex.              

  ENDTRY.

  ev_body_xml = ls_document_xml.

ENDFUNCTION.

 

Open again the custom handler “Z_OUTBOUND_CUSTOM_HANDLER” in SE37. In this line of the code, the custom handler calls function module “Z_SAMPLE_APP_CONTENT” to create the PO XML document string.         

  • Optional: Inside the custom handler function module, you can change the subject of the workflow approval task.

  • Pass the XML string to SharePoint by appending the string to Duet Enterprise default workflow task body structure.

  • Activate the function module.

One thing to pay attention is the business content I push to SharePoint in the custom handler coding is only static XML string. There is another technique to push name-value pair structures from SAP to SharePoint task so that they can be used in your code behind programming. I will cover that in my next blog for Duet Enterprise Workflow.

Highlights of Configuration Steps

Although you could find the information from SAP delivered Duet Enterprise implementation document. I would still like to give some highlights of SAP configuration steps for Duet Enterprise workflow. So that you know where to add the custom handler into the Duet Enterprie Workflow configuration picture. 

 

  • Include the “Z_OUTBOUND_CUSTOM_HANDLER” as custom handler for your workflow. Go to transaction SIMGH in the ERP system (Not SCL system). Search and display IMG structure Duet Implementation Guide

  • Choose “Workflow Pattern Customization”.

  • Select the application ID where your workflow customization already exists. Such as “TGWF”. Double click on menu Workflow.          

  • Click on the New Entries button and insert the Outbound Custom Handler – “Z_OUTBOUND_CUSTOM_HANDLER”. Call the Z Outbound Custom Handler first, which is indicated by Counter 1 in this example. Make sure to include and call the SAP default Outbound Custom Handler “S_OSP_WF_PAT_DEFAULT_CH_OB” the last, which is indicated by Counter 2 in this example.

  • Select one of the workflow entries and double click on menu Tasks. It doesn’t matter which one you choose.

  • Display the setting defined for PO approval workflow. These settings inform Duet Enterprise Workflow which SAP workflow template, which user decision task, and which workflow step should be picked up and sent to Duet Enterprise SharePoint and Outlook. Notice the settings - Groupware Object Type and GPW Bound Item Type. The two settings define how SAP workflow associates with a SharePoint workflow task. The GPW Bound Item Type “POApproval” is exactly what you should define in SharePoint as Task Name for PO Approval workflow site.

  • Double click on menu Action.
  • Display transition actions defined for PO approval workflow. Transition actions define how Duet Enterprise Workflow should act for a specific workflow item status transition. For example, if a workflow item status changed from blank to C (Create), a workflow task should be created and sent out to SharePoint 2010 and Outlook 2010.

 

These are all the steps you need to create and add a new custom handler in Duet Enterprise Workflow. In the next blog I will talk about how to send name-value data structure from SAP to SharePoint for Duet Enterprise Workflow. That will be a dynamic approach to program SAP worklfow data in SharePoint.

In this blog, you learned how to:

  • Implement custom handler in ECC for Duet Enterprise Workflow
  • Build custom workflow task body and subject using custom handler 
5 Comments