# Tuesday, 16 August 2011

imageIn a previous article we discussed 4 Steps to Building an Apple-style Product Configurator with uCommerce, which detailed how to piece together a complete product from multiple product options configured in the catalog.

This article will help you deal with those composite items as a unit rather than separate line items.

Step 1: Adding a Composite Product to Basket

When adding the main product and options to the basket we’ll need some way to tell the “master order line” from the “sub order lines”.

We’ll use dynamic order properties to enrich the order lines  for the required information linking each product option line to a master order line containing the main product; our MacBook Air 11 inch.

With that in mind here’s the Razor code in Umbraco to add all the selected options to the basket.

ProductCatalog catalog = ProductCatalog.All().Single(x => x.Name == SiteContext.Current.CatalogContext.CurrentCatalogName);
    
// Check if we're dealing with a post
if (!string.IsNullOrEmpty(Request["masterSku"]))
{
    var basket = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
        
    // Add the master order line
    var mainProduct = Product.All().Single(x => x.Sku == Request["masterSku"] && x.ParentProductId == null);
    var masterOrderLine = basket.AddProduct(catalog, mainProduct, 1, false);
        
    // Mark the master as such
    masterOrderLine["master"] = true.ToString();
 
    // Save basket to generate ids for the order line
    basket.Save();
        
    // Add each product option to the basket
    foreach (string key in Request.Params.AllKeys.Where(x => x.Substring(0, 3) == "SKU"))
    {
        // Split the value of the posted skus to get both sku and variant sku (where applicable)
        // Example Intel-Core-CPU,i7-1.7
        string[] skus = Request[key].Split(',');
        string sku = skus[0];
        string variantSku = skus.Length == 2 ? skus[1] : null;
            
        // Add the option order line
        var optionProduct = Product.All().Single(x => x.Sku == sku && x.VariantSku == variantSku);
        OrderLine subOrderLine = basket.AddProduct(catalog, optionProduct, 1, false);
 
        // Add a reference back to the master order line
        subOrderLine["masterOrderlineId"] = masterOrderLine.OrderLineId.ToString();
    }
 
    basket.Save();
 
    // Execute the basket pipeline to recalculate basket
    Library.ExecuteBasketPipeline();
}

Now we’ve got all the items added to the basket let’s move on to displaying the items in a nice way on the basket page.

Step 2:  Displaying the Composite Product

Now we’ll need to leverage that extra information we added in the previous step to group the items together.

@using UCommerce.EntitiesV2;
@using UCommerce.Runtime;
@{
    // Load basket
    var basket = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
}
 
@foreach (var masterOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "master" && y.Value == true.ToString()).Count() > 0))
{
    <form method="post">
    <input type="hidden" name="masterOrderLineId" value="@masterOrderLine.OrderLineId"/>
    <div>
        <h4>@masterOrderLine.ProductName</h4>
        <ul>
            @foreach (var subOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "masterOrderLineId" && y.Value == masterOrderLine.OrderLineId.ToString()).Count() > 0))
            {
                <li>@subOrderLine.ProductName</li>
            }
        </ul>
        <input type="submit" value="Remove" name="remove" />
    </div>
    </form>
}

Here’s what the basket looks like when Umbraco and Razor renders it:

image

Step 3: Remove a Composite Product

Next we’ll want to let the customer remove composite items from the basket by remove the master order line along with any sub order lines it might have.

@using UCommerce.EntitiesV2;
@using UCommerce.Runtime;
@using UCommerce.Xslt;
@{
    // Load basket
    var basket = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
 
    // Check for post
    if (!string.IsNullOrEmpty(Request["masterOrderLineId"]))
    {
        int masterOrderLineId = Convert.ToInt32(Request["masterOrderLineId"]);
 
        // Find all sub order lines for master
        var subOrderlines = basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "masterOrderLineId" && y.Value == masterOrderLineId.ToString()).Count() > 0).ToList();
 
        // Remove sub order lines from basket
        foreach (var subOrderLine in subOrderlines)
        {
            basket.RemoveOrderLine(subOrderLine);
        }
 
        // Now remove the master order line
        OrderLine masterOrderLine = basket.OrderLines.Single(x => x.OrderLineId == masterOrderLineId);
 
        basket.RemoveOrderLine(masterOrderLine);
        basket.Save();
 
        // Recalculate basket
        Library.ExecuteBasketPipeline();
    }
  
}
 
@foreach (var masterOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "master" && y.Value == true.ToString()).Count() > 0))
{
    <form method="post">
    <input type="hidden" name="masterOrderLineId" value="@masterOrderLine.OrderLineId"/>
    <div>
        <h4>@masterOrderLine.ProductName</h4>
        <ul>
            @foreach (var subOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "masterOrderLineId" && y.Value == masterOrderLine.OrderLineId.ToString()).Count() > 0))
            {
                <li>@subOrderLine.ProductName</li>
            }
        </ul>
        <input type="submit" value="Remove" name="remove" />
    </div>
    </form>
}

Summary

Managing multiple items as one in the basket is handy when working with complex product options like we did for the MacBook Air just now. At all times should customers be certain as to what they’re buying and managing the items should be as straightforward as for “simple items”.

Combining multiple items into one visually is a matter of adding a bit of extra information to tie the items together and doing a clever presentation of the items.

All the internal calculations and stock management stay the same behind the scenes so you just have to worry about doing a nice presentation of the basket.

Comments are closed.