
Any many of you have pointed out, there isn't much sample code out there on working with Change Orders. So let me attempt to remedy that by providing code on two common operations you might want to do through the API: creating a new Change Order and updating the lifecycle state of a Change Order.
Adding a new Change Order
A new Change Order will always use the default workflow. A workflow is the set of lifecycle states and transitions (activities) between them. Once created, the Change Order is locked to that workflow forever.
So, when you create a new Change Order you don't need to pass in the workflow. But you do need to pass in the routing, which is the set of users and their roles on that Change Order. You also need to pass in the number for the Change Order. The easiest route is to just use the default routing and default numbering scheme, as shown below.
|
// C# private void NewChangeOrder(ChangeOrderService coSvc) { // get the default routing Workflow workflow = coSvc.GetDefaultWorkflow(); Routing [] routings = coSvc.GetRoutingsByWorkflowId(workflow.Id); Routing defaultRouting = routings.FirstOrDefault(n => n.IsDflt); if (defaultRouting == null) throw new Exception("No default routing");
// get the next number in the default sequence ChangeOrderNumSchm [] numberingSchemes = coSvc.GetNumberingSchemesByType(NumSchmType.ApplicationDefault); ChangeOrderNumSchm defaultNumberingScheme = numberingSchemes.FirstOrDefault(); if (defaultNumberingScheme == null) throw new Exception("No default numbering scheme"); string coNumber = coSvc.GetChangeOrderNumberBySchemeId(defaultNumberingScheme.Id);
// create the new change order ChangeOrder newCo = coSvc.AddChangeOrder(defaultRouting.Id, coNumber, "Sample CO", "Sample", DateTime.Now.AddMonths(1), null, null, null, null, null, null, null); }
|
|
' VB.NET Private Sub NewChangeOrder(coSvc As ChangeOrderService) ' get the default routing Dim workflow As Workflow = coSvc.GetDefaultWorkflow() Dim routings As Routing() = coSvc.GetRoutingsByWorkflowId(workflow.Id) Dim defaultRouting As Routing = routings.FirstOrDefault(Function(n) n.IsDflt) If defaultRouting Is Nothing Then Throw New Exception("No default routing") End If
' get the next number in the default sequence Dim numberingSchemes As ChangeOrderNumSchm() = _ coSvc.GetNumberingSchemesByType(NumSchmType.ApplicationDefault) Dim defaultNumberingScheme As ChangeOrderNumSchm = _ numberingSchemes.FirstOrDefault() If defaultNumberingScheme Is Nothing Then Throw New Exception("No default numbering scheme") End If Dim coNumber As String = coSvc.GetChangeOrderNumberBySchemeId( _ defaultNumberingScheme.Id)
' create the new change order Dim newCo As ChangeOrder = coSvc.AddChangeOrder( _ defaultRouting.Id, coNumber, "Sample CO", "Sample", _ DateTime.Now.AddMonths(1), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing) End Sub
|
Moving to a new state
One nice thing is that the Change Order object has an Activities property which lists all the valid state changes currently possible. So, all your code needs to do is pick one and run the update calls. There are a few things you need to know:
- There might not be any activities. There are a couple of "sink" states where Change Orders cannot move out of.
- An activity might loop back to the same state. For example, you can perform the review operation when you are in the review state. This will result in the Change Order moving to the review state. So even though an activity was performed, the state is the same.
- Closing a Change Order requires additional information, effectivity. Therefore, a different API function is used for that case.
Like with many Item operations, you need to do 2 calls to perform the update. The first call starts the operation and the second call commits the operation. If something goes wrong, you need to call an undo function.
|
private void ChangeState(ChangeOrderService coSvc, ChangeOrder co) { if (co.ActivityArray == null || co.ActivityArray.Length == 0) throw new Exception("Change Order cannot be moved to another state"); // for demo purposes, we will just pick the first one Activity activity = co.ActivityArray[0]; ChangeOrder editableCo = null; try { editableCo = coSvc.StartChangeOrderActivity( co.Id, activity.Id, co.StateId, co.StateEntered); ChangeOrder committedCo; if (activity.Name == "Set Effectivity") { committedCo = coSvc.CommitChangeOrderCloseActivity( editableCo.Id, activity.Id, editableCo.StateId, editableCo.StateEntered, null, null, DateTime.Now, DateTime.MaxValue); } else { committedCo = coSvc.CommitChangeOrderActivity( editableCo.Id, activity.Id, editableCo.StateId, editableCo.StateEntered, null, null); } } catch { if (editableCo != null) coSvc.CancelChangeOrderActivity(editableCo.Id, activity.Id); throw; } }
|
|
Private Sub ChangeState(coSvc As ChangeOrderService, co As ChangeOrder) If co.ActivityArray Is Nothing OrElse co.ActivityArray.Length = 0 Then Throw New Exception("Change Order cannot be moved to another state") End If
' for demo purposes, we will just pick the first one Dim activity As Activity = co.ActivityArray(0)
Dim editableCo As ChangeOrder = Nothing Try editableCo = coSvc.StartChangeOrderActivity( _ co.Id, activity.Id, co.StateId, co.StateEntered) Dim committedCo As ChangeOrder If activity.Name = "Set Effectivity" Then committedCo = coSvc.CommitChangeOrderCloseActivity( editableCo.Id, activity.Id, editableCo.StateId, editableCo.StateEntered, Nothing, Nothing, DateTime.Now, DateTime.MaxValue) Else committedCo = coSvc.CommitChangeOrderActivity( editableCo.Id, activity.Id, editableCo.StateId, editableCo.StateEntered, Nothing, Nothing) End If Catch If editableCo IsNot Nothing Then coSvc.CancelChangeOrderActivity(editableCo.Id, activity.Id) End If Throw End Try End Sub
|
Leave a Reply