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 '
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> '
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..
相关推荐
/opt/nessus/sbin/nessuscli fetch --register-offline nessus.license Windows C:\\Program Files\\Tenable\\Nessus\\nessuscli.exe fetch --register-offline nessus.license macOS /Library/Nessus/run/sbin/...
opencv-3.4.4-android-sdk/apk opencv-3.4.4-android-sdk/LICENSE opencv-3.4.4-android-sdk/README.android opencv-3.4.4-android-sdk/samples
MeterSphere 是一站式开源持续测试平台,覆盖测试管理、接口测试、性能测试等。...metersphere-offline-installer-v1.19.1-arm64.part3.rar https://download.csdn.net/download/weixin_43800734/85093040
MeterSphere 是一站式开源持续测试平台,覆盖测试管理、接口测试、性能测试等。...metersphere-offline-installer-v1.19.1.part3.rar https://download.csdn.net/download/weixin_43800734/85092975
MeterSphere 是一站式开源持续测试平台,覆盖测试管理、接口测试、性能测试等。...metersphere-offline-installer-v1.19.1.part3.rar https://download.csdn.net/download/weixin_43800734/85092975
MeterSphere 是一站式开源持续测试平台,覆盖测试管理、接口测试、性能测试等。...metersphere-offline-installer-v1.19.1-arm64.part3.rar https://download.csdn.net/download/weixin_43800734/85093040
MeterSphere 是一站式开源持续测试平台,覆盖测试管理、接口测试、性能测试等。...metersphere-offline-installer-v1.19.1-arm64.part3.rar https://download.csdn.net/download/weixin_43800734/85093040
Android studio离线组件最新版本的 Google Maven 依赖项offline-gmaven-stable,文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Android studio离线组件offline-gmaven-stable.part1.rar ...
MeterSphere 是一站式开源持续测试平台,覆盖测试管理、接口测试、性能测试等。...metersphere-offline-installer-v1.19.1.part3.rar https://download.csdn.net/download/weixin_43800734/85092975
Android studio离线组件最新版本的 Google Maven 依赖项offline-gmaven-stable,文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Android studio离线组件offline-gmaven-stable.part1.rar ...
Android studio离线组件最新版本的 Google Maven 依赖项offline-gmaven-stable,文件分割成 三个 压缩包,必须集齐 三个 文件后才能一起解压一起使用: Android studio离线组件offline-gmaven-stable.part1.rar ...
很详细的ROS-L7教程,使用效果很好,自己就能做流控了
官方地址 https://github.com/vmware/harbor/releases/download/v1.2.0/harbor-offline-installer-v1.2.0.tgz,可以先尝试从官方下载,如果中断或者下载失败,可以下载此版本...harbor-offline v1.2.0 避免龟速下载安装
[myeclipse.10.0.更新发布(破解更新)].MyEclipse10cr.rar 附详细操作及说明 适合于MyEclipse 9/10.0,具体看详细操作说明吧 ... 另附MyEclipse 10.0 正式版(For Windows)其它各个版本的下载地址,无法下载的话,...
(Realtek RTL8111B / RTL8168B / RTL8111/RTL8168 / RTL8111C / RTL8111CP / RTL8111D(L) / RTL8168C / RTL8111DP / RTL8111E / RTL8168E / RTL8111F / RTL8411 / RTL8111G / RTL8111GUS / RTL8411B(N) / RTL8118AS ...
m_Name[3] = 'E'; // ----- m_nPort = 00000; m_hCmport = 0; m_nThreadCount = 0; m_AddedCount = 0; m_DelaySNet = 100; m_Listen = INVALID_SOCKET; // ----- for(int i = 0; i != MAX_OBJECT; ...
ros qtcreator plugin 离线安装包,外网下载速度很慢。 本篇博客主要用来记录ubuntu 16.04下配置ROS Qt Creator Plugin的过程。 https://blog.csdn.net/Bing_Lee/article/details/115221346
kaldi-offline-transcriber-nextflow 基于Nextflow的语音处理 用法 首先构建容器:docker build。 -t nextflow:最新 启动一个容器(名称为“ nextflow”)并将其置于后台( -d )。 另外,将本地目录~/tmp/...
myeclipse.10.0.更新发布(破解更新).myeclipse10.0_key.gen ... 适合于MyEclipse 10.0,具体看详细操作说明吧......... ...另附MyEclipse 10.0 正式版(For Windows)其它各个版本的下载地址,无法下载的话,自己想办法去,...
dropbox的最新离线安装版,windows系统软件,最强云同步工具.