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

<body><p class="Section1">In blog part one I demonstrated how to configure Duet Workflow Template for Time Approval scenario in SAP. In this section, I am going to show you examples on how to implement outbound and inbound custom handlers. </p>  <p>Custom handlers are function modules that you can use to influence the outbound and inbound processing of Outlook approval objects. SAP has provided default custom handlers for Duet Workflow Template 1.0. You can use directly the default custom handlers - S_OSP_WF_PAT_DEFAULT_CH_OB and S_OSP_WF_PAT_DEFAULT_CH_IB. The SAP-Outlook approval round trip process will work with that. But you will not have much on the approval email/task body. So if you want to add more business content to the approval email body and have your own formatting, you should create your own outbound custom handler. Your custom handlers can be added on top of the SAP default custom handlers. This was demonstrated in blog part one during the Duet Workflow Template configuration. </p>  <p>The way to create custom handlers is to mimic the SAP default custom handlers. Other than the Time Approval workflow example I am talking about here. I will provide another example source code for outbound custom handler at the end of this blog. </p>  <p>So the main functions of the outbound custom handler can be summarized as below:</p>  <ul><li><div class="Section1">Handle Outlook object content information, such as email / task subject and body. This will decide what information you want to present to the approvers and how you want to display them. </div></li>  <li><div class="Section1">Pass information to Outlook object to be rendered in action panel region. Action panel region in Duet is designed to display information such as business object header information, system message and workflow road-map etc. In additional to that, you can add business information by coding the outbound custom handler. For example, in time approval you might want to display what employee group the requestor belongs to, whether he/she is a permanent employee or a contractor. In the future release, you might be able to include a link to analytical report which will help manager makes decision against the request.</div></li></ul>  <p>For the inbound custom handler, the SAP default custom handler will do the following.</p>  <ul><li><div class="Section1">Update workflow container with decision and business information</div></li></ul>  <p>You can develop your own inbound custom handler to do follow-up activities such as:</p>  <ul><li>Implement application logic based on decision from approver. For example, release purchase requisition by calling specific function module, based on the decision received.</li></ul><p class="Section1"> </p><ul><li>Trigger additional workflow. For instance, in my time approval example, I triggered a second approval workflow for requestor to approve or reject the manager decision. Case agree, employee will go ahead to change the problem time entries. Case reject, employee will keep the same time entries, a notification email will be sent to the manager. OK. Let's see how we can do these in our time approval example.</li></ul>   <h3 class="Section1">1. Handling Approval Email Body</h3><div class="Section1">There are two options to handle the approval email body. </div>  <ul><li><div class="Section1">Use SAP standard text. This is simple but only gives you text email body.</div></li></ul>  <ul><li><div class="Section1">Create a XSLT mapping in SAP and generate a HTML email body from SAP. Really, is this possible? Yes. You may be surprised on how much SAP ABAP can do. </div></li></ul>  <div class="Section1">Below is the screenshot of HTML email body for Duet time approval. It was generated using option two. The email is well formatted and the time entries are organized in a HTML table structure by dates. The good thing is you can easily change the formatting by changing the XSLT mapping. So let's go through the process step by step. </div>  <div class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image001b2.png|height=405|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image001b2.png|border=0! </div>  <div class="Section1">First of all I need to decide how I want to display approval information in the email body. This can be done by using a XML schema. It is not necessary to use a XML schema, as long as you know what to do when you generate a XML structure in ABAP code. But a XML schema can help you see the big picture of the email body and reduce error while generating the XML structure in ABAP coding. </div>  <p class="Section1">Below is the XML schema I used for the Time Approval Email body. This is a simple XML schema. The root element is duet -> workflow -> timeApproval. Under the root element, I defined two simple elements to capture employee name and time entry period. Under the same root element, I defined a table structure to fill in time entry values such as document number, time entry number, activity description, and activity type. </p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image002b2.png|height=361|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image002b2.png|border=0! </p>  <p class="Section1">Secondly, with the defined schema, I went to transaction “STRANS” in SAP to create a transformation XSLT for Time Approval. </p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image003b2.png|height=278|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image003b2.png|border=0! </p>  <p class="Section1">The key here is to define a HTML structure following the XML schema, and retrieve the data value by using XSL code such as <xsl:value-of select="employeeName"/>. “employeeName” is the XML data structure that I will create later in an ABAP function module.</p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/rsz_image001.jpg|height=500|alt=image|width=700|src=https://weblogs.sdn.sap.com/weblogs/images/38003/rsz_image001.jpg|border=0! </p>  <p>Thirdly, I created a function module to generate the HTML data string. The below ABAP code inside the function module creates the XML root structure according to the Time Approval XML schema.  </p>  <p><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image005b2.png|height=255|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image005b2.png|border=0! </p>  <p>I then retrieved the employee name and time entry period and continued to create the two simple elements - employee name and time entry period.</p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image006b2.png|height=349|alt=image|width=500|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image006b2.png|border=0! </p>  <p class="Section1">Similarly, I created the time entries table structure with all the time entries values defined in the XML schema. </p>  <p><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image007b2.png|height=327|alt=image|width=450|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image007b2.png|border=0! </p>  <p class="Section1">The above ABAP coding will generate XML stream. Last I need to covert the XML stream to HTML string by using the XSLT transformation file I created earlier. This is done by using the below example coding. The result HTML string is now in the data structure called “ls_body_text”. </p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image008b2.png|height=231|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image008b2.png|border=0! </p>  <p class="Section1">All the ABAP coding was included in an ABAP function module called “Z_TIME_APPROVAL_APP_CONTENT”. The outbound custom handler Z_TIME_APPROVAL_CH_OB will call this function module and populate the email body with the result HTML string, which will be sent to Outlook as the approval email body.</p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image009b2.png|height=188|alt=image|width=500|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image009b2.png|border=0! </p><h3 class="Section1">2. Add Business Data to Action Panel</h3><div class="Section1">The Duet Workflow  Approval Details action panel region displays  business information that helps approvers make their decision. </div>  <div class="Section1">By default, the region is used to display information from workflow container. Such as Requester name and Submitted on date etc.</div>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image010b2.png|height=370|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image010b2.png|border=0! </p>  <div class="Section1">But you can include extra business information  in the action panel by passing the data via a special data structure called XPROP in the outbound custom handler. Inside the custom handler function module, what you need to do is to define the name of the data you want to display in the action panel region. Then you retrieve the value of the data and fill the name-value pair of the XPROP table. You can populate multiple name-value pairs in the XPROP structure. </div>  <div class="Section1">Later in Duet Workflow Outlook UI configuration tool, you define how you want to position and display the XPROP value. I am going to cover that in blog part three. The filling of XPROP value will be done in outbound custom handler. Below is the the example code from my Time Approval outbound custom handler.</div>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image011b2.png|height=58|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image011b2.png|border=0! </p>  <p class="Section1">The XPROP structure is as below.</p>  <p class="Section1"><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image012b2.png|height=243|alt=image|width=640|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image012b2.png|border=0! </p>  <h3 class="Section1">3. Trigger New Workflow from Inbound Custom Handler</h3><div class="Section1">Now that I have covered outbound custom handler, next I am going to talk about inbound custom handler. </div>  <div class="Section1">The main purpose of inbound custom handler is to pass approver decision and updated XPROP data from Outlook to SAP workflow container. But of course you can do more, it is a function module. </div>  <div class="Section1">In my Time Approval example, I used an inbound custom handler to trigger a new workflow. The new workflow will send approval email to requestor, in case of manager rejects the time entries. If the requestor agrees with the manager, he/she will go ahead and change the time entries. The changed time entries will be collected and sent to manager again upon the next run of the time approval batch job (The time approval batch job was explained in blog part one). If requestor doesn’t agree, he/she will keep the same time entries. A notification email with requestor note can then be sent to the manager for more explanation. </div>  <div class="Section1">Below is the example code in the inbound custom handler to trigger the new approval workflow for requestor. </div>  <p><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image013b2.png|height=400|alt=image|width=304|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image013b2.png|border=0! </p>  <p>That is pretty much I want to cover for the Duet Workflow Template Outbound and Inbound custom handlers. In blog part three I am going to define the Outlook Approval email UI, by using the Duet Workflow Template Configuration Tool. The tool is an add-in to Visual Studio 2005. It will be interesting to see how it integrates SAP to Microsoft after all the above SAP configuration and coding.</p>  <div class="Section1">Below is another example of outbound custom handler that I promised earlier in the blog. </div>  <p><img  />//weblogs.sdn.sap.com/weblogs/images/38003/image014b2.png|height=348|alt=image|width=350|src=https://weblogs.sdn.sap.com/weblogs/images/38003/image014b2.png|border=0! </p>  <p><img  /></body>