Order Creation/Modification Via Overlay Using External Data

Discussions related to SoftPro Select user interface development.

Moderator: Phil Barton

Post Reply
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Order Creation/Modification Via Overlay Using External Data

Post by dlerickson »

In a nutshell, what I'm basically trying to do is take a list of predefined key/value pairs from an external data source, and either create a new order or overlay an existing order, depending on whether a current order matching a Loan number exists. I've seen the existing 'Overlay Order' feature in the Select client and am wondering if/how this can be achieved programmatically.

To complicate matters, for existing orders, the incoming fields must be compared with the existing order fields, and for those that differ, the user must have the ability to view each side-by-side, and select which overlay values to save.

So, a couple of questions:

1. How, if at all, can the existing application and API be used to map, display and/or commit the overlay fields?
2. Can the .pfd/.pft formats be used in any way? I'm thinking of some sort of XSL transform or something similar with the incoming key/value data, but have no idea what format these files are in, as I don't have an example of one handy.
3. Keep in mind that I'm new to this, and am making assumptions about how the templates would work, but those assumptions could be completely wrong.
Phil Barton
Posts: 54
Joined: Wed Sep 24, 2008 2:37 pm
Location: Raleigh, NC
Contact:

Re: Order Creation/Modification Via Overlay Using External D

Post by Phil Barton »

Which version of Select are you using?
Phil Barton
Software Architect
SoftPro
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Order Creation/Modification Via Overlay Using External D

Post by dlerickson »

I believe it's 3.0.
Phil Barton
Posts: 54
Joined: Wed Sep 24, 2008 2:37 pm
Location: Raleigh, NC
Contact:

Re: Order Creation/Modification Via Overlay Using External D

Post by Phil Barton »

I'm assuming at this point, you are able to connect to the server and create the order through the API. If not, here is a link to posts on how to do that viewtopic.php?f=19&t=539&p=2224&hilit=IOrderStore#p2224. Opening an order is not too different. To set data values you simply assign the value to the property you need (the field code browser in the UI will show you the entire class structure of an order). Retrieving values is essentially the same - reference the property on the object to get the value. Now, it should be noted that the API is not strongly typed, so you'll be dealing with type object, throughout. From the previous article, here's a code snippet:

Code: Select all

Public Class Form1
 
    Dim creds As NetworkCredential
    Dim sps As SelectServer
 
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        'connect to the server
        creds = New NetworkCredential("Admin", "Passw0rd", "[SERVER]")
        sps = New SelectServer("http://LOCALHOST:8080", creds)
        sps.EnsureAuthenticated()
 
        Dim OrderStore As IOrderStore = sps.GetService(Of IOrderStore)()
        Dim numberManager As IOrderNumberingManager = sps.GetService(Of IOrderNumberingManager)()
        Dim profileManager As IProfileManager = sps.GetService(Of IProfileManager)()
        Dim groups As IQueryable(Of IOrderNumberingGroup) = numberManager.OrderNumberingGroups
        Dim closestProfile = New ClosestAncestorProfileSearch(profileManager.ActiveProfile)
 
        Dim group As IOrderNumberingGroup
        group = Searchable.Search(Of IOrderNumberingGroup, ClosestAncestorProfileSearch)(groups, closestProfile).FirstOrDefault()
 
        'The creationSpec needs to be setup before using it to create an order
        Dim spec As New OrderCreationSpec() With {
            .Number = group.GetFormattedOrderNumber()}
 
        group.GetNextNumber(Nothing, Nothing) 'If you were providing prefix or suffix, they would go here
 
        'Using order As IOrder = OrderStore.NewOrder(spec)
        Using order As IOrder = OrderStore.NewOrder(spec)
            Try
                Dim DynOrder As Object = order
                DynOrder.Project = "Setting a simple string property."
                DynOrder.Properties(0).Address.City = "City"
 
 
                Dim propertyInfo As Object = order.CreateNew("Property")
                propertyInfo.Address.Address1 = "test"
 
                Try : DynOrder.SettlementDate = DateTime.Now : Catch : End Try
 
                OrderStore.ApplyChanges(order)
                MsgBox(String.Format("Order has been created: {0}", DynOrder.Number))
            Catch ex As Exception
                MsgBox(String.Format("An error occured: {0}", ex.Message))
            Finally
                OrderStore.CloseOrder(order)
            End Try
        End Using
    End Sub
 
End Class
Here, you can see the setting and getting of properties on the objects. Now, for your scenarios, the mapping of the data would have to come from your analysis of the incoming key-value pairs and how they map to the object hierarchy. I know that's not much of an answer, but going from a flat structure to a hierarchal one, that's what is required. The PFD/PFT files are stored in a binary format, so they may not be of much use to you unless you can get them into they key-value pair notation that you're expecting. Now, for your other requirements:

1. To find out if there is an order with the loan number already exists in the system, use the IOrderStore.NewOrderSearch(...) method to query for any orders that match your criteria
2. Displaying the differences of data from current to incoming is going to have to be something specific to your case. There is nothing built in that will do that for you. However, there are methods on the IOrderItem interface that may help you. If you cast, say, the order to IOrderItem, you have access to many helper methods such as GetIsCalculated(...), which lets you know if a property's value was calculated by a rule or user-entered, GetIsReadOnly(...), which lets you know if the rules have made the property read-only, and may others.

I hope this gets you going. We'll keep monitoring this forum and help you as best we can along the way.
Phil Barton
Software Architect
SoftPro
dlerickson
Posts: 80
Joined: Tue Jan 21, 2014 11:35 am
Location: Austin, TX

Re: Order Creation/Modification Via Overlay Using External D

Post by dlerickson »

Thanks, Phil! Very helpful information, and thanks for getting back to me on this. Unfortunately, I made a mistake; we're actually using the Boylan/2.0 version of the software and API. Does the process differ radically there?

Also, my original idea was to try to set these overlay properties via a field mapping lookup table in the database, which would map my overlay key/value items to the correct table and column. That was going to get nasty quick, so I'm glad that the Order object is addressable in a similar but more stable fashion. My plan is now to store Property metadata in the lookup and set the object properties via reflection.

One of the BA's here mentioned that there are some sort of "field codes" that can be set, and from the little water cooler conversation I had, it sounds *really* similar to my idea. Any insights on that, and how I might be able to take advantage of it?

Thanks again!
john.morton
Posts: 89
Joined: Wed Nov 16, 2011 11:51 am

Re: Order Creation/Modification Via Overlay Using External D

Post by john.morton »

...either create a new order or overlay an existing order, depending on whether a current order matching a Loan number exists.
Unfortunately, with the 2.6 version of the API, there is no way to search orders. You must connect directly to our database to find the order numbers that you want to deal with.

As far as the data-driven approach to mapping key-value pairs to API entries, based on the fact that the object model is a hierarchical structure, with several one-to-many collections, I would think you would not be well-served following this path. The amount of overhead required to put a system like that in place is quite extensive. it may behoove you more to determine a static approach to handling the mappings.

Other than that, it's just a matter of manipulating the correct collections and objects through our API. There are several examples on this forum and in our SDK help file, but here are a couple to get you started:

Connecting and creating an order:

Code: Select all

        private void CreateOrder()
        {
            if (!ConnectToSelect("Admin", "MyPassword", "http://MyServer:8080"))
            {
                return;
            }
            string myOrderNumber;

            OrderTracking ot = _server.GetService<OrderTracking>();

            // Open the order
            using (IOrder order = ot.CreateOrder())
            {
                try
                {
                    myOrderNumber = order.Number;

                    order.SalesContract.SalesPrice = 1000000;

                    ValidationMessage[] results;
                    ot.SaveOrder(order, out results);
                }
                finally
                {
                    ot.CloseOrder(order);
                }
            }

            MessageBox.Show(string.Format("Order: {0} has been created!", myOrderNumber));
        }
Open an existing order, create a buyer and set the loan amount:

Code: Select all

           if (!ConnectToSelect("Admin", "MyPassword", "http://MyServer:8080"))
            {
                return;
            }

            // Create the order tracking client
            _orderTracking = _server.GetService<OrderTracking>();


            // Create the specification for the existing order.
            OrderQuerySpec spec = new OrderQuerySpec()
            {
                BaseOrderNumber = @"TestOrder"
            };

            // Open the order
            using (IOrder order = _orderTracking.GetOrder(spec, false))
            {
                try
                {
                    IBuyer buyer = order.Buyer.CreateNew();
                    buyer.Name = "Billy Buyer";

                    order.Loan[0].LoanAmount = 1000000;

                    ValidationMessage[] results;
                    if (!_orderTracking.SaveOrder(order, out results))
                    {
                        foreach (var message in results)
                        {
                            MessageBox.Show(message.Message);
                        }
                    }


                }
                finally
                {
                    // This MUST be called to release any locks on the order
                    _orderTracking.CloseOrder(order);
                }
            }
Post Reply