aiftikhar
Scholar

Using Custom Worklist to open OOF task fails.

Background: We are currently running K2 BlackPearl 4.7 with March 2018 Update. 

 

Problem: The tasks fails to open for traget users when using Out of Office Tasks. 

 

Error Message: Worklist item could not be opened. 24411 K2:DomainDomainUser from 172.xx.x.xxx:xxxx is not allowed to open the worklist item with SN=29531_44

 

Issue: Currently when a user sets their status as out of office and fowards all assigned tasks to a delgated users, the user is able to use the Out of The Box Worklist to access and action tasks, although when using the customer worklist the user recieves an error listed above. After some reading online was I was able to conclude that this has to do with how our Custom Worklist was written and how it opens the task items is incorrect as follows:

 

What our current service uses - WorklistItem = this.Connection.OpenWorklistItem
What we need our modified service to use to open shared items - WorklistItem = this.Connection.OpenSharedWorklistItem

 

I need some possible help and guidence as to how I can incorrporate the open shared worklist item call into our current custome WorkList Service using the correct API calls and still being able to handle regular tasks that are not shared or deligated, below is how it is current written. I am not proficent .NET and would appreicate any help I can get in this matter. 

 

using System;
using System.Linq;
using SourceCode.Workflow.Client;

namespace WL
{
public static class ClientTask
{
public static RequestApprovalTask OpenApprovalTask(string serialNumber, bool readOnly)
{
if(string.IsNullOrWhiteSpace(serialNumber))
throw new ArgumentException("Parameter 'serialNumber' can not be null, empty or whitespace.");

var splitIndex = serialNumber.IndexOf('_');
if(splitIndex <= 0)
throw new ArgumentException("Parameter 'serialNumber' does not represent a valid client event serial number. Format should be <Process Instance ID>_<Activity Destination Instance ID>.");

using(var connection = ConnectionHelper.CreateWorkflowConnection())
{
var processInstanceID = int.Parse(serialNumber.Substring(0, splitIndex));

var criteria = new WorklistCriteria();
criteria.AddFilterField(WCField.ProcessID, WCCompare.Equal, processInstanceID);

// Approval client events are configured as plan all at once, 1 slot; so we need to open the worklist first.
// Trying to open the worklist item by serial number directly, without first opening the worklist will fail.
var worklist = connection.OpenWorklist(criteria);

// Try to find the worklist item by serial number. This will only return a result if the item is open or available.
var clientTask = worklist
.Cast<WorklistItem>()
.Where(i => string.Equals(i.SerialNumber, serialNumber, StringComparison.InvariantCultureIgnoreCase))
.FirstOrDefault();

try
{
if(clientTask != null)
{
// Found our worklist item by serial number
clientTask.Open(readOnly ? false : true);
}
else
{
// If we don't have a worklist item here, it's probably allocated to someone else
// so try to find the allocated item.
clientTask = worklist
.Cast<WorklistItem>()
.Where(i => i.Status == WorklistStatus.Allocated)
.FirstOrDefault();

if(clientTask == null)
throw new ApplicationException("The requested task could not be located. Serial Number: " + serialNumber);
}

return new RequestApprovalTask
{
RequestID = Guid.Parse((clientTask.ProcessInstance.DataFields["RequestID"].Value ?? string.Empty).ToString()),
AllocatedUser = clientTask.AllocatedUser
};
}
finally
{
connection.Close();
}
}
}

public static void ReleaseApprovalTask(string serialNumber)
{
using(var connection = ConnectionHelper.CreateWorkflowConnection())
{
var criteria = new WorklistCriteria();
criteria.AddFilterField(WCField.SerialNumber, WCCompare.Equal, serialNumber);

var worklist = connection.OpenWorklist(criteria);
if(worklist == null || worklist.Count == 0)
return;

var clientTask = worklist[0];
clientTask.Release();

connection.Close();
}
}
}

public class RequestApprovalTask
{
public Guid RequestID { get; set; }
public string AllocatedUser { get; set; }
}
}

 

0 Kudos
Reply
4 Replies
boringNerd1
Novice

Re: Using Custom Worklist to open OOF task fails.

Hi,


 


K2's developers reference should provide you with some clue on how to achieve this. If you refer to the section called "Opening a Delegated WorklistItem (including Out of Office items)", there should be some code snippets that you can use in your code.


 


With Out of Office enabled, the worklist item's allocated user should remain unchanged. What that means is, if a task is assigned to userA, and userA sets out of office to userB, then the worklist item will appear on userB, BUT the allocated user for that worklist item should remain unchanged.


 


This means you can use the worklist item's AllocatedUser property to compare it with the user who is trying to open the worklist item. If they match, then use Connection.OpenWorklistItem.


 


If they don't match, then use Connection.OpenSharedWorklistItem.

Reply
Vernon1
Novice

Re: Using Custom Worklist to open OOF task fails.

Hi There

I see you on 4.7 MarchCU, do you have any additional Fixpacks applied on top of that? You can check the db (Select * from [HostServer].[UpdateHistory]).

Reason for asking we did fix some bug in OOO in FP3. If you dont have this or later installed, i suggest you log a K2 Support ticket to get the latest FixPack for 4.7 March CU.

Please let us know once applied if your issue is resolved.

HTH
Vernon
0 Kudos
Reply
aiftikhar
Scholar

Re: Using Custom Worklist to open OOF task fails.

@

 

 

 

0 Kudos
Reply
Olivier1
Novice

Re: Using Custom Worklist to open OOF task fails.

@aiftikhar,

 

You should be able to compare the current user with the allocated user by a comparison of "cnx.User.FQN" with "wkItem.AllocatedUser".
In this example, you will be able to see how to get the final url by added the &SharedUser=... in the URL only if necessary:

 

foreach (SourceCode.Workflow.Client.WorklistItem wkItem in cnx.OpenWorklist(criteria))
{
...
FinalURL = wkItem.Data + ((wkItem.AllocatedUser.ToLowerInvariant() == cnx.User.FQN.ToLowerInvariant() || wkItem.Data.ToLowerInvariant().Contains("&shareduser=")) ? "" : "&SharedUser=" + wkItem.AllocatedUser.ToString());
...
}

 

Best regards,

Olivier

0 Kudos
Reply