SmarTeam Workflow’s API engine offers tremendous flexibility for manipulating processes on-the-fly.  The object model, and the combination of nodes, users, and events make it easy to perform fairly advanced operations with workflow.  As an example, let’s use the API to dynamically assign a user to a node based on their participation earlier in the workflow. We’ll use BasicScript and C#.NET to write the code (directions for getting the source code below), and cover some of the important details of how to apply the customization in ENOVIA SmarTeam.

One of the most common requirements when designing a workflow in SmarTeam is dynamic user assignments but what is that?  Imagine a workflow that is routed through an approval process that is initiated by an engineer.  The engineer initiates the workflow which is routed to a document control node for a primary approval step which, in turn, goes to the engineer again for an additional step.  Since the engineer is not known at design-time of the flowchart, the user must be dynamically assigned to the next node.  Dynamic assignments may be done manually by the user at the node, or can be done automatically via scripting.  Rather than rely on the document control user to manually assign the engineer for notification, it’s more efficient and reliable to automate the assignment of the user.  In this case, automation is the only way to ensure that the initiator (the engineer) is assigned to the node.

The good news is that SmarTeam exposes all the objects needed for this flexibility via scripting.  Before explaining the code, let’s review what we’re creating to support the automation:

  1. SmarTeam script (written in BasicScript) with a function that will be hooked to an event in Workflow
  2. Workflow flowchart that is configured to run the script function
  3. Compiled COM-visible DLL that will be called by the script to do the automation (in this case, we’re using C#.NET 2005)

1. SmarTeam Script Development

Create a function within a SmarTeam script file.  For this scenario, the function will be called AssignInitiatorToEngineering.  Note the parameters that are being passed.  The parameters are important, because at various event hooks, different parameters are required.  In this case, the function will be hooked to the “After Send Accept” event of the Start Node (described later).

Function AssignInitiatorToEngineering(smFlowSession As Object, smFlowProcess As Object, smNode As Object, smResponse As Object) As Integer
‘ hook to After Send Accept of start node
On Error GoTo Error_AssignInitiatorToEngineering
Dim RazorleafUtils As Object
Set RazorleafUtils = CreateObject(“Razorleaf.AcmeMfg.Workflow.MessageUtils”)
RazorleafUtils.AssignInitiatorToEngineering smFlowProcess
Exit Function
MsgBox “An error has occured on line ” & Erl & “. The error number is ” & Err.Number & “. The error description is ‘” & Err.Description & “‘.”, ebCritical, “Error AssignInitiatorToEngineering()”
End Function

2. SmarTeam Workflow Configuration

Once the BasicScript function is in place, it can be hooked to the After Send Accept event on the Start Node of the flowchart.  Note that we are not covering creation of the Workflow flowchart here, but you can do this with the Flowchart Designer.  While in the Flowchart Designer (via the SmarTeam Admin Console), click on the Start Node; press F4 to access the Properties dialog; click on the Events tab and click the ellipsis button next to After Send Accept:

Locate the BasicScript file, select the AssignInitiatorToEngineering function, and click OK.

The Properties dialog in the Flowchart Designer should then look like this:

3. Library Development

Now that the script has been created and hooked to the event, the code development can be started.  In the script above, note the two lines that call the library:

Set RazorleafUtils = CreateObject(“Razorleaf.AcmeMfg.Workflow.MessageUtils”)
RazorleafUtils.AssignInitiatorToEngineering smFlowProcess

Razorleaf.AcmeMfg.Workflow.MessageUtils is the name of the library being developed.  It can have almost any name, but good practice is to name it something relevant.  Note that the second line is where the script passes the parameter into the library.

Open Visual Studio and create a class library project.  To use the SmarTeam API, several references must be added.  For ease of supporting future versions of SmarTeam, reference the COM assemblies and not the SmarTeam .NET interops:

SmarTeam Library
SmartFlow Library

The project’s references should now look like this: As mentioned above, this library was named Razorleaf.AcmeMfg.Workflow.MessageUtils.  The method we’re creating is named AssignInitiatorToEngineering and it will be configured to accept the parameters noted above.  Note that the class and the method must be public and the class constructor cannot take any input parameters.

public System.Int16 AssignInitiatorToEngineering(SmartFlow.ISmFlowProcess smFlowProcess)

In this dynamic assignment scenario, we need to perform two actions:

  1. Get the user who initiated the workflow
  2. Assign the user to the node named “Engineering”

To do these steps, first get the initiator’s User Object ID and then retrieve the User object:

//Getting User Object ID
System.Int32 userObjectID = (System.Int32)smFlowProcess.SmObject.get_Value(“USER_OBJECT_ID”);
//Retrieving user object
SmApplic.ISmObject smUser = smFlowProcess.FlowStore.Session.ObjectStore.RetrieveObject(smFlowProcess.FlowStore.Session.MetaInfo.get_SmClassByName(“Users”).ClassId, userObjectID);

Once the user object is retrieved, then we need to also retrieve the Engineering Node:

//Getting engineering node
SmartFlow.ISmNode engineeringNode = GetNode(“ENGINEERING”, smFlowProcess);

Note that GetNode() is a custom method that was added to the class.  The method retrieves the node, given the flow process and the name of the node.  Here is the code for the GetNode internal method:

internal SmartFlow.ISmNode GetNode(System.String nodeName, SmartFlow.ISmFlowProcess flowProcess)
//Getting outgoing nodes…
SmartFlow.ISmNodes smNodes = flowProcess.Flowchart.Nodes;
for (int i = 0; i < smNodes.Count; i++)
if (smNodes[i].Name.ToUpper() == nodeName.ToUpper())
//Found node…returning node
return smNodes[i];
// no match found
//Node not found..returning null
return null;

Once the node is found by the GetNode method, the user can be added to the node.  Be sure to save the node after updating:

if (engineeringNode != nul