I've been playing around a little bit with Iron Python in SoftPro Select. Setting fields, doing validation, learning some boundaries and how it fits in. It was time for a real life example so I chose the EscrowBriefLegal field. That seemed complex but simple.
A custom rule starts by defining the function with the Context (Property) as it's seen in the Field Code browser at the bottom
Followed by the Field Name (EscrowBriefLegal) which is displayed in bold, and the rule aspect being attached to. (Value)
Line 9 sets up a couple of variables to use later.
On line 13, we are looping up args.Context.Lots, which says, hey IronPython that Context you started at, (Property in this case) give me the .Lots object of it please. In IronPython indents keep us in our loop, the loop ends when the next line is on the same indent of the start of the loop.
Order.Properties(0).Lots has a member Number, which can be seen in the field code browser, if there is text in Number then we care about it, otherwise loop. That keeps the output updated when users delete a cell in a row without deleting the row. In line 15, I did my if statement a bit backward, if count is zero we save the number in the else statement. Then the counter is incremented and we loop. If there are more lots they are preceded by a comma space and the count incremented.. Finally if we counted more than one number precede the numbers with the appropriate tag. Set the count to zero for the next usage.
The code does the same thing with Units and Parcels and TaxMaps, saving each to a string variable
Next we just grab some individual fields starting with Block
Our Context is Property so we define and set the variable pblock to whatever is there. If it's something it is formatted, if it's nothing, it is set to String.Empty() to keep the final line happy.
The Subdivision should start on a new line done with "\r\n" in IronPython.
At the end the order is set as it's being assigned to the value
and it renders on every property every time.
That all has been refactored in this module
from System import * from SoftPro.ClientModel import * from SoftPro.OrderTracking.Client import * from SoftPro.OrderTracking.Client.Orders import * from System.Text import StringBuilder # # Escrow Brief Legal creation by Dan Van Fleet email@example.com 05/31/2015 def AddObjectNumber(sb, object, single, multiple, afterLabel, betweenMultiples): #object = multiple object with a .Number child #single = label for single item return (Lot) #multiple = label for multiple item return (Lots) #afterLabel = string to appear after the label and before the Identifier #betweenMultiples = string to appear between multiples normally ', ' count = 0 curPos = sb.Length for u in object: if u.Number > '': if count > 0: sb.Append(betweenMultiples) sb.Append(u.Number) else: sb.Append(u.Number) count += 1 InsertLabel(sb, curPos, count,single,multiple, afterLabel) def AddObjectIdentification(sb, object, single, multiple, afterLabel, betweenMultiples): #object = multiple object with a .Identification child #single = label for single item return (Lot) #multiple = label for multiple item return (Lots) #afterLabel = string to appear after the label and before the Identifier #betweenMultiples = string to appear between multiples normally ', ' count = 0 curPos = sb.Length for u in object: if u.Identification > '': if count > 0: sb.Append(betweenMultiples) sb.Append(u.Identification) else: sb.Append(u.Identification) count += 1 InsertLabel(sb, curPos, count,single,multiple, afterLabel) def InsertLabel(sb, curPos, count, single, multiple, spaceAfter): #Inserts single or multiple text label at curPos if count > 1: sb.Insert(curPos, multiple) sb.Append(spaceAfter) elif count == 1: sb.Insert(curPos, single) sb.Append(spaceAfter) def AddSingleField(sb, field, pre, post): #adds field with preamble and post text, or skips if no field data if field > '': sb.Append(pre).Append(field).Append(post) def Property_EscrowBriefLegal_Value(args): sb = StringBuilder() AddObjectNumber(sb, args.Context.Lots, 'Lot ', 'Lots ', ' ' , ', ') AddObjectNumber(sb, args.Context.Units, 'Unit ', 'Units ', ' ' , ', ') AddSingleField(sb, args.Context.Block, 'Block ', ' ' ) AddSingleField(sb, args.Context.Building, 'Building ' , ' ' ) #demo start Subdivision on a new Line if it exists, # start Condo on one if Subdivision doesn't exist preSubdivision = sb.Length #Save length AddSingleField(sb, args.Context.Subdivision, '\r\n', ' ') if preSubdivision == sb.Length: #Length didn't grow so put Condo on separate line AddSingleField(sb, args.Context.Condo, '\r\n', ' ') else: AddSingleField(sb, args.Context.Condo, '', ' ') AddSingleField(sb, args.Context.Section, '\r\nSection ', ' ') AddSingleField(sb, args.Context.Phase, 'Phase ' , ' ' ) AddObjectIdentification(sb, args.Context.Parcels, '\r\nParcel ID ','\r\nParcel IDs ', ' ' , ', ') AddObjectIdentification(sb, args.Context.TaxMaps, '\r\nTax/Map ID ','\r\nTax/Map IDs ', ' ' , ', ') args.Value = sb.ToString()
A little about the refactored code:
6/1/15 A new update has been made using StringBuilder to end the immutable string issue on performance.
New function refactored, InsertLabel to handle the single or plural
The function AddObjectNumber() is used to pull the Lot.Number and Unit Number. AddObjectIdentification() is used for Parcels and TaxMaps. The function AddSingleField() is used to format non multiple Order.Properties().Objects.
AddOrderNumber accepts 3 parameters, the multiple being processed, the single unit label and the multiple unit label, either of which can be string.Empty(). AddOrderIdentification works the same way, but is used for objects that contain an .Identification field.
AddSingleField accepts a non multiple field which gets combined with the pre and post text.
Add field by field name for example to add Order.Property(current).MapReference use
AddSingleField(sb, args.Context.MapReference, ‘Map Ref ‘, ‘\r\n\r\n’)
where ever in the order MapReference is to appear. With that coding it will be preceded by “Map Ref” and followed by an double line feed.