Automatic Abandoned Basket Reminders

by Joe Payne 22. June 2012 09:06

Put together a really nice automation routine for a client recently.

The client needed a way to fully automate abandoned basket reminders.  But the key is they only wanted to send the reminder X number of times. 

Thanks to some code from a few previous projects, I was able to put together a modification that changed only 1 existing AbleCommerce file.

Now their AC7 store will automatically scan for abandoned baskets at regular intervals.  Any baskets found are sent the designated email.  Once the email is sent, a marker is placed on the basket so the shopper isn’t spammed with reminders.  Even wrote a handy config page so the client can adjust the designated email template or the criteria without further program customization.

Tags: , ,

General News | Personal

How to explode checkout basket items into separate shipments in AbleCommerce 7

by Joe Payne 25. March 2011 07:47

Need:  The project requires every item ordered from the AbleCommerce 7 storefront to be assigned it’s own shipment.  The reason is each item is made separately and must ship separately.  Even if multiple quantities of the same item are purchased, each unit of 1 must be by itself on a separate shipment.

 

Justification: Existing AC7 code will automatically split basket items up into separate shipments based on the WarehouseId value assigned to each product in the basket.  However this does not split up multiple quantities of the same item.  Even if an item is set as “Ships Separately” on the Edit Product page, AC7 will not break each quantity of the multi-quantity item into separate shipments.  Thus custom code is required.

 

Solution:  Create a new helper class in /App_Code/.  I called mine AbleModsHelper.Basket.cs.  Put the following code into the file and call the routine in the basket initialization area of OnePageCheckout.ascx.cs.  You’ll probably want to comment out the original Basket.Package() code so AbleCommerce libraries don’t mess up your shipments.

 

/// <summary>
/// Builds a shipment for each quantity of each product in the supplied basket
/// </summary>
/// <param name="_Basket">Basket to which shipments will be assigned</param>
public static void MakeBasketShipments(Basket _Basket)
{
    // Reset basket item shipment assignments 
    foreach (BasketItem _BasketItem in _Basket.Items)
    {
        _BasketItem.BasketShipmentId = 0;
        _BasketItem.Save();
    }
 
    // remove any shipments after shipment[0]
    if (_Basket.Shipments.Count > 1)
        for (int x = 1; x < _Basket.Shipments.Count; x++)
            _Basket.Shipments[x].Delete();
 
    // loop through basket items and make new shipments for each item and quantity ordered
    //BasketItemCollection _NewItems = new BasketItemCollection();
    int _ItemCount = _Basket.Items.Count;
    for (int _Count = 0; _Count < _ItemCount; _Count++)
    {
        BasketItem _BasketItem = _Basket.Items[_Count];
        // skip anything that's not a product or is already Qty 1
        if (_BasketItem.OrderItemType != OrderItemType.Product | _BasketItem.Quantity <= 1)
            continue;
 
        // we've got an item with multiple quantity - split it out using the original basketitem
        // record as a template.
        // first though, we must reset the new "master" product to qty 1
        int _LoopQty = _BasketItem.Quantity - 1;
        _BasketItem.Quantity = 1;
        _BasketItem.Save();
 
        // loop through remaining quantity of this item
        for (int x = 0; x < _LoopQty; x++)
        {
            // clone the original basket item
            BasketItem _NewItem = _BasketItem.Clone();
 
            // set it's quantity and basketid
            _NewItem.Quantity = 1;
            _NewItem.BasketId = _Basket.BasketId;
 
            // save the duplicate basketitem 
            _NewItem.Save();
 
            // clone any basket inputs from the original basket item
            foreach (BasketItemInput _BasketInput in _BasketItem.Inputs)
            {
                BasketItemInput _NewInput = new BasketItemInput();
                _NewInput.BasketItemId = _NewItem.BasketItemId;
                _NewInput.InputFieldId = _BasketInput.InputFieldId;
                _NewInput.InputValue = _BasketInput.InputValue;
                _NewInput.Save();
            }
 
            // add new item it to the basket
            _Basket.Items.Add(_NewItem);
            _Basket.Save();
        }
 
    }
 
    // clear out all shipments for this basket
    _Basket.Shipments.DeleteAll();
 
    // Sort the basket so the items are grouped together by name
    BasketItemCollection _BasketItems = _Basket.Items;
    _BasketItems.Sort("Name");
 
    // We have all basket items broken into separate lines
    // Create unique shipment for each basket item that doesn't already have a shipment assigned to it
    foreach (BasketItem _BasketItem in _BasketItems)
    {
        // skip basket item if not a product
        if (_BasketItem.OrderItemType != OrderItemType.Product)
            continue;
 
        // make new shipment
        BasketShipment _Shipment = new BasketShipment();
        _Shipment.BasketId = _Basket.BasketId;
        _Shipment.WarehouseId = _BasketItem.Product.WarehouseId;
        _Shipment.AddressId = Token.Instance.User.PrimaryAddress.AddressId;
        _Shipment.Save();
 
        // add new shipment to basket
        _Basket.Shipments.Add(_Shipment);
 
        // assign this basket item to the new shipment
        _BasketItem.BasketShipmentId = _Shipment.BasketShipmentId;
        _BasketItem.Save();
 
        //// reset the parentitemid value since now this item is its own basket item record
        _BasketItem.ParentItemId = _BasketItem.BasketItemId;
        _BasketItem.Save();
 
    }
 
    // save the basket
    _Basket.Save();
 
}

Tags: , , ,

AC7 Articles

Month List