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();
 
}