How to add free item to the basket during checkout in AbleCommerce 7

by Joe Payne 26. March 2011 10:11

Introduction

 

This short tutorial describes a common need in AbleCommerce storefronts.  You are going to see line-by-line descriptions of the tasks required and how they are accomplished with my code.  At the end, the full source code is available free for you to use as you wish.  If you want to skip the entrée and go straight to the dessert, scroll to the bottom of this post.

 

The Need

 

You want to offer your shoppers a freebie when their order total exceeds a specific amount.  Currently AbleCommerce has coupons, but coupons don’t offer this particular functionality.  Plus coupons require the shopper to enter something.  In this case, we want the freebie to be completely automatic.

 

How It Works

 

These changes are heavily commented so you can walk through the experience yourself.    All of this work is done in the OnePageCheckout.ascx.cs file.   The code itself is loaded at the very beginning of the Page_Init() function.  Remember the entire code snippet is included at the bottom of this article.

 

The routine starts by making sure we’re not on a postback.  If we’re on a postback, that means all the remaining logic has already been executed in some previous page life cycle;  since the basket cannot be altered while within the checkout page itself, there’s no need to perform the free-item check again.

if (!Page.IsPostBack)
{

 

Next we set some variables we’re going to need for this modification.  The first variable _FreeProductId represents the ProductId value of the product you want to give away for free.  It’s important to remember that you should have this product marked as Hidden else shoppers will find it and try to buy it with every order. 

The second variable is our basket total threshold.  If the basket total (of products only) meets or exceeds this amount, it qualifies for the free item.

Feel free to adjust these values to suit your particular need.

// set the product ID of the free item we want to add
int _FreeProductId = 42;
 
// set the dollar amount threshold of the basket total we want
LSDecimal _MinBasketTotal = 1000;

 

Now we need to scan the basket.  In AC7, this is easily done with the Basket class object contained in the global Token instance.  We have to look through every item in the basket.  If it’s a product-type item, we add it’s dollar total to the grand total.  We also record whether the basket item is our free item i.e. is the free item already in the basket.

// build a basket total and scan the basket for existing free item
int _FreeItemBasketItemIndex = -1;
LSDecimal _BasketTotal = 0;
for (int x=0;x < Token.Instance.User.Basket.Items.Count;x++)
{
    // pull in the basket item object
    BasketItem _BasketItem = Token.Instance.User.Basket.Items[x];
 
    // if it's a product, add it to our total
    if (_BasketItem.OrderItemType == OrderItemType.Product)
        _BasketTotal += _BasketItem.ExtendedPrice;
 
    // if it's the free item, set the ID so we can check later if the free item
    // is already in the basket
    if (_BasketItem.ProductId == _FreeProductId)
        _FreeItemBasketItemIndex = x;
}

 

Now for the real work.  We have to determine if the basket even qualifies for a free item.  If it does, AND the free item doesn’t already exist in the basket, we have some work to do.  First we build a new BasketItem object called _FreeItem with a quantity 1.  Then we add the item to the current shoppers basket and save the basket.

//see if basket total exceeds threshold
if (_BasketTotal >= _MinBasketTotal)
{
    // Ok basket qualifies for the free item
    // see if the free item already exists in basket
    // if the _FreeItemBasketItemId value is still -1, a free item was never found in the
    // current basket
    if (_FreeItemBasketItemIndex == -1)
    {
        // create a basketitem object for this free product
        BasketItem _FreeItem = BasketItemDataSource.CreateForProduct(_FreeProductId, 1);
 
        // add the item to the basket and save it
        Token.Instance.User.Basket.Items.Add(_FreeItem);
        Token.Instance.User.Basket.Save();
    }
}

 

If the basket doe NOT qualify, then we still have a little work to do.  We need to remove any free item already in the basket.  Since we recorded the index of the free item earlier in the code, it becomes a quick and easy check here.

else
{
    // basket doesn't qualify, get rid of the free item if it exists
    if (_FreeItemBasketItemIndex > -1)
    {
        // remove the item and save basket
        Token.Instance.User.Basket.Items[_FreeItemBasketItemIndex].Delete();
        Token.Instance.User.Basket.Save();
    }
}
        }
ND MOD: AbleMods.com

So that’s it.  You’ve tested the basket, added the item if necessary and made sure to remove it if the basket doesn’t qualify.

 

Summary

 

This routine was written for AbleCommerce v7.0.6 but should work in practically any flavor.   To make it work for your site, simply add all the code provided to the beginning of the Page_Init() function in OnePageCheckout.ascx.cs file found in the /ConLib/ folder of your AbleCommerce 7 installation.

 

As always, back up any original files before making changes to them.  Nothing ruins a shoppers experience more than a broken checkout page.

 

Be sure to check out all my modules available at http://www.AbleMods.com/

 

Full Source Code

// BEGIN MOD: AbleMods.com
// 3/26/2011
// This modification will add a specific product (presumably priced at 0 so it's free) if
// the basket total exceeds a specified dollar amount.  Only products are counted towards the 
// basket total.
 
// total up products in the basket
if (!Page.IsPostBack)
{
    // set the product ID of the free item we want to add
    int _FreeProductId = 42;
 
    // set the dollar amount threshold of the basket total we want
    LSDecimal _MinBasketTotal = 1000;
 
    // build a basket total and scan the basket for existing free item
    int _FreeItemBasketItemIndex = -1;
    LSDecimal _BasketTotal = 0;
    for (int x=0;x < Token.Instance.User.Basket.Items.Count;x++)
    {
        // pull in the basket item object
        BasketItem _BasketItem = Token.Instance.User.Basket.Items[x];
 
        // if it's a product, add it to our total
        if (_BasketItem.OrderItemType == OrderItemType.Product)
            _BasketTotal += _BasketItem.ExtendedPrice;
 
        // if it's the free item, set the ID so we can check later if the free item
        // is already in the basket
        if (_BasketItem.ProductId == _FreeProductId)
            _FreeItemBasketItemIndex = x;
    }
 
    //see if basket total exceeds threshold
    if (_BasketTotal >= _MinBasketTotal)
    {
        // Ok basket qualifies for the free item
        // see if the free item already exists in basket
        // if the _FreeItemBasketItemId value is still -1, a free item was never found in the
        // current basket
        if (_FreeItemBasketItemIndex == -1)
        {
            // create a basketitem object for this free product
            BasketItem _FreeItem = BasketItemDataSource.CreateForProduct(_FreeProductId, 1);
 
            // add the item to the basket and save it
            Token.Instance.User.Basket.Items.Add(_FreeItem);
            Token.Instance.User.Basket.Save();
        }
    }
    else
    {
        // basket doesn't qualify, get rid of the free item if it exists
        if (_FreeItemBasketItemIndex > -1)
        {
            // remove the item and save basket
            Token.Instance.User.Basket.Items[_FreeItemBasketItemIndex].Delete();
            Token.Instance.User.Basket.Save();
        }
    }
}
// END MOD: AbleMods.com

Tags: , , ,

AC7 Articles

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

QBWC sales tax are double taxed

by Joe Payne 25. March 2011 07:22

If you are using QBWC aka QuickBooks Web Connector to import invoices or sales receipts to your company file, you may see the sales getting double taxed.

This is caused by having sales tax calculated by the original source of the data (in my case AbleCommerce 7) and then again in QuickBooks.

The solution is to change the default sales tax setting in the QuickBooks company file.  QuickBooks likes to set the default taxable status of a customer to “Taxable”.  However in situations where the data is being imported from another app, it’s quite possible that taxes are already computed.

The setting is easy to find, once you know where it is.   First, load QB and open your desired company file.

Then choose the Edit menu and select ‘Preferences’

When the preferences load, select the Sales Tax category as shown here.   image

Now select the Company Preferences tab in the main window.  You’ll see a dropdown choice for “Your Most Common Sales Tax Item”.  Change that from whatever taxable tax code is listed to a non-taxable tax code.

image

 

If you have a non-taxable sales tax item, just click the Add Sales Tax Item… button to create a new one.

Tags: , , ,

AC7 Articles | QuickBooks Connector

How to edit existing blog posts with Windows Live Writer 2011

by Joe Payne 23. March 2011 09:04

I finally figured out how to edit existing posts in my blog using WLW 2011.  It’s actually simple but not obvious with the Microsoft style of menus and toolbars.

First you have to click the primary app menu in WLW that looks like this:  image_thumb

Then click on Open Recent Posts.  Don’t click a choice on the fly-out menu to the right, just click the menu option itself.

Finally, the traditional File/Open dialog appears.  On the left side you will see your specific name.  Click your name and all your previous blog posts are listed. image_thumb[1]

  From there you pick one, edit as needed and just click Publish to save it back to your blog.

So far I like WLW 2011 – does a good job where other web-based editors don’t.

Tags:

Personal

Odd web traffic statistics for my store/blog/support site

by Joe Payne 22. March 2011 09:29

You’d like my support pages, my product pages and my online store would get the most traffic.  Wrong!

I just started looking seriously at web traffic stats for my www.AbleMods.com web site.  Oh what interesting details have I found.  Take a look at the top pages in a site that sells software products.  Thank goodness at least ONE of my products actually made the Most Popular Pages top 10 list Smile

image

Tags: ,

Personal

Month List