Product orders have the most complex structure of all the financial transaction types. Each order is associated with purchaser and payment information, and can contain one or more shipments, and each shipment can contain one or more items. The resulting XML looks like this:
<Record xsi:type="ens:ProductOrder"> <ens:OrderId>100000064</ens:OrderId> <ens:Payment> <ens:Amount>1000.00</ens:Amount> </ens:Payment> <ens:Purchaser> <ens:ConsId>100000053</ens:ConsId> <ens:ConsName> <ens:FirstName>John</ens:FirstName> <ens:LastName>Doe</ens:LastName> </ens:ConsName> </ens:Purchaser> <ens:ShipTo> <ens:Item> <ens:ProductId>100000055</ens:ProductId> <!-- additional item attributes... --> </ens:Item> </ens:ShipTo> <ens:ShipTo> <ens:Item> <ens:ProductId>100000055</ens:ProductId> <!-- additional item attributes... --> </ens:Item> </ens:ShipTo> </Record>
It is important to note that each Item element represents a single unit, rather than a line item in a typical invoice. If someone places an order for 5 of the same product, then the corresponding record will contain 5 Item elements, rather than a single Item with a quantity of 5. In many cases this may seem repetitive, but it is necessary to accommodate the fact that each unit may have distinct shipping address, shipping option, fulfillment and tribute details.
In most cases client applications will want to summarize or "roll up" product orders into a flatter structure that reflects a particular product configuration. For example, say that your site typically only sells two products, and you just want to get a count of each product sold. The following C# code illustrates how you would summarize each order:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Configuration; namespace DataSyncClient { /** * Downloads new or updated donations to a local XML file. */ class ProductOrderDownloader { private static String PRODUCT_ONE_ID = "1234"; private static String PRODUCT_TWO_ID = "1235"; private Convio.SoapClient client; private Convio.Session session; public ProductOrderDownloader(Convio.SoapClient client, Convio.Session session) { this.client = client; this.session = session; } /** * Makes a series of requests to retrieve the full set of order of the specified type. * * Sums line items by product ID */ public void download(DownloadType type) { String typeLabel = type.ToString().ToLower(); String partitionId = ConfigurationSettings.AppSettings["partitionId"]; String[] fields = { "OrderId", "Payment.Amount", "Purchaser.ConsId", "Purchaser.ConsName", "Purchaser.MemberId", "ShipTo.Item.ProductId"}; int page = 1; while (true) { Convio.Record[] records = (type == DownloadType.Inserts) ? client.GetIncrementalInserts(session, partitionId, "ProductOrder", page.ToString(), "100", fields) : client.GetIncrementalUpdates(session, partitionId, "ProductOrder", page.ToString(), "100", fields); if (records == null || records.Length == 0) { if (page == 1) { System.Console.WriteLine("No Product Order " + typeLabel + " to download"); } break; } int start = (page - 1) * 100 + 1; System.Console.WriteLine("Downloading Product Order " + typeLabel + " " + start + " to " + (start + records.Length)); foreach (Convio.Record record in records) { Convio.ProductOrder order = (Convio.ProductOrder)record; /** * Each Item element represents a single unit. Iterate over all the elements * to count how many were ordered of each product; **/ int productOneCount = 0, productTwoCount = 0, otherCount = 0; foreach (Convio.ShipTo ship in order.ShipTo) { foreach (Convio.Item item in ship.Item) { String productId = item.ProductId; if (PRODUCT_ONE_ID.Equals(productId)) { productOneCount++; } else if (PRODUCT_TWO_ID.Equals(productId)) { productTwoCount++; } else { otherCount++; } } } // process the order, including product counts... } page++; } } } }