ABF shipping gateway base written and working

by Joe Payne 2. February 2014 09:13

Spent some time this morning and put together the complete shell for an ABF shipping gateway in AbleCommerce Gold.    It’s only purpose is to provide tracking URL support for ABF shipments when marking orders as shipped.

It was interesting how Able has implemented a default provider interface, leveraged embedded resources and connected it all to specific configure and register pages in the admin.  I’ve worked on various shipping gateway pieces several times, but never a brand new AbleCommerce Gold gateway implementation.   Kinda slick how they did it.

I have to see if ABF will approve my request for an account.  It’s needed to access their API.   If I can get API access, I can build a fully functional gateway.

Now that the learning curve is over, it will be far easier for me to build new shipping gateways in AbleCommerce Gold.

Tags: ,

AbleCommerce Gold | Personal

Troubleshoot FedEx gateway responses in AbleCommerce Gold

by Joe Payne 1. November 2013 11:05

Here are some useful tips for troubleshooting the FedEx shipping gateway in AbleCommerce Gold.   

Occasionally you might have the situation where you do not see any shipping rates from FedEx.  This can happen during checkout, or even with the basket shipping estimator control.

image

The first step is to turn on the Debug Logging in the shipping gateway configuration as shown here.

Now every gateway request and response will be recorded to a log file found in the website.  The file is ~/App_Data/Logs/AblePlugins.FedEx.Log

To access this log file, you will either need to access your server console or have FTP access to the site.

With debug mode enabled, go make a rate request using any means you want.   Add an order through the backend, go to page 4 in checkout, or simply use the basket shipping estimator from the basket page.

Once you’ve triggered the rate request, now open the FedEx log file.   You will see a LOT of XML communication, this is how the plugin talks with the FedEx servers.  Search the file for any references to <ServiceType>

In the service type XML tag, you’ll see the actual service name being calculated.   It could say PRIORITY_OVERNIGHT or GROUND or INTERNATIONAL_STANDARD etc.   Each service type response is a valid shipping method for the given location you submitted.

If you don’t have those particular service types configured as shipping methods in AbleCommerce, you won’t see a shipping rate.   So just add an Integrated Carrier shipping method for each of the ServiceType responses you see in the log file.   Make sure you leave it configured for All Warehouses, All Zones, All Groups.  You can always change those values later.

Now request another rate estimate by either refreshing the page or using the shipping estimator.  You should see rates for shipping methods.

When dealing with international FedEx, this is the easiest way to figure out what exact shipping methods are being sent back to Able from FedEx.

Don’t forget to disable the Debug Mode on the integrated shipping carrier configuration page when you are done!

Tags: , , , ,

AbleCommerce Gold | Tech Support

Configuring AbleCommerce Gold Shipping Estimator for international addresses

by Joe Payne 1. November 2013 10:50

Came across an interesting challenge today with an Able Gold R1 install.   An international client could not get the shipping estimator to return rates for international addresses.

You could choose the destination country from the dropdown list and click the button.  But no rates were returned.

The site was configured to use the FedEx integrated shipping provider.   Yet the estimator would only give FedEx rates if it was given a US location.

After digging through the code and the FedEx debug log responses, I figured out something I didn’t realize.  AbleCommerce keeps a manual list of what countries require a postal code.   This list, by default, only includes US and CA.

FedEx requires a postal code when calculating rates.  And the shipping estimator control must prompt for the postal code for shipments to countries that require a postal code. 

imageTo make the shipping estimator control prompt for the postal code (zip code) for specific countries, go into the Admin Configure/Store/General and add all the desired country codes to the Locale Settings.

Shipping Estimator will read this list and only show the postal code input field when the selected country code is one of the codes listed in this field.

 

 

 

Now that the shipping estimator knows to prompt for postal code for your selected country, it will send enough information to FedEx to get a shipping rate quote.

Tags: , , ,

Tech Support | AbleCommerce Gold

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