Build an Advanced Document Workflow

Overview

The purpose of this tutorial is to:

  • Help clients with little or no programmer resources to gain expertise in developing lightweight complex department-wide workflows
  • Help clients to move from a paper-based form paradigm to an electronic form paradigm
  • Help clients to progress to building workflows that facilitate complex business processes.

In this tutorial we will use eDocLite to facilitate a business process called Request Firewall Change which is owned by IET Application Development. This time the process involves more responsible parties and more levels of decision making (yikes!!!).

Instead of creating Users and Work Groups ourselves, we will leave that task to the administrators of the identity management system. We can expect all Users to already be present in the system. Work Groups can be specific to workflows, so we can expect to request that these be created by the system administrators.

Also, instead of expanding on the workflow in the Simple Document Workflow tutorial, we will build a brand new workflow. Whereas the previous tutorial has a "get-your-feet-wet" flavor, we will give this one the "little-fish-in-the-big-pond" treatment. This means we will act as though there are several departments (tens of or hundreds of) at UCD who are already using eDocLite for all kinds of document workflows and therefore, we must use naming conventions that will prevent our work from colliding with other departments' work and do so without confusing us at the same time.

In this case, there may be several other departments who:

  • administer their own firewalls
  • have a "Firewall Request Change" process that differs from IET Application Development's process
  • have work groups that have the same name as IET's work groups, but may or may not have the same responsibilities

We will employ a development cycle that closely follows the eDocLite dependency hierarchy:

Naming Conventions

Workflow Component

Naming Convention

Parent Document Type

<namespace>.<workflow name>.ParentDocType

Child Document Type

<namespace>.<workflow name>.ChildDocType

eDocLite Form Definition

<namespace>.<workflow name>.Form

Rule Attribute

<namespace>.<workflow name>.<rule attribute name>.RuleAttribute

Rule Template

<namespace>.<workflow name>.<rule template name>.RuleTemplate

Rule

<namespace>.<workflow name>.<rule name>.Rule

XML Files

Naming Convention

Parent Document Type

<namespace>.<workflow name>.ParentDocType.xml

Child Document Type

<namespace>.<workflow name>.ChildDocType.xml

eDocLite Form

<namespace>.<workflow name>.Form.xml

Rule Attributes

<namespace>.<workflow name>.RuleAttributes.xml

Rule Templates

<namespace>.<workflow name>.RuleTemplates.xml

Rules

<namespace>.<workflow name>.Rules.xml

Development Cycle

  1. Model the Business Process
  2. Model the Form Details
  3. Model the Document Workflow
  4. Create Validation Checklists
  5. Procure Work Groups
  6. Create Workflow Components
    • Create the Parent Document Type
    • Create the Child Document Types
    • Create the eDocLite Form
      • Create the Definition
      • Create the Stylesheet
    • Create Rule Attributes
    • Create Rule Templates
    • Create Rules
  7. Implement Workflow Components
  8. Simulate the Business Process

Model the Business Process

This time there are four responsible parties: Requester, Desktop Services, Firewall Policy Group, and Firewall Gatekeeper
Here is a breakdown of each parties responsibilities:

Requester

  1. Submits the request just as in the previous tutorial.
  2. Is now allowed to specify if the request is urgent.

Desktop Services

  1. Field all submitted requests.
  2. Check if the requested firewall configuration is already in effect.
  3. If so, cancel or deny the request. Otherwise,
    • forward urgent requests to the Firewall Gatekeeper.
    • forward non-urgent requests to the Firewall Policy Group.

Firewall Policy Group

  1. Review requests and decide if they meet policy.
  2. Forward approved non-urgent requests to the Firewall Gatekeeper.
  3. Forward disapproved urgent requests to the Firewall Gatekeeper.

Firewall Gatekeeper

  1. Implement urgent requested firewall configurations immediately.
  2. If disapproved by the Firewall Policy Group afterward, reverse firewall configuration.
  3. Implement non-urgent requests upon approval of the Firewall Policy Group.

We documented the Review Non-Urgent Request and Review Urgent Request as subprocesses because there is potential for the members of the Firewall Policy Group to have continuous correspondence with each other and with the Requester. At this point, it is not clear how we will address these subprocesses, since there is no document routing going on during the rounds of correspondence.

Model the Form Details

As part of the process, the Firewall Policy Group requires that anyone who wants the firewall rules modified must provide the following details:

Request Detail

Detail Style

Example

Date of change

Date in MM/DD/YYYY format

11/01/2010

Description of the port change

Descriptive blurb

Allow all workstations of the Application Development group access to the Oracle database port

Ingress/egress characteristic

Descriptive blurb

Incoming on port 1521

Source specification

Descriptive blurb

wk1.ucdavis.edu, wk2.ucdavis.edu, wk3.ucdavis.edu

Destination specification

Descriptive blurb

dbhost.ucdavis.edu

The term of the change (indefinite or otherwise)

One-liner

Indefinite

Project(s) related to the requested rule(s) change

Descriptive blurb

Kuali Rice Implementation

Urgent?

Pick either YES or NO

NO

Additionally, we want to add other detail as the process moves along:

Detail

Detail Style

Example

By Desktop Services:



Configuration is already in effect?

Pick either YES or NO

NO




By Firewall Policy Group:



Reason for disapproval

Descriptive Explanation

This request did not reflect urgency because of Reason A, Reason B, and Reason C.

Model the Document Workflow

Here is the document workflow diagram based on our business process. In it, we want to represent:

  • The path that the Request Firewall Change document must take in order to yield a successful lifecycle. This is the route path.
  • The various steps in the route path. Each step is called a route node.
  • The responsible party or parties who take action on each node. These are either persons, workgroups, or roles.
  • The rule scheme applied to each node. These schemes are comprised of rule templates, rule attributes and rules.

Let's lay down a few ground rules about the notation:

Element

Ground Rule

Request

The first route node, a.k.a. the start node, in the workflow's route path. This is where the Request Firewall Change document is created by an initiator.

Purple "Document"

A node in the route path. Each node represents a point in the business process where a responsible party is viewing (and possibly editing) the Request Firewall Change document.

Lavender Parallelogram

A rule template that is applied to each node. Each rule template is associated with a set of rules and rule attributes.

Orange Sail

A rule attribute associated with a rule template.

Lime Rectangle

The responsible party or parties who take action on a node.

Red Arrow

The action that must be taken to get from one node to the next node.

Blue Join Line

When connected to a rule attribute, it represents a rule that evaluates that rule attribute

Finish

Means the workflow has completed with flying colors.

Create Validation Checklists

Let's build a checklist that the QA team can use to validate the above simulation:

Requested Node

Current Status

Action

Taken By

New Status

Request

INITIATED

Fill out form, set URGENT to NO, click route

requester1

ENROUTE

ReviewCurrentConfiguration

ENROUTE

Click approve

DES1

ENROUTE

InitialApproval

ENROUTE

Click approve

FPG1

ENROUTE

FinalApproval

ENROUTE

Click approve

DCCS1

PROCESSED

AcknowledgeConfiguration

PROCESSED

Click acknowledge

requester1

FINAL

Let's build another one for urgent requests:

Requested Node

Current Status

Action

Taken By

New Status

Request

INITIATED

Fill out form, set URGENT to YES, click route

requester1

ENROUTE

ReviewCurrentConfiguration

ENROUTE

Click approve

DES1

ENROUTE

InitialApproval

ENROUTE

Click approve

DCCS1

ENROUTE

FinalApproval

ENROUTE

Click approve

FPG1

PROCESSED

AcknowledgeConfiguration

PROCESSED

Click acknowledge

requester1

FINAL

And another one for non-urgent requests that are disapproved:

Requested Node

Current Status

Action

Taken By

New Status

Request

INITIATED

Fill out form, set URGENT to NO, click route

requester1

ENROUTE

ReviewCurrentConfiguration

ENROUTE

Click approve

DES1

ENROUTE

InitialApproval

ENROUTE

Click disapprove

FPG1

DISAPPROVED

AcknowledgeConfiguration

DISAPPROVED

Click acknowledge

requester1

DISAPPROVED

Procure Roles

Looking at our workflow diagram, we build a responsibility matrix documenting who should act on which node and what action we're requesting of them. We'll use this later when we build our set of rules.

Node

Responsible Party

Responsibility Condition(s)

Action Requested

Request

Initiator (whoever creates the document)

none

SUBMIT

Review Current Configuration

IET DES Development Support

anyone, any request

APPROVE

Initial Approval

IET PSL Firewall Policy Group

everyone, non-urgent request

APPROVE

Initial Approval

IET DCCS Firewall System Administrator

first one, urgent request

APPROVE

Final Approval

IET PSL Firewall Policy Group

everyone, non-urgent request

APPROVE

Final Approval

IET DCCS Firewall System Administrator

first one, urgent request

APPROVE

Acknowledge Configuration

Initiator

none

ACKNOWLEDGE

After going through the easy and expedient process of requesting work groups, the Kuali Rice administrator has notified us that the following roles are available for use in our workflow:

Responsible Party

Work Group

Requester

Initiator.Role.RuleAttribute

Desktop Services

edu.ucdavis.iet.des.DevelopmentSupport

Firewall Policy Group

edu.ucdavis.iet.adda.FirewallPolicyGroup

Firewall Gatekeeper

edu.ucdavis.iet.dccs.FirewallSysAdmin

Super User Workgroup

edu.ucdavis.iet.adda.KualiRiceSysAdmin

Default Exception Workgroup

edu.ucdavis.iet.KualiRiceSysAdmin

Notice that the Kuali Rice Administrator identified edu.ucdavis.iet.KualiRiceSysAdmin even though that role is not involved in our business process. We'll need to identify a Super User Role and Default Exception Role when we create Document Types. In production, these work groups could potentially be the process owners, or department system administrators, rather than IET system administrators.

Create the Parent Document Type

Here we create a Parent Document Type that defines the behavior of all Request Firewall Change documents. This particular parent document type defines everything short of routing paths. The idea is to allow for a hierarchy of child document types that inherit attributes of their parents.

RequestFirewallChange.eDoc.ParentDocType.xml
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="ns:workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ns:workflow resource:WorkflowData">
<documentTypes xmlns="ns:workflow/DocumentType" xsi:schemaLocation="ns:workflow/DocumentType resource:DocumentType">
	<documentType>
		<name>RequestFirewallChange.eDoc.ParentDocType</name>
		<description>Request Firewall Change eDocLite Parent Document Type</description>
		<label>Request Firewall Change eDocLite Parent Document Type</label>
		<blanketApprovePolicy>NONE</blanketApprovePolicy>
		<docHandler>${workflow.url}/EDocLite</docHandler>
		<active>true</active>
		<routingVersion>2</routingVersion>
	</documentType>
</documentTypes>
</data>

Create the Child Document Type

Here we create a Child Document Type that identifies the route path and route nodes based on our workflow diagram.

First, we build a table documenting the routePath, the routeNodes and the ruleTemplate applied to each node:

Node Name

nextNode

ruleTemplate

Request (the Start Node)

ReviewCurrentConfiguration

RequestFirewallChange.eDoc.ReviewCurrentConfiguration.RuleTemplate

ReviewCurrentConfiguration

InitialApproval.Node

RequestFirewallChange.eDoc.InitialApproval.RuleTemplate

InitialApproval

FinalApproval.Node

RequestFirewallChange.eDoc.FinalApproval.RuleTemplate

FinalApproval

AcknowledgeConfiguration.Node

RequestFirewallChange.eDoc.AcknowledgeConfiguration.RuleTemplate

AcknowledgeConfiguration

none, since the workflow is done

none

The resulting XML looks like so:

RequestFirewallChange.eDoc.ChildDocType.xml
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="ns:workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ns:workflow resource:WorkflowData">
<documentTypes xmlns="ns:workflow/DocumentType" xsi:schemaLocation="ns:workflow/DocumentType resource:DocumentType">
	<documentType>
		<name>RequestFirewallChange.eDoc.ChildDocType</name>
		<parent>RequestFirewallChange.eDoc.ParentDocType</parent>
		<description>Request Firewall Change eDocLite Child Document Type</description>
		<label>Request Firewall Change eDocLite Child Document Type</label>
		<postProcessorName>edu.iu.uis.eden.edl.EDocLitePostProcessor</postProcessorName>
		<superUserWorkgroupName>ucd.IET.AppDev.KualiRice.SysAdmin.Workgroup</superUserWorkgroupName>
		<defaultExceptionWorkgroupName>ucd.IET.AppDev.KualiRice.SysAdmin.Workgroup</defaultExceptionWorkgroupName>
		<docHandler>${workflow.url}/EDocLite</docHandler>
		<active>true</active>
		<routingVersion>2</routingVersion>
		<routePaths>
			<routePath>
          			<start name="Request" nextNode="ReviewCurrentConfiguration" />
		          	<requests name="ReviewCurrentConfiguration" nextNode="InitialApproval" />
				<requests name="InitialApproval" nextNode="FinalApproval" />
				<requests name="FinalApproval" nextNode="AcknowledgeConfiguration" />
				<requests name="AcknowledgeConfiguration" />
        	      </routePath>
		</routePaths>
	      <routeNodes>
			<start name="Request">
				<activationType>P</activationType>
			</start>
			<requests name="ReviewCurrentConfiguration">
				<activationType>P</activationType>
				<ruleTemplate>RequestFirewallChange.eDoc.ReviewCurrentConfiguration.RuleTemplate</ruleTemplate>
			</requests>
			<requests name="InitialApproval">

				<activationType>P</activationType>
				<ruleTemplate>RequestFirewallChange.eDoc.InitialApproval.RuleTemplate</ruleTemplate>
			</requests>
			<requests name="FinalApproval">
				<activationType>P</activationType>
				<ruleTemplate>RequestFirewallChange.eDoc.FinalApproval.RuleTemplate</ruleTemplate>
			</requests>		
			<requests name="AcknowledgeConfiguration">
				<activationType>S</activationType>
				<ruleTemplate>RequestFirewallChange.eDoc.AcknowledgeConfiguration.RuleTemplate</ruleTemplate>
				<mandatoryRoute>false</mandatoryRoute>
				<finalApproval>false</finalApproval>
			</requests>
		</routeNodes>
	</documentType>
</documentTypes>
</data>

Create the eDocLite Form

First, we build a table documenting the fieldDefs (field definitions) based on the request details required by our process.

Field Name

Title

Type

Rule Attribute

Validation Rule(s)

dateOfChange

Date of Change

text

none

  1. required
  2. format: MM/DD/YYYY

descriptionOfChange

Description of the Port Change

text area

none

required

isUrgent

URGENT

select

RequestFirewallChange.eDoc.isUrgent.RuleAttribute

required

ingressEgressCharacteristic

Ingress/Egress Characteristic

text area

none

required

sourceSpecification

Source Specification

text

none

required

destinationSpecification

Destination Specification

text

none

required

termOfRuleChange

Term of Rule Change (indefinite or otherwise)

text

none

required

relatedProject

Project Related to Requested Rule(s) Change

text

none

required

Now we build the data entry form:

  1. The eDocLite Form Skeleton
    The Form Skeleton is the structure of the entire eDocLite form minus the Form Definition and Form Stylesheet. We separate this out so that you can use it as a base template for all of your eDocLite forms. This particular skeleton follows the scheme of the out-of-the-box Kuali Rice forms. The scheme uses the same look and feel and makes calls to the eDocLite widgets on the Kuali Rice server.
    RequestFirewallChange.eDoc.Form.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <data xmlns="ns:workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ns:workflow resource:WorkflowData">
    <edoclite xmlns="ns:workflow/EDocLite" xsi:schemaLocation="ns:workflow/EDocLite resource:EDocLite">
      
    	<edl name="RequestFirewallChange.eDoc.Form" title="Request Firewall Change">
    		<security />
    		<createInstructions>** Fields with an asterisk are required.</createInstructions>
    		<instructions>** Fields with an asterisk are required.</instructions>
    		<validations />
    		<attributes />
    	        ...
    	        ...
    	</edl>
    
    	<style name="RequestFirewallChange.eDoc.Style">
    	<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my-class="xalan://edu.iu.uis.eden.edl.WorkflowFunctions" version="1.0">
    		<xsl:include href="widgets" />
    		<xsl:output indent="yes" method="html" omit-xml-declaration="yes" version="4.01" />
    		<xsl:variable name="actionable" select="/documentContent/documentState/actionable" />
    		<xsl:variable name="docHeaderId" select="/documentContent/documentState/docId" />
    		<xsl:variable name="editable" select="/documentContent/documentState/editable" />
    		<xsl:variable name="globalReadOnly" select="/documentContent/documentState/editable != 'true'" />
    		<xsl:variable name="docStatus" select="//documentState/workflowDocumentState/status" />
    		<xsl:variable name="isAtNodeInitiated" select="my-class:isAtNode($docHeaderId, 'Initiated')" />
    		<xsl:variable name="isPastInitiated" select="my-class:isNodeInPreviousNodeList('Initiated', $docHeaderId)" />
    		<xsl:variable name="isUserInitiator" select="my-class:isUserInitiator($docHeaderId)" />
    		<xsl:param name="overrideMain" select="'true'" />
            
    		<xsl:template name="mainForm">
    			<html xmlns="">
    			  <head>
    			  <script language="javascript" />
    			  <xsl:call-template name="htmlHead" />
    			  </head>
      			<body onload="onPageLoad()">
    			  <xsl:call-template name="errors" />
    			  <xsl:call-template name="header" />
    			  <xsl:call-template name="instructions" />
    		  	  <xsl:variable name="formTarget" select="'EDocLite'" />
    		          <form action="{$formTarget}" enctype="multipart/form-data" id="edoclite" method="post" onsubmit="return validateOnSubmit(this)">
    		  	    <xsl:call-template name="hidden-params" />
    		  	    <xsl:call-template name="mainBody" />
    		  	    <xsl:call-template name="notes" />
    		  	    <br />
    		  	    <xsl:call-template name="buttons" />
    		  	    <br />
    		  	  </form>
                              <xsl:call-template name="footer" />
        		  	</body>
        		       </html>
    		</xsl:template>
    
    		<xsl:template name="mainBody">
    			...
    			...
     		</xsl:template>
    
      		<xsl:template name="nbsp">
    			<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
    		</xsl:template>
    	</xsl:stylesheet>
    	</style>
    
    	<association>
    		<docType>RequestFirewallChange.eDoc.ChildDocType</docType>
    		<definition>RequestFirewallChange.eDoc.Form</definition>
    		<style>RequestFirewallChange.eDoc.Style</style>
        		<active>true</active>
      	</association>
    
    </edoclite>
    </data>
    

  2. Form Definition
    The Form Definition defines the data entry fields on the form. Our definitions define field display characteristics and field validations. Place your form definition between the <edl> and </edl> tags in the Form Skeleton.
    RequestFirewallChange.eDoc.Form.xml
        <fieldDef name="dateOfChange" title="Date and Time for Change: MM/DD/YYYY">
          <display>
            <type>text</type>
          </display>
          <validation required="true">
            <regex>^[0-1]?[0-9](/|-)[0-3]?[0-9](/|-)[1-2][0-9][0-9][0-9]$</regex>
            <message>Enter a valid date in the format mm/dd/yyyy.</message>
          </validation>
        </fieldDef>
    
        <fieldDef name="descriptionOfChange" title="Description of the Port Change">
          <display>
            <type>textarea</type>
            <meta>
              <name>rows</name>
              <value>5</value>
            </meta>
            <meta>
              <name>cols</name>
              <value>60</value>
            </meta>
            <meta>
              <name>wrap</name>
              <value>hard</value>
            </meta>
          </display>
          <validation required="true">
            <message>Enter a description of the port change.</message>
          </validation>
        </fieldDef>
    
        <fieldDef attributeName="RequestFirewallChange.eDoc.isUrgent.RuleAttribute" name="isUrgent" title="URGENT">
          <display>
            <type>select</type>
              <values title="NO">NO</values>
              <values title="YES">YES</values>
          </display>
          <validation required="true">
              <message>Is this request URGENT?</message>
          </validation>
        </fieldDef>
    
        <fieldDef name="ingressEgressCharacteristic" title="Ingress/Egress Characteristic">
          <display>
            <type>textarea</type>
            <meta>
              <name>rows</name>
              <value>5</value>
            </meta>
            <meta>
              <name>cols</name>
              <value>60</value>
            </meta>
            <meta>
              <name>wrap</name>
              <value>hard</value>
            </meta>
          </display>
          <validation required="true">
            <message>Enter the ingress/egress characteristic.</message>
          </validation>
        </fieldDef>
    
        <fieldDef name="sourceSpecification" title="Source Specification">
          <display>
            <type>textarea</type>
            <meta>
              <name>rows</name>
              <value>5</value>
            </meta>
            <meta>
              <name>cols</name>
              <value>60</value>
            </meta>
            <meta>
              <name>wrap</name>
              <value>hard</value>
            </meta>
          </display>
          <validation required="true">
            <message>Enter the source specification.</message>
          </validation>
        </fieldDef>
    
        <fieldDef name="destinationSpecification" title="Destination Specification">
          <display>
            <type>textarea</type>
            <meta>
              <name>rows</name>
              <value>5</value>
            </meta>
            <meta>
              <name>cols</name>
              <value>60</value>
            </meta>
            <meta>
              <name>wrap</name>
              <value>hard</value>
            </meta>
          </display>
          <validation required="true">
            <message>Enter the destination specification.</message>
          </validation>
        </fieldDef>
    
        <fieldDef name="termOfRuleChange" title="Term of Rule Change (indefinite or otherwise)">
          <display>
            <type>text</type>
            <meta>
              <name>size</name>
              <value>50</value>
            </meta>
          </display>
          <validation required="true">
            <message>Enter term of the rule change.</message>
          </validation>
        </fieldDef>
    
        <fieldDef name="relatedProject" title="Project Related to Requested Rule(s) Change">
          <display>
            <type>text</type>
            <meta>
              <name>size</name>
              <value>50</value>
            </meta>
          </display>
          <validation required="true">
            <message>Enter a related project to the requested rule change.</message>
          </validation>
        </fieldDef>
    

  3. Form Stylesheet
    The Form Stylesheet defines the layout of the form and renders the fields from our Form Definition onto the form. Our layout is an HTML table with a row for each field. In this case, we are customizing the mainBody piece of the stylesheet. In general, place your form stylesheet between the <style> and </style> tags in the Form Skeleton.
    RequestFirewallChange.eDoc.Form.xml
      <xsl:template name="mainBody">
        <table xmlns="" align="center" border="0" cellpadding="0" cellspacing="0" class="bord-r-t" width="80%">
          <tr>
            <td align="left" border="3" class="thnormal" colspan="1">
              <br />
              <h3>
                University of California, Davis
                <br />
                eDoclite Tutorial
    	  </h3>
              <br />
            </td>
            <td align="center" border="3" class="thnormal" colspan="2">
              <br />
              <h2>Request Firewall Change Form</h2>
            </td>
          </tr>
          <tr>
            <td class="headercell5" colspan="100%">
            <b>Request Details</b>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'dateOfChange'" />
                <xsl:with-param name="renderCmd" select="'title'" />
              </xsl:call-template>
              <font color="#ff0000">*</font>
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'dateOfChange'" />
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="readOnly" select="$isPastInitiated" />
              </xsl:call-template>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'descriptionOfChange'" />
                <xsl:with-param name="renderCmd" select="'title'" />
              </xsl:call-template>
              <font color="#ff0000">*</font>
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'descriptionOfChange'" />
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="readOnly" select="$isPastInitiated" />
              </xsl:call-template>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
              <xsl:with-param name="fieldName" select="'isUrgent'" />
              <xsl:with-param name="renderCmd" select="'title'" />
              </xsl:call-template>
              <font color="#ff0000">*</font>
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
              <xsl:with-param name="fieldName" select="'isURgent'" />
              <xsl:with-param name="renderCmd" select="'input'" />
              <xsl:with-param name="readOnly" select="$isPastInitiated" />
              </xsl:call-template>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'ingressEgressCharacteristic'" />
                <xsl:with-param name="renderCmd" select="'title'" />
              </xsl:call-template>
              <font color="#ff0000">*</font>
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'ingressEgressCharacteristic'" />
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="readOnly" select="$isPastInitiated" />
              </xsl:call-template>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'destinationSourceSpecification'" />
                <xsl:with-param name="renderCmd" select="'title'" />
    
              </xsl:call-template>
              <font color="#ff0000">*</font>
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'destinationSourceSpecification'" />
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="readOnly" select="$isPastInitiated" />
    
              </xsl:call-template>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'termOfRuleChange'" />
                <xsl:with-param name="renderCmd" select="'title'" />
              </xsl:call-template>
              <font color="#ff0000">*</font>
    
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'termOfRuleChange'" />
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="readOnly" select="$isPastInitiated" />
              </xsl:call-template>
            </td>
          </tr>
          <tr>
            <td class="thnormal">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'relatedProject'" />
                <xsl:with-param name="renderCmd" select="'title'" />
              </xsl:call-template>
              <font color="#ff0000">*</font>
            </td>
            <td class="datacell">
              <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="'relatedProject'" />
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="readOnly" select="$isPastInitiated" />
              </xsl:call-template>
            </td>
          </tr>
        </table>
        <br xmlns="" />
    <xsl:template>
    

Create Rule Attributes

Here we create a Rule Attribute that is associated with the isUrgent field in the form.

RequestFirewallChange.eDoc.RuleAttributes.xml
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="ns:workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ns:workflow resource:WorkflowData">
<ruleAttributes xmlns="ns:workflow/RuleAttribute" xsi:schemaLocation="ns:workflow/RuleAttribute resource:RuleAttribute">
	<ruleAttribute>
      	<name>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</name>
	      <className>edu.iu.uis.eden.routetemplate.xmlrouting.StandardGenericXMLRuleAttribute</className>
      	<label>Request Firewall Change Is Urgent Rule Attribute</label>
	      <description>Request Firewall Change Is Urgent Rule Attribute</description>
      	<type>RuleXmlAttribute</type>

      	<routingConfig>
        		<fieldDef name="isUrgent" title="URGENT" workflowType="ALL">
	          		<display>
            			<type>select</type>
            			<values title="NO">NO</values>
            			<values title="YES">YES</values>
             		</display>
          			<validation required="true" />
          			<fieldEvaluation>
            			<xpathexpression>//isUrgent = wf:ruledata('isUrgent')</xpathexpression>
          			</fieldEvaluation>
       		</fieldDef>
        		<xmlDocumentContent>
          			<isUrgent>%isUrgent%</isUrgent>
        		</xmlDocumentContent>
      	</routingConfig>
    </ruleAttribute>
</ruleAttributes>

</data>

Create Rule Templates

Here we create several Rule Templates that are applied to each route node.

First we document each ruleTemplate and any associated attributes:

Rule Template

Description

Attribute(s)

RequestFirewallChange.eDoc.ReviewCurrentConfiguration.RuleTemplate

Review Current Configuration RuleTemplate

none

RequestFirewallChange.eDoc.InitialApproval.RuleTemplate

Initial Approval RuleTemplate

RequestFirewallChange.eDoc.isUrgent.RuleAttribute

RequestFirewallChange.eDoc.FinalApproval.RuleTemplate

Final Approval RuleTemplate

RequestFirewallChange.eDoc.isUrgent.RuleAttribute

RequestFirewallChange.eDoc.AcknowledgeConfiguration.RuleTemplate

Acknowledge Configuration RuleTemplate

Initiator.Role.RuleAttribute

RequestFirewallChange.eDoc.RuleTemplates.xml
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="ns:workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ns:workflow resource:WorkflowData">
<ruleTemplates xmlns="ns:workflow/RuleTemplate" xsi:schemaLocation="ns:workflow/RuleTemplate resource:RuleTemplate">
	<ruleTemplate>
      		<name>RequestFirewallChange.eDoc.ReviewCurrentConfiguration.RuleTemplate</name>
      		<description>Review Current Configuration RuleTemplate</description>
	</ruleTemplate>
	<ruleTemplate>
      		<name>RequestFirewallChange.eDoc.InitialApproval.RuleTemplate</name>
      		<description>Initial Approval RuleTemplate</description>
      		<attributes>
        			<attribute>
          				<name>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</name>
          				<required>true</required>
        			</attribute>
      		</attributes>
	</ruleTemplate>
	<ruleTemplate>
      		<name>RequestFirewallChange.eDoc.FinalApproval.RuleTemplate</name>
      		<description>Final Approval RuleTemplate</description>
      		<attributes>
        			<attribute>
          				<name>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</name>
          				<required>true</required>
        			</attribute>
      		</attributes>
	</ruleTemplate>
	<ruleTemplate>
      		<name>RequestFirewallChange.eDoc.AcknowledgeConfiguration.RuleTemplate</name>
      		<description>Acknowledge Configuration RuleTemplate</description> 
			<attributes>
				<attribute>
					<name>Initiator.Role.RuleAttribute</name>
					<required>true</required>
				</attribute>
			</attributes>
	</ruleTemplate>
</ruleTemplates>
</data>

Create Routing Rules

Finally, we create Rules that are associated with RequestFirewallChange.eDoc.ChildDocType and its associated rule templates. We apply the responsibility matrix we created way above.

RequestFirewallChange.eDoc.Rules.xml
<?xml version="1.0" encoding="UTF-8"?>
<data xmlns="ns:workflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ns:workflow resource:WorkflowData">
<rules xmlns="ns:workflow/Rule" xsi:schemaLocation="ns:workflow/Rule resource:Rule">
	<rule>
      		<documentType>RequestFirewallChange.eDoc.ChildDocType</documentType>
      		<ruleTemplate>RequestFirewallChange.eDoc.ReviewCurrentConfiguration.RuleTemplate</ruleTemplate>
      		<description>Review Current Configuration Rule</description>
      		<ignorePrevious>false</ignorePrevious>
      		<responsibilities>
        		<responsibility>
          			<workgroup>ucd.IET.DES.DevelopmentSupport.WorkGroup</workgroup>
          			<actionRequested>A</actionRequested>
          			<priority>1</priority>
        		</responsibility>
      		</responsibilities>
    	</rule>
	<rule>
      		<documentType>RequestFirewallChange.eDoc.ChildDocType</documentType>
      		<ruleTemplate>RequestFirewallChange.eDoc.InitialApproval.RuleTemplate</ruleTemplate>
      		<description>Initial Approval By Firewall SysAdmin Rule</description>
      		<ignorePrevious>false</ignorePrevious>
      		<ruleExtensions>
        			<ruleExtension>
         	 			<attribute>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</attribute>
          				<ruleTemplate>RequestFirewallChange.eDoc.InitialApproval.RuleTemplate</ruleTemplate>
          				<ruleExtensionValues>
            					<ruleExtensionValue>
              						<key>isUrgent</key>
              						<value>YES</value>
            					</ruleExtensionValue>
          				</ruleExtensionValues>
        			</ruleExtension>
	      	</ruleExtensions>
      		<responsibilities>
        		<responsibility>
          			<workgroup>ucd.IET.DCCS.FirewallSysAdmin.Workgroup</workgroup>
          			<actionRequested>A</actionRequested>
          			<priority>1</priority>
        		</responsibility>
      		</responsibilities>
    	</rule>
	<rule>
      		<documentType>RequestFirewallChange.eDoc.ChildDocType</documentType>
      		<ruleTemplate>RequestFirewallChange.eDoc.InitialApproval.RuleTemplate</ruleTemplate>
      		<description>Initial Approval By Firewall Policy Group Rule</description>
      		<ignorePrevious>false</ignorePrevious>
      		<ruleExtensions>
        			<ruleExtension>
         	 			<attribute>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</attribute>
          				<ruleTemplate>RequestFirewallChange.eDoc.InitialApproval.RuleTemplate</ruleTemplate>
          				<ruleExtensionValues>
            					<ruleExtensionValue>
              						<key>isUrgent</key>
              						<value>NO</value>
            					</ruleExtensionValue>
          				</ruleExtensionValues>
        			</ruleExtension>
	      	</ruleExtensions>
      		<responsibilities>
        		<responsibility>
          			<workgroup>ucd.IET.AppDev.FirewallPolicyGroup.Workgroup</workgroup>
          			<actionRequested>A</actionRequested>
          			<priority>1</priority>
        		</responsibility>
      		</responsibilities>
    	</rule>
	<rule>
      		<documentType>RequestFirewallChange.eDoc.ChildDocType</documentType>
      		<ruleTemplate>RequestFirewallChange.eDoc.FinalApproval.RuleTemplate</ruleTemplate>
      		<description>Final Approval By Firewall SysAdmin Rule</description>
      		<ignorePrevious>false</ignorePrevious>
      		<ruleExtensions>
        			<ruleExtension>
         	 			<attribute>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</attribute>
          				<ruleTemplate>RequestFirewallChange.eDoc.FinalApproval.RuleTemplate</ruleTemplate>
          				<ruleExtensionValues>
            					<ruleExtensionValue>
              						<key>isUrgent</key>
              						<value>NO</value>
            					</ruleExtensionValue>
          				</ruleExtensionValues>
        			</ruleExtension>
	      	</ruleExtensions>
      		<responsibilities>
        		<responsibility>
          			<workgroup>ucd.IET.DCCS.FirewallSysAdmin.Workgroup</workgroup>
          			<actionRequested>A</actionRequested>
          			<priority>1</priority>
        		</responsibility>
      		</responsibilities>
    	</rule>
	<rule>
      		<documentType>RequestFirewallChange.eDoc.ChildDocType</documentType>
      		<ruleTemplate>RequestFirewallChange.eDoc.FinalApproval.RuleTemplate</ruleTemplate>
      		<description>Final Approval By Firewall Policy Group Rule</description>
      		<ignorePrevious>false</ignorePrevious>
      		<ruleExtensions>
        			<ruleExtension>
         	 			<attribute>RequestFirewallChange.eDoc.isUrgent.RuleAttribute</attribute>
          				<ruleTemplate>RequestFirewallChange.eDoc.FinalApproval.RuleTemplate</ruleTemplate>
          				<ruleExtensionValues>
            					<ruleExtensionValue>
              						<key>isUrgent</key>
              						<value>YES</value>
            					</ruleExtensionValue>
          				</ruleExtensionValues>
        			</ruleExtension>
	      	</ruleExtensions>
      		<responsibilities>
        		<responsibility>

          			<workgroup>ucd.IET.AppDev.FirewallPolicyGroup.Workgroup</workgroup>
          			<actionRequested>A</actionRequested>
          			<priority>1</priority>
        		</responsibility>
      		</responsibilities>
    	</rule>
	<rule>
      		<documentType>RequestFirewallChange.eDoc.ChildDocType</documentType>
      		<ruleTemplate>RequestFirewallChange.eDoc.AcknowledgeConfiguration.RuleTemplate</ruleTemplate>
      		<description>Acknowledge Configuration Rule</description>
      		<ignorePrevious>true</ignorePrevious>
      		<responsibilities>
        		<responsibility>
          			<role>edu.iu.uis.eden.routetemplate.InitiatorRoleAttribute!INITIATOR</role>
				<approvePolicy>F</approvePolicy>
          			<actionRequested>K</actionRequested>
          			<priority>1</priority>
        		</responsibility>
      		</responsibilities>
    	</rule>
</rules>
</data>

actionRequested codes: A = APPROVE, K = ACKNOWLEDGE

XML File Ingestion

Now, we take all that we have built and upload it to a Kuali Rice server using the XML Ingestion tool.

  1. Open the URL to a Kuali Rice development server (e.g. http://ricedevhost.ucdavis.edu:8080/rice-0.9.3-server/)
  2. Click on Kuali Enterprise Workflow
  3. Log in as admin
  4. Under Administration, click on XML Ingester
  5. Upload the XML files we created in the following order:

    Rule Attributes

    RequestFirewallChange.eDoc.RuleAttributes.xml

    Rule Templates

    RequestFirewallChange.eDoc.RuleTemplates.xml

    Parent Document Type

    RequestFirewallChange.eDoc.ParentDocType.xml

    Child Document Types

    RequestFirewallChange.eDoc.ChildDocType.xml

    EDL Form

    RequestFirewallChange.eDoc.Form.xml

    Routing Rules:

    RequestFirewallChange.eDoc.Rules.xml

    In production, each department will submit all XML files to the Kuali Rice team via a formal collaborative process.

Simulate the Business Process

Let's simulate a Firewall Change Request that gets approved by someone in the Firewall Policy Group:

  1. Log in as requester1
  2. Click on EDocLites
  3. Click Search
  4. Find the eDocLite whose Definition Name is RequestFirewallChange.eDoc.Form
  5. Click on Create Document
  6. Here's the form we built:
  7. Fill out the form, set URGENT to NO and click route
  8. Log in as DES1
  9. Click on Action List
  10. Find and open the document initiated by requester1. Its status should be ENROUTE
  11. Click on the document and it should look like so:
  12. Click approve
  13. Login as DCCS1
  14. Click on Action List. The document should not be in DCCS1's Action List.
  15. Log in as FPG1
  16. Click on Action List
  17. Find and open the document initiated by requester1 and approved by DES1. Its status should be ENROUTE
  18. Click approve
  19. Login as DCCS1
  20. Click on Action List
  21. Find and open the document initiated by requester1, approved by DES1, and approved by FPG1. Its status should be ENROUTE
  22. Click approve
  23. Log in as requester1 again
  24. Click on Action List
  25. Find and open the document initiated by requester1, approved by DES1, approved by FPG1, and acknowledged by DCCS1. Its status should be PROCESSED
  26. Click acknowledge
  27. Click Document Search
  28. Find the document again
  29. Click on the Log icon
  30. The log should like like so:

Reference

https://test.kuali.org/confluence/display/KULRICE/EDocLite+Documentation+Guide
https://test.kuali.org/confluence/display/KULRICE/eDocLite+Example+1
https://test.kuali.org/confluence/display/KULRICE/EDoclite+Support+Notes
https://test.kuali.org/confluence/display/KULRICE/KEW+Rules
https://test.kuali.org/confluence/display/KULRICE/Routing+Components+and+Configuration+Guide