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
- Model the Business Process
- Model the Form Details
- Model the Document Workflow
- Create Validation Checklists
- Procure Work Groups
- 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
- Implement Workflow Components
- 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 |
|
Desktop Services |
|
Firewall Policy Group |
|
Firewall Gatekeeper |
|
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.
<?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:
<?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 |
|
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:
- 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">&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>
- 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>
- 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.
<?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 |
<?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.
<?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.
- Open the URL to a Kuali Rice development server (e.g. http://ricedevhost.ucdavis.edu:8080/rice-0.9.3-server/)
- Click on Kuali Enterprise Workflow
- Log in as admin
- Under Administration, click on XML Ingester
- 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:
- Log in as requester1
- Click on EDocLites
- Click Search
- Find the eDocLite whose Definition Name is RequestFirewallChange.eDoc.Form
- Click on Create Document
- Here's the form we built:
- Fill out the form, set URGENT to NO and click route
- Log in as DES1
- Click on Action List
- Find and open the document initiated by requester1. Its status should be ENROUTE
- Click on the document and it should look like so:
- Click approve
- Login as DCCS1
- Click on Action List. The document should not be in DCCS1's Action List.
- Log in as FPG1
- Click on Action List
- Find and open the document initiated by requester1 and approved by DES1. Its status should be ENROUTE
- Click approve
- Login as DCCS1
- Click on Action List
- Find and open the document initiated by requester1, approved by DES1, and approved by FPG1. Its status should be ENROUTE
- Click approve
- Log in as requester1 again
- Click on Action List
- Find and open the document initiated by requester1, approved by DES1, approved by FPG1, and acknowledged by DCCS1. Its status should be PROCESSED
- Click acknowledge
- Click Document Search
- Find the document again
- Click on the Log icon
- 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