`
evangxli
  • 浏览: 223620 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

转 Offline Workflow Approval in ECC R/3 without SAP Logon from E-Mail (Outlook)

 
阅读更多

Offline Workflow Approval in ECC R/3 without SAP Logon from E-Mail (Outlook)

By Anirban Bhattacharjee, KPIT Cummins and Infosystems from Link

Purpose: This document will demonstrate how you can set up a DEMO that will allow a user to APPROVE or REJECT (Process as per requirement) a workflow work item directly from Outlook E-Mail without logging into SAP. The approver does not need to have SAP GUI Installed in the system from where the approval is being carried out. The approver also does not need to enter the SAP user ID and password. These approval links are not SAP Shortcut links as generated by the RSWUWFML2 program that is normally used for approval from outlook. These are normal MAILTO links and works on almost all e-mail environments and internet browsers. This will also work on hand held devices like iPhone® or Blackberry® if adequately configured with Exchange Server. Since the MAILTO links will work on the Web Mail version of outlook as well, so normal browsers running on the handheld devices can also assist in carrying out the Workflow Processing Offline.

Hence using this concept, you can now process work items, run ABAP programs, do any SAP activity Offline remotely, without having to log into SAP.

Business Requirement: Business needs a way by which they can process workflow work items completely offline. They want to be able to do this even when they are not in the SAP Network. The user will not enter the SAP User ID and password, nor will they have SAP GUI in the system from where the approval is being carried out. They should be able to directly process from Outlook which should work across different browsers and handheld devices that run internet browsers.

How the DEMO Will Work, its features and ADVANTAGES

The various working steps, features and advantages of this demo are mentioned belowè

·         The workflow template consisting of a single user decision step with a work item exit will generate a HTML Notification E-Mail to the Approver who also has received the User Decision Work Item for processing.

·         This HTML E-Mail will demonstrate the data in Tabular Format and provide two links to the approver; APPROVE and REJECT.

·         These links are typical MAILTO links. On clicking either of these links, the system will generate an auto e-mail to send to the SAP System.

·         This e-mail will have the TO field auto-populated with the Offline System SAP ID and the Subject also auto-populated with the action (A or R, for APPROVE or REJECT) and the Work Item ID of the User Decision step that was sent to the approver.

·         The Inbound Exit Class will read this e-mail subject and process the work item.

·         User will not have to enter the SAP User ID or Password to send this auto email.

·         The user thus does not need to log on to the SAP System.

·         The user need not be in the SAP Network or VPN to send this email.

·         The user does not need to have SAP GUI present, since these links are not SAP Short Cut Links that need SAP GUI.

·         Any application that can process MAILTO links can send these auto e-mails. Hence this works even in handheld devices like iPhone®, Blackberry®, etc.

·         This works in various Internet Browsers. I have tested this in various versions of Microsoft® Internet Explorer, Google® Chrome, etc.

·         Works on both Web Mail version of Microsoft® Outlook and Normal Outlook®

·         No need to schedule any batch job for programs like RSWUWFML2.

·         Highly customizable and easy to implement.

·         No third party tool required.

·         Using this concept you can run any SAP Transaction, schedule batch jobs, get report summary and output in your e-mail from a remote system without logging into the SAP Network.

Inbound E-Mail Receiving configurations in SAP

We need to first create a user ID in Outlook along with a sub-domain that will point to the desired SAP System. So for example if your company domain is www.yourdomain.com then the sub-domain would be something like ecc-dev.yourdomain.com (This will be created by your Network and Infrastructure People). You should be able to ping this domain.

Now let us name the Offline System User as ECCOFFLINE and then after a user is created in Microsoft Outlook with above sub-domain, the e-mail ID will be eccoffline@ecc-dev.yourdomain.com. Please note that this is a very critical step in this development and hence needs to be configured correctly. This e-mail ID and sub-domain choice is completely your own. You can plan your own ID as per your choice. This is the only configuration outside SAP on the Network / Exchange Server Side.

Create Offline User in SAP (SU01)

To receive e-mail in SAP, you need to first create a System User ID that will receive these e-mails. This will be a system user with “SYSTEM” as the User Group. The user ID created is named ECCOFFLINE. The Logon Data tab is shown belowè

This user must have three mandatory Profiles: S_A.SCON, SAP_ALL and SAP_NEW as shown belowè

The e-mail ID created in the first step, is also entered here in the Address tab as shown (eccoffline@ecc-dev.yourdomain.com)è

Configure the SAP-Connect node via SICF Transaction

The entry screen of SICF Transaction, press F8è

Select the SAP-Connect Node and click the DISPLAY-CHANGE button as shownè

Then activate the node as shownè

After activation, the node screen will look as shown belowè

In the LOGON Data Tab, mention the ECCOFFLINE user and set the passwordè

Configure and activate the SMTP Service via SMICM transaction

Run transaction SMICM or Report RSMONICM_STANDARDè

Display the services via SHIFT+F1 or menu path as shownè

This displays the Services as shown. Mention the SMTP port (normally 25, your Basis consultant will provide you the port number, this is similar to the port settings done in SCOT transaction for SAP Connect Outbound E-Mail Configuration) and activate the service. The GREEN check will indicate the service is active. The Host Name will also be provided by your Basis / Security Consultant. This Host is also similar to the host maintained in SCOT for the SMTP nodeè

Activate and change the service via the menu as shown belowè

Configure and set the Inbound E-Mail Exit Configuration

Transaction SO50 is used to mention the inbound e-mail exit. This also can be access via SCOT transaction by the menu path SettingsàInbound Processing. This also calls SO50.

You can also run Report BCS_IBND_MAINT to call SO50 Transaction.

 

We have to write an Inbound Exit Class that will process the Inbound E-Mails. That class should be mentioned here. (We will see later how to create this class)è

Note that we mention our offline e-mail ID here (eccoffline@ecc-dev.yourdomain.com). The class ZZZCL_PROCESS_INBOUND_WORKFLOW is the Exit Class designed to process inbound e-mails as per our need. By default generally the first entry with the CL_APPOINTMENT_REPLY is always present. We include our entry here and set the call sequence. The Document Class / Type is set as “*” to allow all types of documents available in ECC.

Creation of the Inbound Exit Class

This class implements the interface IF_INBOUND_EXIT_BCS (BCS: Exit for Inbound Processing). The properties tab of the class is shownè

The Interfaces Tabè

The Methods Tabè

The CREATE_INSTANCE method is called by standard SAP (via SO50 Configuration) to create a unique instance for each inbound e-mail. The code is written belowè

METHOD if_inbound_exit_bcs~create_instance.
  DATA: ref TYPE REF TO zzzcl_process_inbound_workflow.
* Check if the Instance is initial
  IF ref IS INITIAL.
    CREATE OBJECT ref.
  ENDIF.
* Return the Instance
  ro_ref = ref.
ENDMETHOD.

The interface of the method CREATE_INSTANCE is shownè

The PROCESS_INBOUND method is the place where we write the exit logic. This is where we will process the desired work item of the workflow and process it based on the e-mail action / reply created by the automated e-mail. The interface of method PROCESS_INBOUND is shownè

The code in PROCESS_INBOUND methodè

METHOD if_inbound_exit_bcs~process_inbound.
* Declare for Inbound E-Mail processing (ENJOY :) :) )
  DATA: lo_document     TYPE REF TO if_document_bcs,
        l_mail_attr     TYPE bcss_dbpa,
        l_mail_content  TYPE bcss_dbpc,
        lo_reply        TYPE REF TO cl_send_request_bcs,
        sender          TYPE REF TO if_sender_bcs,
        sender_addr     TYPE string,
        lv_email        TYPE comm_id_long,
        send_request    TYPE REF TO cl_bcs,
        ltext           TYPE bcsy_text,
        body_text       TYPE so_text255,
        document        TYPE REF TO cl_document_bcs,
        ex_sender       TYPE REF TO cl_sapuser_bcs,
        recipient       TYPE REF TO if_recipient_bcs,
        bcs_exception   TYPE REF TO cx_bcs,
        sent_to_all     TYPE os_boolean,
        lv_action       TYPE char01,
        lv_wid          TYPE char12,
        lv_wid_num      TYPE sww_wiid,
        lv_wid_func     TYPE swr_struct-workitemid,
        ls_swwwihead    TYPE swwwihead,
        lv_new_status   TYPE sww_wistat,
        lv_action_text  TYPE char12.
*--------------------------------------------------------------------*
*- Get a pointer to the reply email object -*
*--------------------------------------------------------------------*
  TRY.
      lo_reply = io_sreq->reply( ).
    CATCH cx_send_req_bcs.
  ENDTRY.
**** Check to make sure this is from an approved Sender
  sender = io_sreq->get_sender( ).
  sender_addr =  sender->address_string( ).
  lv_email = sender_addr.
  TRANSLATE sender_addr TO UPPER CASE.
**** Only reply if this message came from within our mail system or domain
**** SPAMMERS Beware, your e-mails will not be processed!!!
  IF sender_addr CS '@YOURDOMAIN.COM'.
**** send reply and inbound processing
*--------------------------------------------------------------------*
*- Get email subject -*
*--------------------------------------------------------------------*
    TRY.
        lo_document = io_sreq->get_document( ).
        l_mail_attr = lo_document->get_body_part_attributes( '1' ).
      CATCH cx_document_bcs.
    ENDTRY.
*--------------------------------------------------------------------*
*- Get mail body, here you can read the REJECTION Reason -*
*--------------------------------------------------------------------*
    TRY.
        l_mail_content = lo_document->get_body_part_content( '1' ).
      CATCH cx_document_bcs.
    ENDTRY.
*--------------------------------------------------------------------*
* YAAAAAHHHHHHOOOO at this point I have the Subject and the Body
*--------------------------------------------------------------------*
* Now read the subject and process the work item
* Condense the subject to remove blank spaces
    CONDENSE l_mail_attr-subject.
* Read the action
    lv_action = l_mail_attr-subject+0(1).
* Read the work item ID
    lv_wid    = l_mail_attr-subject+1(12).
* Pass to variables
    lv_wid_num = lv_wid.
    lv_wid_func = lv_wid_num.
* First check the status of the work item, process only if READY or IN-PROCESS
    SELECT SINGLE *
      FROM swwwihead
      INTO ls_swwwihead
      WHERE wi_id = lv_wid_num.
* If data not found, indicates an invalid e-mail sent to offline ID
    IF sy-subrc NE 0.
      lv_wid = 'INVALID WID'.
    ENDIF.
* Check the status, if COMPLETED, send the notification
    IF ls_swwwihead-wi_stat = 'COMPLETED'.
      TRY.
*     -------- create persistent send request ------------------------
          send_request = cl_bcs=>create_persistent( ).
*     -------- create and set document -------------------------------
*     Build the e-mail Body
          CLEAR: body_text.
          CONCATENATE 'WORK ITEM ID : '
                      lv_wid
                      'is in status "COMPLETED"' INTO body_text SEPARATED BY space.
          APPEND body_text TO ltext.
          CLEAR: body_text.
          CONCATENATE 'This has already been processed '
                      'and cannot be processed again.' INTO body_text SEPARATED BY space.
          APPEND body_text TO ltext.
          document = cl_document_bcs=>create_document(
                                i_type    = 'RAW'
                                i_text    = ltext
                                i_length  = '510'
                                i_subject = 'Work Item has already been processed' ).
*     Add document to send request
          CALL METHOD send_request->set_document( document ).
*     --------- set sender -------------------------------------------
*     note: this is necessary only if you want to set the sender
*           different from actual user (SY-UNAME). Otherwise sender is
*           set automatically with actual user.
          sender = cl_sapuser_bcs=>create( 'ECCOFFLINE' ).
          CALL METHOD send_request->set_sender
            EXPORTING
              i_sender = sender.
*     --------- Add recipient (e-mail address) -----------------------
*     Create recipient - passing the receipient e-mail ID
          recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
*     Add recipient with its respective attributes to send request
          CALL METHOD send_request->add_recipient
            EXPORTING
              i_recipient = recipient
              i_express   = 'X'.
*     ---------- Send document ---------------------------------------
          CALL METHOD send_request->send(
            EXPORTING
              i_with_error_screen = 'X'
            RECEIVING
              result              = sent_to_all ).
          COMMIT WORK.
        CATCH cx_bcs INTO bcs_exception.
      ENDTRY.
    ELSEIF ls_swwwihead-wi_stat = 'READY' OR
           ls_swwwihead-wi_stat = 'STARTED'.
* First process the Work Item Based on the action
      IF lv_action = 'A'.
* Set the ACTION Text
        lv_action_text = 'APPROVED'.
* If APPROVED
        CALL FUNCTION 'SAP_WAPI_DECISION_COMPLETE'
          EXPORTING
            workitem_id          = lv_wid_func
            language             = sy-langu
            user                 = sy-uname
            decision_key         = '0001' "Approval Node
            do_commit            = 'X'
          IMPORTING
            new_status           = lv_new_status
*  TABLES
*    MESSAGE_LINES        =
*    MESSAGE_STRUCT       =
                  .
      ELSEIF lv_action = 'R'.
* Set the ACTION Text
        lv_action_text = 'REJECTED'.
* If REJECTED
        CALL FUNCTION 'SAP_WAPI_DECISION_COMPLETE'
          EXPORTING
            workitem_id          = lv_wid_func
            language             = sy-langu
            user                 = sy-uname
            decision_key         = '0002' "Rejection Node
            do_commit            = 'X'
          IMPORTING
            new_status           = lv_new_status
*  TABLES
*    MESSAGE_LINES        =
*    MESSAGE_STRUCT       =
                  .
      ENDIF.
* After the action now send the e-mail
      TRY.
*     -------- create persistent send request ------------------------
          send_request = cl_bcs=>create_persistent( ).
*     -------- create and set document -------------------------------
*     Build the e-mail Body
          CLEAR: body_text.
          CONCATENATE 'WORK ITEM ID : '
                      lv_wid
                      'has been'
                      lv_action_text INTO body_text SEPARATED BY space.
          APPEND body_text TO ltext.
          CLEAR: body_text.
          CONCATENATE 'New status of work item is '
                      lv_new_status INTO body_text SEPARATED BY space.
          APPEND body_text TO ltext.
          document = cl_document_bcs=>create_document(
                                i_type    = 'RAW'
                                i_text    = ltext
                                i_length  = '510'
                                i_subject = 'Work Item processing confirmation' ).
*     Add document to send request
          CALL METHOD send_request->set_document( document ).
*     --------- set sender -------------------------------------------
*     note: this is necessary only if you want to set the sender
*           different from actual user (SY-UNAME). Otherwise sender is
*           set automatically with actual user.
          sender = cl_sapuser_bcs=>create( 'ECCOFFLINE' ).
          CALL METHOD send_request->set_sender
            EXPORTING
              i_sender = sender.
*     --------- Add recipient (e-mail address) -----------------------
*     Create recipient - passing the receipient e-mail ID
          recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
*     Add recipient with its respective attributes to send request
          CALL METHOD send_request->add_recipient
            EXPORTING
              i_recipient = recipient
              i_express   = 'X'.
*     ---------- Send document ---------------------------------------
          CALL METHOD send_request->send(
            EXPORTING
              i_with_error_screen = 'X'
            RECEIVING
              result              = sent_to_all ).
          COMMIT WORK.
        CATCH cx_bcs INTO bcs_exception.
      ENDTRY.
    ELSE.
* This means the work item is in ERROR or some exception status, NOTIFY!!!!!
* Here you can reply back to the user if they send invalid e-mails to ECCOFFLINE other then clicking on the Processing Links
      TRY.
*     -------- create persistent send request ------------------------
          send_request = cl_bcs=>create_persistent( ).
*     -------- create and set document -------------------------------
*     Build the e-mail Body based on the Work Item ID
          IF lv_wid = 'INVALID WID'.
* Build E-Mail for Invalid WID
            CLEAR: body_text.
            CONCATENATE 'This system e-mail is meant only for OFFLINE WORKFLOW Processing.'
                        'Please do not send any e-mails to this ID other then via Workflow Processing Offline Links.' INTO body_text SEPARATED BY space.
            APPEND body_text TO ltext.
            CLEAR: body_text.
            CONCATENATE 'This is a system generated auto e-mail '
                        'Please do not reply to this ID.' INTO body_text SEPARATED BY space.
            APPEND body_text TO ltext.
            document = cl_document_bcs=>create_document(
                                  i_type    = 'RAW'
                                  i_text    = ltext
                                  i_length  = '510'
                                  i_subject = 'System ID - Please do not reply or send E-Mail' ).
          ELSE.
* Build E-Mail body for Valid WID gone in exception status
            CLEAR: body_text.
            CONCATENATE 'WORK ITEM ID '
                        lv_wid
                        'might not have processed as desired.' INTO body_text SEPARATED BY space.
            APPEND body_text TO ltext.
            CLEAR: body_text.
            CONCATENATE 'Please forward this e-mail to the '
                        'System / Workflow Administrator to help you and analyze / solve it.' INTO body_text SEPARATED BY space.
            APPEND body_text TO ltext.
            document = cl_document_bcs=>create_document(
                                  i_type    = 'RAW'
                                  i_text    = ltext
                                  i_length  = '510'
                                  i_subject = 'Work Item exception might have occured' ).
          ENDIF.
*     Add document to send request
          CALL METHOD send_request->set_document( document ).
*     --------- set sender -------------------------------------------
*     note: this is necessary only if you want to set the sender
*           different from actual user (SY-UNAME). Otherwise sender is
*           set automatically with actual user.
          sender = cl_sapuser_bcs=>create( 'ECCOFFLINE' ).
          CALL METHOD send_request->set_sender
            EXPORTING
              i_sender = sender.
*     --------- Add recipient (e-mail address) -----------------------
*     Create recipient - passing the receipient e-mail ID
          recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
*     Add recipient with its respective attributes to send request
          CALL METHOD send_request->add_recipient
            EXPORTING
              i_recipient = recipient
              i_express   = 'X'.
*     ---------- Send document ---------------------------------------
          CALL METHOD send_request->send(
            EXPORTING
              i_with_error_screen = 'X'
            RECEIVING
              result              = sent_to_all ).
          COMMIT WORK.
        CATCH cx_bcs INTO bcs_exception.
      ENDTRY.
    ENDIF.
* End the IF for checking valid E-Mail
  ENDIF.
ENDMETHOD.

Creation of the workflow template

I will not discuss in details on this step. The SAP Technical site has a huge number of tutorials that will show you how to do this. For our demo, we are creating a very simple workflow template with a single User Decision Step. The template is shown (Notice there is no SEND MAIL step. E-Mail is sent via the Work Item exit)è

The work item exit is mentioned in the user decision step as shownè

To know how to create a work item exit, please follow this LINK in SAP Technical to learn and follow the steps in the tutorial.

(If that does not open copy and paste this link in your browseràhttp://saptechnical.com/Tutorials/Workflow/Exit/Index.htm)

In the exit, we write our e-mail logic in the method AFTER_WI_CREATION. This method is triggered the moment the User Decision Work Item is created and sent to the approver. Our e-mail is also created and sent almost at the same instant. The code in this method is shown. The system e-mail ID will depend on the ID created by your infrastructure team.

(Note: I have shown two different ways to send the e-mail; one via the BCS Class and the other the SOFM Function Module. Please select whichever way you prefer. Remember to comment out one of the ways, else you will get two e-mails on Work Item Creation J)

Code for method AFTER_WI_CREATION è 

METHOD after_wi_creation.
  DATA: lcl_v_wi_id        TYPE sww_wiid,  "Work Item ID
        lv_wid_read        TYPE sww_wiid,  "Work Item ID to read container data
        lv_wid_text        TYPE char12,
        l_it_father_wis    TYPE STANDARD TABLE OF swwwihead,
        l_wa_father_wis    TYPE swwwihead,
        send_request       TYPE REF TO cl_bcs,
        text               TYPE bcsy_text,
        body_text          TYPE so_text255,
        document           TYPE REF TO cl_document_bcs,
        sender             TYPE REF TO cl_sapuser_bcs,
        recipient          TYPE REF TO if_recipient_bcs,
        bcs_exception      TYPE REF TO cx_bcs,
        sent_to_all        TYPE os_boolean.
* Declare the Work Item Container data
  DATA: l_it_wi_container  TYPE STANDARD TABLE OF swcont,
        l_wa_wi_container  TYPE swcont,
        l_wa_wi_header     TYPE swwwihead.
* Declaration for the Dynamic Values in text
  DATA: lv_belnr           TYPE belnr_d,
        lv_bukrs           TYPE bukrs,
        lv_gjahr           TYPE char04,
        lv_email           TYPE comm_id_long,
        lv_lines           TYPE i,
        lv_so_obj_len      TYPE so_obj_len.
* Other e-mail technique to do the declarations
  DATA : it_message         TYPE STANDARD TABLE OF solisti1,
         wa_message         TYPE solisti1,
         it_attach          TYPE STANDARD TABLE OF solisti1,
         wa_attach          TYPE solisti1,
         t_receivers        TYPE STANDARD TABLE OF somlreci1,
         wa_receivers       TYPE somlreci1,
         w_doc_data         TYPE sodocchgi1.
* For simplicity of the demo, we are only fetching the work item ID
* You can get the complete work item and workflow details as well
* Please refer class CL_SWF_RUN_WORKITEM_CONTEXT and interface IF_WAPI_WORKITEM_CONTEXT
* Get the Work Item ID
  CALL METHOD wi_context->get_workitem_id
    RECEIVING
      re_workitem = lcl_v_wi_id.
* Pass WID to text field to concatenate to the e-mail body for MAILTO link
  CLEAR: lv_wid_text.
  lv_wid_text = lcl_v_wi_id.
* Fetch the parent work item ID
  REFRESH: l_it_father_wis[].
  CALL FUNCTION 'SWW_WI_FIND_FATHER_WIS'
    EXPORTING
      wi_id      = lcl_v_wi_id
    TABLES
      father_wis = l_it_father_wis.
* Read the Father WID, if not found then running WID is Father WID
  CLEAR: l_wa_father_wis, lv_wid_read.
  READ TABLE l_it_father_wis INTO l_wa_father_wis INDEX 1.
* If Father Work Item ID found pass to the WID Variable else pass the Original WID
  IF sy-subrc = 0.
    lv_wid_read = l_wa_father_wis-wi_id.
  ELSE.
    lv_wid_read = lcl_v_wi_id.
  ENDIF.
* Read the work flow container data with WID Populated
  REFRESH: l_it_wi_container[].
  CLEAR: l_wa_wi_header.
  lv_wid_read = lcl_v_wi_id - 1.
  CALL FUNCTION 'SWW_WI_CONTAINER_READ'
    EXPORTING
      wi_id                    = lv_wid_read
    TABLES
      wi_container             = l_it_wi_container
    CHANGING
      wi_header                = l_wa_wi_header
    EXCEPTIONS
      container_does_not_exist = 1
      read_failed              = 2
      OTHERS                   = 3.
* If the call is a success
  IF sy-subrc = 0.
    CLEAR: lv_belnr, lv_bukrs, lv_gjahr, lv_email.
* Read the container values and pass them to generate the dynamic e-mail body
* Read the Company Code from Workflow WS91000120
    CLEAR: l_wa_wi_container.
    READ TABLE l_it_wi_container INTO l_wa_wi_container
    WITH KEY element = 'BUKRS'.
    IF sy-subrc = 0.
      CONDENSE l_wa_wi_container-value.
      lv_bukrs = l_wa_wi_container-value.
    ENDIF.
* Read the Invoice Number from Workflow WS91000120
    CLEAR: l_wa_wi_container.
    READ TABLE l_it_wi_container INTO l_wa_wi_container
    WITH KEY element = 'BELNR'.
    IF sy-subrc = 0.
      CONDENSE l_wa_wi_container-value.
      lv_belnr = l_wa_wi_container-value.
    ENDIF.
* Read the Fiscal Year from Workflow WS91000120
    CLEAR: l_wa_wi_container.
    READ TABLE l_it_wi_container INTO l_wa_wi_container
    WITH KEY element = 'GJAHR'.
    IF sy-subrc = 0.
      CONDENSE l_wa_wi_container-value.
      lv_gjahr = l_wa_wi_container-value.
    ENDIF.
* Read the Company Code from Workflow WS91000120
    CLEAR: l_wa_wi_container.
    READ TABLE l_it_wi_container INTO l_wa_wi_container
    WITH KEY element = 'EMAIL_ID'.
    IF sy-subrc = 0.
      CONDENSE l_wa_wi_container-value.
      lv_email = l_wa_wi_container-value.
    ENDIF.
  ENDIF.
*----------------------------------------------------------------------------------------*
* Send an e-mail to a dummy e-mail ID stating that the above Work Item has been created
*----------------------------------------------------------------------------------------*
  TRY.
*     -------- create persistent send request ------------------------
      send_request = cl_bcs=>create_persistent( ).
*     -------- create and set document -------------------------------
*     Build the e-mail Body
*      CLEAR: body_text.
*      CONCATENATE 'Work Item Created. WID:'
*                  lv_wid_text INTO body_text SEPARATED BY space.
*--------------------------------------------------------------------*
* Start the Mail Body
*--------------------------------------------------------------------*
      CLEAR: body_text, wa_message.
      CONCATENATE body_text
                  '<html><body>Dear User'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<h3>What you need to know:</h3>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  'Below is the invoice waiting for your approval.'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<h4>Invoice Information</h4>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
*--------------------------------------------------------------------*
* Start Invoice Information in Table
*--------------------------------------------------------------------*
      CLEAR: body_text.
      CONCATENATE body_text
                  '<table border = "1" bgcolor = "skyblue">'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr><td>Invoice Number</td><td>'
                  lv_belnr
                  '</td></tr>'
                  INTO body_text.
      CONDENSE body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr><td>Company Code</td><td>'
                  lv_bukrs
                  '</td></tr>'
                  INTO body_text.
      CONDENSE body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr><td>Fiscal Year</td><td>'
                  lv_gjahr
                  '</td></tr>'
                  INTO body_text.
      CONDENSE body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr><td>Gross Invoice Value (USD)</td><td>200,000.00</td></tr></table>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
*--------------------------------------------------------------------*
* End Invoice Table
*--------------------------------------------------------------------*
*--------------------------------------------------------------------*
* Start Multiline Table
*--------------------------------------------------------------------*
      CLEAR: body_text.
      CONCATENATE body_text
                  '<h4>Line Item Data displayed in tabular format</h4>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<table border="1" bgcolor = "lightgreen">'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr>'
                  '<th>Header 1</th>'
                  '<th>Header 2</th>'
                  '<th>Header 3</th>'
                  '<th>Header 4</th>'
                  '<tr>'
                  '<td>row 1, cell 1</td>'
                  '<td>row 1, cell 2</td>'
                  '<td>row 1, cell 3</td>'
                  '<td>row 1, cell 4</td>'
                  '</tr>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr>'
                  '<td>row 2, cell 1</td>'
                  '<td>row 2, cell 2</td>'
                  '<td>row 2, cell 3</td>'
                  '<td>row 2, cell 4</td>'
                  '</tr>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr>'
                  '<td>row 3, cell 1</td>'
                  '<td>row 3, cell 2</td>'
                  '<td>row 3, cell 3</td>'
                  '<td>row 3, cell 4</td>'
                  '</tr>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<tr>'
                  '<td>row 4, cell 1</td>'
                  '<td>row 4, cell 2</td>'
                  '<td>row 4, cell 3</td>'
                  '<td>row 4, cell 4</td>'
                  '</tr>'
                  '</table>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
*--------------------------------------------------------------------*
* End Multiline Table
*--------------------------------------------------------------------*
      CLEAR: body_text.
      CONCATENATE body_text
                  '<h3>What you need to do:</h3>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  'To approve the invoice via portal, please log onto the YOUR-COMPANY Business Portal by clicking here:'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
* Generate the YOUR Company Portal Production Link
      CLEAR: body_text.
      CONCATENATE body_text
                  '<a href="http://companyprderp.yourcompany.net:50000/irj/portal">YOUR_COMPANY Portal</a></p>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
* Genrate the Dynamic MAILTO Links
      CLEAR: body_text.
      CONCATENATE body_text
                  'To process directly from e-mail, make your selection here &nbsp;'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<a href="mailto:eccoffline@ecc-dev.yourcompany.com?subject=A'
                  lv_wid_text
                  ' - Approve Document">APPROVE</a>&nbsp;&nbsp;'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<a href="mailto:eccoffline@ecc-dev.yourcompany.com?subject=R'
                  lv_wid_text
                  ' - Reject Document">REJECT</a>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
* Start DISCLAIMERS and WARNING Notifications
      CLEAR: body_text.
      CONCATENATE body_text
                  '<br><h4>Please Note: The links will send an e-mail via MICROSOFT OUTLOOK.'
                  'Please do not change the subject, body or any information in that e-mail.</h4>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<h4>MICROSOFT Outlook must be installed in your system.</h4>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<span style="color:#FF0000">' "This is color for RED. Browser Safe colors mandatory to prevent broswer crash.
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '<h4> <style="color: red"> CAUTION! Please do not reply to this e-mail.'
                  'For approval via e-mail, please click the links provided only. </h4></br>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '</span>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
      CLEAR: body_text.
      CONCATENATE body_text
                  '</body></html>'
                  INTO body_text.
      APPEND body_text TO text.
      wa_message-line = body_text.
      APPEND wa_message TO it_message.
      CLEAR: wa_message.
*--------------------------------------------------------------------*
* End of HTML Code Body
*--------------------------------------------------------------------*
* Calculate the Document Size
      CLEAR: lv_lines, lv_so_obj_len.
      DESCRIBE TABLE it_message LINES lv_lines.
      lv_so_obj_len = 255 * lv_lines.
* Create the Document
      document = cl_document_bcs=>create_document(
                      i_type    = 'HTM' "Send HTML E-Mail and not 'RAW'
                      i_text    = text
                      i_length  = lv_so_obj_len 
                      i_subject = 'E-Mail sent AFTER Work Item Creation' ).
*     Add document to send request
      CALL METHOD send_request->set_document( document ).
*     --------- set sender -------------------------------------------
*     note: this is necessary only if you want to set the sender
*           different from actual user (SY-UNAME). Otherwise sender is
*           set automatically with actual user.
      sender = cl_sapuser_bcs=>create( sy-uname ).
      CALL METHOD send_request->set_sender
        EXPORTING
          i_sender = sender.
*     --------- Add recipient (e-mail address) -----------------------
*     Create recipient - passing the e-mail ID here
      recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
*     Add recipient with its respective attributes to send request
      CALL METHOD send_request->add_recipient
        EXPORTING
          i_recipient = recipient
          i_express   = 'X'.
*     ---------- Send document ---------------------------------------
      CALL METHOD send_request->send(
        EXPORTING
          i_with_error_screen = 'X'
        RECEIVING
          result              = sent_to_all ).
*      IF sent_to_all = 'X'.
*        WRITE text-003.
*      ENDIF.
      COMMIT WORK.
* -----------------------------------------------------------
* *                     exception handling
* -----------------------------------------------------------
    CATCH cx_bcs INTO bcs_exception.
*      WRITE: text-001.
*      WRITE: text-002, bcs_exception->error_type.
*      EXIT.
  ENDTRY.
*--------------------------------------------------------------------*
* Another way to send e-mail in HTML via function module
*--------------------------------------------------------------------*
  CLEAR: w_doc_data.
  w_doc_data-sensitivty = 'F'. "Fill the document data and get size of attachment
  w_doc_data-doc_size   = lv_lines * 255. "Populate the subject/generic message attributes
  w_doc_data-obj_langu  = sy-langu.
  w_doc_data-obj_name   = 'SAPRPT'.
  w_doc_data-obj_descr  = 'E-Mail sent AFTER Work Item Creation'.
  CLEAR: wa_receivers.
  REFRESH: t_receivers[].
  wa_receivers-receiver   = lv_email. "Get requestor mail id from table PA0105 based on his PERNR.
  wa_receivers-rec_type   = 'U'.
  wa_receivers-com_type   = 'INT'.
  wa_receivers-notif_del  = 'X'.
  wa_receivers-notif_ndel = 'X'.
  APPEND wa_receivers TO t_receivers.
* Send the HTML E-Mail
  CALL FUNCTION 'SO_NEW_DOCUMENT_SEND_API1'
    EXPORTING
      document_data  = w_doc_data
      document_type  = 'HTM'   " To get the notification in HTML format
      commit_work    = 'X'
    TABLES
      object_content = it_message
      receivers      = t_receivers.
ENDMETHOD.

This completes our coding and configuration for our demo. We will now test our demo and see how it works.

Testing of the Offline Approval Demo

Running transaction SWUS to test the workflow with following parametersè

The work flow is triggered with work item ID 2735147 (Parent / Father Work Item)

The workflow log shownè

Now running SOST, we see the e-mail is triggered via the work item exit (there is no SEND MAIL step in our workflow)è

We push this e-mail from SOST (Not needed if SCOT Batch Job is set up)è

Message exits from SAP Connectè

Now checking in OUTLOOK Inbox, e-mail received at 08-FEB-2013; 3:41 PMè

The APPROVAL and REJECTION links in the e-mail will look as shownè

We click on APPROVE as of now, the following auto e-mail is generated. Notice that the “TO” field is auto populated with the ECC-OFFLINE approval ID.

The subject is a concatenation of the Processing Action (A = Approve) and the Work Item ID è

I am now clicking on SEND. I am not changing the SUBJECT or TO Field in this e-mail. This is crucial. I can see the e-mail is in the SENT ITEMS in OUTLOOK Web-Mailè

Now I am running the transaction SOIN for Inbound Send Requests (SMTP). This can also be substituted by Report RSBCSINè

I can see the e-mail has been received at SAP J. If you can see this, that your Inbound E-mail Configuration is correct. You have crossed a big hurdle here.

Display the trace of this e-mail (Note: I have activated TRACE in SCOT, this is mandatory to know what has happened in system)

The trace can be displayed from the SOIN screen. Notice the toolbar in that screen shot, the trace button is shownè  

<iframe id="aswift_2" style="position: absolute; top: 0px; left: 0px;" name="aswift_2" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="728" height="90"></iframe>

The trace screen opens as shown below (If trace is not active in SCOT, this screen will show no entries)è

Now the moment the e-mail was received by the system, our Inbound Exit should have triggered and processed the work item.

We can verify this from the trace. If we double click on the trace entry, it will show us all the details, our exit was instantiated and triggered as shown in the highlighted entries below. Also we can see that the RETURN Code was “0” which indicates that the method PROCESS_INBOUND was called correctlyè

So now we will check in SOST. We should see a reply from the Workflow System that the work item has been approved. This was processed in the method PROCESS_INBOUND coded in the Inbound Exit Class ZZZCL_PROCESS_INBOUND_WORKFLOWè

This e-mail was triggered by the Inbound Exit Class (notifying the processing). Displaying the e-mail bodyè

Checking the workflow log, the work item should have been processed as approvedè

BEFORE – Status IN PROCESS

AFTER – Status COMPLETED and action outcome is APPROVED

(Note the work item was not processed manually in Business Workplace SBWP, but was processed in the Inbound Exit Class via function module SAP_WAPI_DECISION_COMPLETE. Please study the code in method PROCESS_INBOUND in class ZZZCL_PROCESS_INBOUND_WORKFLOW. So you can process any code, transaction, etc offline via e-mail using this concept. Simply create specific SUBJECT line in the auto e-mail and model your code on that)

Above work item is also removed from SBWP (Business Workplace)è

Checking in OUTLOOK, we should have received the e-mailè

The OUTLOOK E-mail as seen in outlook. So the effect is; the moment the approver clicked on APPROVE link in the first Workflow Notification HTML e-mail, a few seconds later he receives a system e-mail informing him of the action carried out and stating the success.è

We open the e-mail to see the details and also to verify if the e-mail opens OKè

<iframe id="aswift_2" style="position: absolute; top: 0px; left: 0px;" name="aswift_2" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="728" height="90"></iframe>

Now what happens if the user clicks on APPROVE or REJECTED link on the approval e-mail again?

The work item will not be re-processed or processed multiple times. The system will receive the e-mail and send a notification back to user that the work item was already processed.

(You can design your own system response and code to handle this case where the approver might click on the links multiple times and send multiple e-mails to the system. The system will always process the first e-mail it receives on a first-come-first-served basis)

Let us see how this works. User clicks on REJECT link on the System Notification e-mail. This process the user does after he has already clicked on ‘APPROVE’ and has sent the auto e-mail to the SAP System. The concerned work item has already been processed as APPROVED so system cannot process it again. Hence system should inform this to the userè

On clicking REJECT, we get the below e-mail, notice that the work item ID is same as before of the already approved item.

The e-mail is sent by Outlook and received by the SAP system as shown, highlighted in YELLOWè

The e-mail BODY is shown belowè

Now the Inbound Exit will trigger again and find that this item is already processed, so system will send back the notification e-mail. Notice that the system response is very fast. The system received the e-mail at time 03:15:41 and sends the auto reply at 03:15:41 (see SOIN and SOST screen shot). This is because in this case, it did not need to spend time to process the work item, which has already been processed by the first e-mailè

Displaying the body of the e-mailè

Checking the e-mail in OUTLOOKè

The e-mail is opened to check the contents and validate if it opens correctlyè

We have successfully processed a work item via e-mail without logging into SAP System. We also managed to get the system respond to the e-mails and do the desired processing and reply back with the correct status. We did not require SAP GUI to do any processing. Also SAP Login ID and Password was not needed to do the Workflow Processing..

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics