Create an order note from automation script

Questions about and code samples for automation process code snippets within Select.
Post Reply
kkirkfield
Posts: 27
Joined: Tue Jun 28, 2016 2:26 pm

Create an order note from automation script

Post by kkirkfield » Tue Jun 26, 2018 5:00 pm

Hello, I'm trying to make an automation script in IronPython that creates an order note and adds it to the order being saved. In C#, it would be created by doing

Code: Select all

Order.CreateNew("Note")
and then adding it to the order and applying the changes. When I try doing this in an automation script though it gives the error below:
Error: The automation instance failed.
Stack Trace:
at SoftPro.Select.Server.Automation.Runtime.XamlWorkflowInstanceWorker.OnResume(String bookmark, EventArgs args)
at SoftPro.Select.Server.Automation.Runtime.WorkflowController.Resume(WorkflowInstance instance, String bookmark, EventArgs args)
***********************************************************************************
Error: 'Order' object has no attribute 'CreateNew'
Stack Trace:
at SoftPro.ClientModel.AsyncResult`1.get_Result()
at SoftPro.Select.Server.Automation.Builtin.CodedActionActivity.EndExecute(NativeActivityContext context, IAsyncResult result)
at System.Activities.Runtime.BookmarkWorkItem.Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
I'm importing the IOrder interface that defines the CreateNew method. What do I need to do to accomplish this?

Code: Select all

import clr
from System import *
from SoftPro.ClientModel import *
from SoftPro.Select.Client import *
from SoftPro.OrderTracking.Client.Orders import *

newNote = Context.CreateNew("Note") # Fails here

# Other code

BobRichards
Posts: 1006
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Create an order note from automation script

Post by BobRichards » Wed Jun 27, 2018 3:28 pm

CreateNew() is a method on the IOrder interface and not accessible as a context method. We can get the IOrder interface from Select but first we must manually load the library (via AddReference()) then import its namespace as usual. The Automation Python engine does not do it for us automatically as it would for a custom order rule.

Code: Select all

from System import *
from SoftPro.ClientModel import *
from SoftPro.Select.Client import *

import clr
clr.AddReference('SoftPro.OrderTracking.Client')
from SoftPro.OrderTracking.Client.Orders import IOrder

# Get an empty note from the order and get the Order object.
#    If order is not context (i.e. Task is context), then use "order = Context.Root"
order = Context
note = IOrder.CreateNew(order, 'Note')

# Fill it out: Text, DisplayOnOrderOpen, Categories, ...
note.Text = 'Hello'

# Add it to the order.
order.Notes.Add(note)
Bob Richards, Software Developer, SoftPro

kkirkfield
Posts: 27
Joined: Tue Jun 28, 2016 2:26 pm

Re: Create an order note from automation script

Post by kkirkfield » Thu Jun 28, 2018 10:12 am

Thanks Bob, works perfectly. I was confused how the CreateNew() method was working in your example since it doesn't match any method signatures on IOrder. Found this great site explaining the syntax you used and that the first parameter is the instance. Makes sense now.
http://ironpython.net/documentation/dot ... ce-methods

BobRichards
Posts: 1006
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Create an order note from automation script

Post by BobRichards » Thu Jun 28, 2018 11:51 am

Yeah. You found my magic documentation on IronPython. It has helped a lot. It is a little thick to get through for the average Python script writer so I usually don't mention it. Glad you found enlightenment!
Bob Richards, Software Developer, SoftPro

kkirkfield
Posts: 27
Joined: Tue Jun 28, 2016 2:26 pm

Re: Create an order note from automation script

Post by kkirkfield » Thu Jun 28, 2018 12:26 pm

One final question regarding order notes in automation scripts. The Note Categories property in the Field Code Browser shows it is a String. I originally assumed it was a comma separated list, because that is how it is displayed on the notes screen on the order. That didn't work, so now I'm thinking it is a list of Enum<INoteCategory>. Now I'm trying to get the IEnumManager so that I can search the enums and return the subset that I want. I assumed it works like order rules, in that you can call args.GetService(), but the below is failing. How can I get the EnumManager from automation scripts?

Code: Select all

import clr

from System import *
from SoftPro.ClientModel import *
from SoftPro.Select.Client import *
from SoftPro.Select.Client.Enumerations import *

clr.AddReference("SoftPro.OrderTracking.Client")
from SoftPro.OrderTracking.Client.Orders import IOrder, NoteType

enumManager = Context.GetService[IEnumManager]()

BobRichards
Posts: 1006
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Create an order note from automation script

Post by BobRichards » Fri Jul 06, 2018 6:09 pm

The note Categories property is a string holding zero or more integers separated by commas ("", "3", "4,9") as you surmised. The numbers are the Value property for the particular enum. As this is a dynamic table, you will need to get the list of INoteCategory enums at runtime. This is what I did below. I also got a little fancy in that you can test against a list of desired categories and it will look them all up and build the string.

Code: Select all

from System import *
from SoftPro.ClientModel import *
from SoftPro.Select.Client import *
from SoftPro.Select.Client.Enumerations import *

import clr
clr.AddReference('SoftPro.OrderTracking.Client')
from SoftPro.OrderTracking.Client.Orders import IOrder

# Get an empty note from the order and get the Order object.
#    If order is not context (i.e. Task is context), then use "order = Context.Root"
order = Context
note = IOrder.CreateNew(order, 'Note')

# Add categories and copy string to Text for testing purposes only.
enumMgr = Context.GetService(IEnumManager)
noteCategories = enumMgr.GetEnum[INoteCategory]()
cats = [str(b.Value) for b in noteCategories.Values if b.Description in ['Integration', 'Select']]
if cats:
	note.Categories = ','.join(cats)
	note.Text = 'This is the text written to categories: "' + note.Categories + '"'

# Add it to the order.
order.Notes.Add(note)
The code produces the following results based on how many codes were requested and found. (Description is case sensitive!)
Attachments
Note.png
Note.png (9.9 KiB) Viewed 1636 times
Bob Richards, Software Developer, SoftPro

kkirkfield
Posts: 27
Joined: Tue Jun 28, 2016 2:26 pm

Re: Create an order note from automation script

Post by kkirkfield » Tue Jul 10, 2018 2:01 pm

Thanks Bob! It works perfectly. Will be able to do so much more from python scripts now that I can get services from it.

kkirkfield
Posts: 27
Joined: Tue Jun 28, 2016 2:26 pm

Re: Create an order note from automation script

Post by kkirkfield » Thu Aug 09, 2018 9:22 am

I ended up converting this over to a server package and ran into a bug in some versions of Select. Just thought I'd share my findings and workarounds for anyone that needs to do something similar.

When you are setting the categories of the note, if you set it to an empty string it will allow it, but it will corrupt the order on certain screens where the notes are displayed. For example, if you open the general notes snap section it will throw an object reference exception at SoftPro.OrderTracking.SnapSections.GeneralNotesSnapSection.AddNoteCommand_QueryStatus(Object sender, QueryStatusEventArgs e).

The workaround is to simply check for an empty string, and if empty, set the categories to null or None instead of empty.

BobRichards
Posts: 1006
Joined: Wed Jan 15, 2014 3:50 pm
Location: Raleigh, NC
Contact:

Re: Create an order note from automation script

Post by BobRichards » Thu Aug 09, 2018 10:02 am

Thanks! Once I verify I can reproduce it I'll add it to our bug tracker. We really appreciate findings from the field where the experience with direct API usage creates bugs in the Select client application.
Bob Richards, Software Developer, SoftPro

Post Reply