Bill’s Tasking Workflow Pattern

Sending tasks is easy to do in K2, but to make them more adaptable from outside the work is a bit more tricky. A colleague of mine named Bill Irvine, came up with pattern to standardize the way tasking is developed and used.  So taking his idea i have come up with own interpretation of his tasking pattern so this why i am calling this Bill’s  tasking workflow pattern.

 

Getting Started

To get started we need the following SmartObjects, I have included the sql for the tables and store procedures.  When the framework is released it will be included as apart of that.

Tables

Tasking relies on the following tables

tasking-db

Task Library

Contains all the task types. It contains Id of the form that the task will navigate too and also whether task needs to send task notification email

CREATE TABLE [dbo].[TaskLibrary](
[TaskTypeId] [uniqueidentifier] NOT NULL,
[TaskName] [nvarchar](50) NULL,
[FormId] [uniqueidentifier] NULL,
[TaskDescription] [nvarchar](max) NULL,
[EmailNotification] [bit] NULL,
[Escalation] [bit] NULL,
[EscalationTimeId] [uniqueidentifier] NULL,
[EmailTemplateId] [uniqueidentifier] NULL,
[Slots] [int] NULL,
CONSTRAINT [PK_TaskLibrary] PRIMARY KEY CLUSTERED
(
[TaskTypeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Note if not using framework change, form id data type from unique identifier to Nvarchar(100).

Task Actions

Task Actions contains all the possible actions for that particular task type

CREATE TABLE [dbo].[TaskActions](
[TaskActionId] [uniqueidentifier] NOT NULL,
[TaskTypeId] [uniqueidentifier] NULL,
[TaskAction] [nvarchar](50) NULL,
[TaskValue] [int] NULL,
CONSTRAINT [PK_TaskActions] PRIMARY KEY CLUSTERED
(
[TaskActionId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Tasks

Tasks contains the destination users for the task type, the task’s serial number against a particular task type and process instance Id

CREATE TABLE [dbo].[Tasks](
[TaskId] [uniqueidentifier] NOT NULL,
[WorkflowType] [uniqueidentifier] NULL,
[SN] [nvarchar](50) NULL,
[Username] [nvarchar](50) NULL,
[BusinesObjectId] [nvarchar](50) NULL,
[ProcessInstanceId] [int] NULL,
[TaskTypeId] [uniqueidentifier] NULL,
[TaskAction] [nvarchar](50) NULL,
[DestinationKey] [uniqueidentifier] NULL,
CONSTRAINT [PK_Tasks_1] PRIMARY KEY CLUSTERED
(
[TaskId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

All tables have basic CRUD methods to manage the data and there is also some additional store procedures to help with the tasking pattern

 

The tables and store procedures scripts can be accessed here 

SmartObject 

The tasking SmartObject is called K2C.CMN.SMO.Tasking, and it manages the creation of creating task types and its related task actions. It also manage the destination user’s task details

Properties

Name
Type
Description
TaskId GUID Destination User Task Id for an instance of the task
ProcessTypeId GUID Process Type Id
Username Text FQDN of the destination user
BusinessObjectId Text Primary Key of the main business data
ProcessInstanceId Number Id of the instance of the process
SN Text Serial Number for the task
TaskTypeId GUID Id for the type of task
TaskAction Text Action for the task
TaskActionId GUID Action Id for a particular task type action
TaskValue Number Task value that relates to actual action in the workflow either 1,2 or 3
TaskName Text Name of the task type
FormId GUID Form Id from the form library
TaskDescription Text Description of the task type
EmailNotification Yes/No Whether task needs to send an email

SmartObject Methods

Method Name
Store Procedure
Description
Create Task Action sp_TaskActionsCreate Creates a new action for the task type
Delete Task Action sp_TaskActionsDelete Deletes the action for the task type
Get All Task Actions sp_TaskActionsList Gets a complete list of the task actions
Get Task Action sp_TaskActionRead Gets a action for Task Type
Update Task Action sp_TaskActionUpdate Updates a action in the task type
Create Task Type sp_TaskLibraryCreate Creates a new task type
Delete Task Type sp_TaskLibraryDelete Deletes a task type
Get all Task Types sp_TaskLibraryList Gets all Task Types
Get Task Type sp_TaskLibraryRead Gets a particular task type
Update Task Type sp_TaskLibraryUpdate Updates a task type
Create Task sp_TasksCreate Creates a new task entry
Delete Task sp_TasksDelete Deletes the task
Get All Tasks sp_TaskList Gets a list of tasks
Get Task sp_TaskRead Gets a particular task
Update Task sp_TaskUpdate Updates the task
Get tasks by type sp_TaskActions Gets all actions by task type
Update Task Action sp_TasksUpDateAction Updates the destination user task’s action
Task Result sp_TaskResult Gets result of the task
Create Destination Key so_CreateDataFieldKey Creates a group key for destination users

Workflow

This version is very simple and only works for one slot, but it could be expanded to manage multiple slots.

Process Data Fields

The process data fields needed for this workflow are

Data Field Name
Data Field Type
Description
In or out
TaskId String So we know what task type In
ParentProcessInstanceId Number Parent Process Instance Id In
 DestinationKey  string
Expire Boolean stops start going to expire, set to false Int
ActionResponse String action value returned Out

Simple tasking pattern

task-workflow-v2

Activities

  1. Setup – Links workflow to framework
  2. Send Email, sends email based on a template
  3. Task, creates task based on the task type Id
  4. Action 1 ,2 , 3,  records the action returned
  5. Expire , responds to the task escalating
  6. End, tidies everything up based on framework

 

Setup

The setup activity does all the framework registration

Send Email

This activity will record the task with the notification service. It will also call the Email service and pass in the template id from the task type reference

Task

It will add the Serial Number to the destination user record in tasks and the activity will also have a client event. It will get task url from the form library and the destination user will come from task reference. It will have 3 actions (1,2,3)

Action 1, 2, 3

Will record the action  against the task by getting the action name from the ‘Get Task Action’ method and it will set the data field ‘Action Response’ with the action value

End

Will do the framework clean up, so deleting  external data fields etc…

 

Notes

Remember to audit logs (for the actual task workflow and also for the parent workflow so we can record the action e

Line Rules

Line Rule
Description
LR Email Notification Required If method ‘Is Email Required’ returns true
LR No Email Notification Required If method ‘Is Email Required’ returns false
Start to Expire Data field ‘Expire’ = ‘True’

References

The tasking pattern workflow requires two references

  1. Destination
  2. Task Type

references

Destination Reference

Gets a list of destination users for a particular task type

  1. In the  Data (3rd) tab of the context browser in K2 Studio / Visual Studio
  2. Right click on ‘References’ and click ‘Add’
  3. Give the reference a name ‘Destination’
  4. Select the method ‘K2C.CMN.SMO.Tasking.Get Destination Users’
  5. For the input property use the ‘DestinationId
  6. Click ‘Next and then ‘Finish’

reference

 

Task Type Reference

Gets information about the task type such as whether an email should be sent, which form to use as the task.

  1. In the  Data (3rd) tab of the context browser in K2 Studio / Visual Studio
  2. Right click on ‘References’ and click ‘Add’
  3. Give the reference a name ‘Task Type’
  4. Select the method ‘K2C.CMN.SMO.Tasking.Get Task Type’
  5. For the input property use the ‘Task Id’ data field
  6. Click ‘Next and then ‘Finish’

tasking

Building the tasking workflow

  1. Create an activity on the canvas and name it ‘Setup’
  2. If you are using framework then, add in the related framework events, else just put a  placeholder event in their for now.
  3.  Create another activities called ‘Send Email’ and ‘Task’
  4. Create a line between ‘Setup’ and ‘Send email’ and another line between ‘Setup’ and ‘Task’
  5. Right click on the line between ‘Setup’ and ‘Send Email’
  6. Select properties
  7. In General properties give it the label of ‘LR Email Notification required’
  8. Click on the ‘Line rule’ section greenarrow
  9. Click on ‘Add’
  10. In the rule editor now. In the ‘First Variable’ open the context browser expand the 3rd tab
  11. Expand references, expand ‘Task Type’
  12. Select ‘Email Notification’, either drag it into ‘first variable’ or click on ‘Add’
  13. Comparison operator should be ‘=’
  14. Second variable will be ‘True’
  15. Click ‘Ok’ and then ‘Finish’
  16. We have now added a rule that will check to see if an email notification is required.
  17. We now need to do the same for the other line we created, except call the line ‘LR No email notification required’
  18.  Second variable for this rule should be ‘False’

This slideshow requires JavaScript.

The email event

  1. Add an email event in the ‘Send Email’ activity
  2. Give it a name like ‘send email’
  3. Select ‘originator’ and unchecked ‘specify’ in ‘Recipient’

Task Activity

In the task activity we need to add a ‘SmartObject event’ that records the serial number of the task and we also need to add a client event

Recording the ‘Serial Number’

  1. Drag the ‘SmartObject Event’ into the task event
  2. Give the event a name ‘Add sn’
  3. Select the SmartObject method ‘Add task sn’ from the SmartObject ‘K2C.CMN.SMO.Tasking’
  4. Click ‘Next’
  5. Now in ‘Input Mapping’ for the ‘PSN’ click on ‘Assign’
  6. Expand Process Instance from and select ‘id’
  7. Type in ‘_’
  8. Expand ‘Activity Destination Instance’ and select ‘Id’
  9. Click on ‘pTaskId’ and ‘Assign’
  10. Expand the ‘Destination’ reference and  use Task Id
  11. This will now save the task serial number against the destination user.

This slideshow requires JavaScript.

Adding user task

  1. Drag a ‘Client Event’ in to the task activity
  2. Name it ‘User Task’
  3. Check ‘Task Item URL’
  4. If using framework follow this route
    1. dd
  5. If not using framework follow this route
    1. Click on eclipse
    2. Go to the 3rd tab expand ‘References’
    3. Expand ‘Task Type’
    4. Drag ‘FormId’ or select ‘Form Id’ and click on ‘Add
  6. Click on ‘Next’ and ‘Next’ again
  7. In Actions click on ‘Add’
  8. In the ‘Add Action’ window, enter 1 in name and click on ‘Ok’
  9. Repeat this adding 2 and 3 as a action
  10. Click ‘Next’ and ‘Next’ again
  11. In Destination users click on ‘Add’
  12. Click on eclipse,
  13. In the context browser
  14. Click on 3rd tab
  15. Expand References
  16. Expand ‘Destination’
  17. Click on ‘Username’ and click on ‘Add’
  18. Click ‘Next’ and then ‘Finish’
  19. We have now created a generic task

This slideshow requires JavaScript.

Recording the Action

  1. Create a ‘Default Activity’ and name it ‘1’
  2. Drag a SmartObject Event into the event
  3. Name it ‘Task Action’
  4. For ‘SmartObject  Method’ use ‘Update Task Action’ from ‘K2C.CMN.SMO.Tasking’
  5. Click ‘Next’
  6. In Input Mapping, click on ‘pTaskAction’ and then on ‘Assign’
  7. Click on eclipse, it opens the context browser
  8. Go the 1st tab, expand SmartObject Servers
  9. Expand the SmartObject ‘K2C.CMN.SMO.Tasking’
  10. Expand the method ‘Get Task Action’
  11. Select the ‘TaskAction’ property
  12. Click on ‘OK’
  13. This method requires some additional properties.
  14. ‘pTaskValue’ property needs to be 1
  15. ‘pTaskTypeId’ property needs to be the datafield called ‘TaskId’
  16. Click ‘Next’ and ‘Next’ again
  17. Select ‘Task Action’ and click ‘Next’
  18. Make sure ‘Return a single item’ is checked
  19. Click on ‘Finish’
  20. Click on ‘OK’
  21. What we have just done is get the text value of the action for the task type and of the action value of 1.
  22. pTaskId just needs to be Task Id from the destination reference
  23. Click on ‘Finish’
  24. Copy this Activity and rename it to ‘2’
  25. and change ‘PtaskValue’ to ‘2’
  26. Repeat steps 24 and 25 and change the ‘1’ to a ‘3’
  27. These activities will now record the action of the task against the destination user
  28. We also need to record the action in the data field ‘Action Response. So do to steps 9 to 23 in a data event for each of the 3 activities. This will allow the parent workflow to easily retrieve the action.
  29. Connect the out come lines to the activities we just created
  30. Create an activity called
  31. Last of all create a activity called ‘End’ with a placeholder called ‘End’ and join the 3 activities to the end activity.

 

Your tasking workflow should look something like this

taskingwkf.PNG

 

Download workflow, SmartObject from here

 

The workflow could be extended to allow multiple slots and multiple destinations. The great thing about a tasking pattern is that it just reduces development time and testing and allows actions to be dynamically added and removed, without the need to go into the actual workflow.

It also allows there to be generic task forms that just point to the tasking workflow and they just need the task type id to load up the correct actions for the task type.

Below is a brief explanation of how to use it, but I will go into more details on how to use it in a later article. For now it’s just about exploring the idea of a tasking pattern and how it would it work.

How to use the tasking workflow

To use the tasking workflow follow these simple steps

  1. Add the tasking workflow to the solution
  2. Create a new workflow
  3. Use the SmartObject event with ‘Create destination key’ method and bind the result to a data data field called ‘Destination key’ of type string
  4. Now we need to use the ‘Create Task’ method to add the destination user, task type id and destination key
  5. Add the IPC Event and point it to the tasking workflow
  6. Choose synchronous
  7. Map the following data fields ‘Task Id, Destination Key’
  8. For the return value map ‘Action response’ data field of the tasking workflow to the parent ‘Action response’ data field
  9. Then use a line rule to direct the workflow based on the ‘Action response’

 

 

 

 

 

 

How to: For Each Event

Over the last couple of weeks people have asked me how to use the for each loop event in K2. So I thought i would put this quick demo together.

The demo, that i am going to do is going to loop through a list of subscribers and update their status from ‘Not Sent’ to ‘Sent’.

Getting Started

I have created a simple Smart box  SmartObject for demo purposes that has the following properties

  1. 1. Name of type string
  2. Email of type string
  3. Id of type Auto number and Key
  4. Status of type string

smo

I have inserted 3 rows of data with the status of ‘Not Sent’. We will use this SmartObject to use the ‘For Each’ event to loop through the data.

Creating the workflow

for-each-simple

Adding the ‘For Each’ event

  1. Open K2 Studio or K2 for Visual Studio ( I am going to use K2 Studio)
  2.  Create a new workflow solution called ‘For Each Demo’
  3. Rename the workflow from process 1 to ‘ForEachWorkflow’
  4. Once the workflow canvas has loaded up
  5. Drag the ‘for each’ event on to the canvas
  6. In the event wizard, give the event the name ‘Loop demo’
  7. Click on Source ico icon, so the drop down list disappears  and open the context browser
  8. In the 1st tab (Environment) , expand ‘SmartObject Services’
  9. Go to the SmartObject you want to use and expand the list method you want to use
  10. Drag the property that you want to use, normally the primary key into the event box
  11. The SmartObject wizard loads up, click ‘Next’ and ‘Next’ again
  12. In ‘Select a return property’ make sure the ‘id’ value is selected.
  13. Click ‘Next’, make sure ‘Return all Results that match filter’ is selected.
  14. Click ‘Finish’
  15. For the reference name, enter in the name ‘Dummy Data Reference’
  16. For the index name, enter in the name ‘Dummy Index’
  17. Click on ‘Finish’

This slideshow requires JavaScript.

Interacting with the for each item

  1. Back in the canvas, you will notice there are now two line rules coming out of the activity
  2. Drag the placeholder event on the canvas and name both the event and activity with the name ‘End’
  3. Drag the ‘line’ named ‘No more items’ to the end activity
  4. Create a new activity on the canvas and name it ‘Status Change’
  5. Drag the SmartObject Event into the newly created activity
  6. In the event wizard for the SmartObject event, name it ‘Update Status’
  7. Select the update method for the SmartObject that you used with the ‘for each’ event
  8. Click ‘Next’
  9. For the ‘ID’ property, click assign
  10. In the context browser go to the 3rd tab (Data) and expand ‘Item references’ and then expand ‘ Loop demo reference’
  11. Click on ‘Id’ property and click on ‘Add’
  12. Click on ‘Status’ and click ‘Assign’ and enter in the text ‘Sent’
  13. Click on ‘Next’ and ‘Next’ again and then ‘Finish’
  14. Drag the remaining line named ‘Next item’ to this activity and then create a new line from this activity back to the ‘for each’ activity.

This slideshow requires JavaScript.

That is a simple example of using the ‘For each’ event. Anything that follows the ‘Next item’ line is in side the loop and has the context of the current row the loop is on. You can have multiple activities in this part and the workflow  will move on to the next item once it has completed everything in that section. You must always have a line going back to the activity with the ‘for each’ event in.

Other things to remember

  1. Choose 1 property to return in the for each event. Always best to use a primary or foreign key
  2. Remember to select ‘Return all Results that match filter’ as it will return the complete list back and it doesn’t matter if there is no filter applied.

 

Next step using references with the ‘For Each’ Event

So we have created a simple workflow with a simple for each loop. But what if we wanted to get more data from the for each event and then possibly use it in a line rule.

In the next example, the workflow is going to check the current status of the item it is looking at. If it’s status is already ‘Sent’ it will ignore it and move on to the next item in the list and if the status is ‘Not Sent’ it will then update the status as normal

I am going to use the same workflow as before

Creating the reference

  1. In the context browser, go to the 3rd tab (data)
  2. Right click on ‘References’ and click on ‘Add’
  3. In the ‘SmartObject Method Reference’ click on ‘Next’
  4. In name, give the reference a name , for my example i have used ‘Dummy data’
  5. In SmartObject Method, select a read type method that uses value you have selected in the for each as the input parameter. I am pointing my reference to the read method.
  6. Click ‘Next’
  7. In input mapping, click on Assign and select the id from the item reference for the for each loop.
  8. Click ‘Next’ and ‘Finish’
  9. We have now created a reference to get the related details based on the current row of the ‘for each’ event.

This slideshow requires JavaScript.

 

Editing the ‘for each’ line rule for ‘Next Item’

Now that we have the reference setup, we can edit the line rule for ‘Next Item’

  1. Right click on ‘Next item’
  2. Click on ‘Properties’
  3. ‘Line General Properties’ will load up. Click on  greenarrowthe green arrow for line rules
  4. Click on ‘Add’
  5.  In rule editor, select ‘And’ from ‘Boolean Operator’
  6. In ‘First Variable’ click on eclipse
  7. In the context browser,  go the references in the 3rd tab
  8. Expand References, expand your reference you created in the last section
  9. Drag ‘Status’ into the ‘First Variable’
  10. The ‘SmartObject Wizard ‘ pops up, click on ‘Status’
  11. Click ‘Finish’
  12. Select ‘<>’ from ‘Comparison Operator’
  13. In the ‘Second Variable’ enter ‘Sent’
  14. Click on ‘Ok’
  15. Click on ‘Finish’
  16. We now need to create another rule that is similar to the ‘Next Item’ rule but where the ‘Status’ is equal to ‘Sent’

This slideshow requires JavaScript.

Creating a new line rule for ‘Next Item’ and where status is equal to ‘Sent’

  1. Right click and drag a line from the ‘For Each’ activity to ‘Update Status’
  2. Then drag the line from ‘Update Status’ to ‘For Each’. (We have to do this as line can’t go back on it self without being connected to another activity first)
  3. Right click on the line and click on ‘properties’
  4. In ‘Label’ enter ‘New Item and status is sent’
  5. Click on greenarrow and then click on ‘Add’
  6. In the Rule editor in ‘First Variable’
  7. Click on eclipse and expand the process data fields
  8. Click on ‘Dummy index result’ and click ‘Ok’
  9. Select ‘=’ for the operator
  10. In Second variable enter in ‘True’
  11. Click ‘Ok’
  12. Click on ‘Add’
  13.  In rule editor, select ‘And’ from ‘Boolean Operator’
  14. In ‘First Variable’ click on eclipse
  15. In the context browser,  go the references in the 3rd tab
  16. Expand References, expand your reference you created in the last section
  17. Drag ‘Status’ into the ‘First Variable’
  18. The ‘SmartObject Wizard ‘ pops up, click on ‘Status’
  19. Click ‘Finish’
  20. Select ‘<>’ from ‘Comparison Operator’
  21. In the ‘Second Variable’ enter ‘Sent’
  22. Click on ‘Ok’
  23. Click on ‘Finish’

 

This slideshow requires JavaScript.

 

Download example here