Documentation Home

Customizing Requests

There is a pre-configured component called com.broadleafcommerce.vendor.avalara.tax.gateway.soap.TaxSoapRequestGeneratorImpl that builds tax requests compatible with the Avalara SOAP API. This has a Spring Bean name of blAvalaraTaxSoapRequestGenerator. You can override this bean by extending the TaxSoapRequestGeneratorImpl, and overriding any of its public or protected methods. Broadleaf will use your custom implementation with a simple configuration addition to your core applicationContext.xml:

<bean id="blAvalaraTaxSoapRequestGenerator" class="com.mycompany.tax.MyTaxSoapRequestGenerator"/>

Here is an example of the implemenation:

public class MyTaxSoapRequestGenerator extends TaxSoapRequestGeneratorImpl {
   ...
}

You can override any of the methods provided in order to manipulate the generation of the tax calculation request. Many of the methods provide hooks for you to override, but do nothing (or return null) out of the box. For example:

/**
 * Allows one to override the VAT or Business Identification Code at the Fulfillment Group Item level.
 * @param item
 * @return
*/
protected String determineBusinessIdentificationCode(FulfillmentGroupItem item, AvalaraTaxModuleConfiguration config) {
    return null;
}

If you needed to provide this information, you have a hook or mechanism to simply override this method and the request will contain the data that you return.

Here are some additional, special cases that deserve some extra attention:

Order ID

A similar method that can be overriden looks like this:

protected String determineDocCode(Order order, AvalaraTaxModuleConfiguration config) {
    return String.valueOf(order.getId());
}

Avalara requires a document code (or DocCode). The default is to use the orderId. This is generally adequate. However, one thing to notes is that when taxes are "committed" to Avalara (which happens, by default, at checkout) the DocCode is stored on the Avalara servers. You cannot commit the same DocCode twice for a given Avalara account. For this reason, if you are using Avalara credentials in multiple environments (e.g. shared by developers, or shared across development and QA), then you need to ensure that the DocCodes are unique. This can be done by overriding this method and using a different, unique property such as a GUUID on the order, a pre-determined order number, or a unique range of primary keys for BLC_ORDER in each environent. Otherwise, each developer and/or environment would need to use a different Avalara account.

Item Code

protected String determineItemCode(FulfillmentGroupItem fgItem, AvalaraTaxModuleConfiguration config) {
    String skuId = null;
    OrderItem orderItem = fgItem.getOrderItem();
    if (orderItem instanceof DiscreteOrderItem) {
        DiscreteOrderItem discreteItem = (DiscreteOrderItem) orderItem;
        skuId = String.valueOf(discreteItem.getSku().getId());
    } else if (orderItem instanceof BundleOrderItem) {
        BundleOrderItem bundleItem = (BundleOrderItem) orderItem;
        skuId = String.valueOf(bundleItem.getSku().getId());
    } else if (orderItem instanceof GiftWrapOrderItem) {
        GiftWrapOrderItem giftItem = (GiftWrapOrderItem) orderItem;
        skuId = String.valueOf(giftItem.getSku().getId());
    }
    String upcCode = determineUpcCode(fgItem, config);
    if (StringUtils.isNotBlank(upcCode)) {
        return new StringBuilder(upcCode).append('-').append(skuId).toString();
    }
    return skuId;
}

The above method uses the ID of the SKU for the item code that is passed to Avalara. This allows for a direct reference back to the SKU when reporting taxes. This can be completely overridden to provide a different reference to the Item Code. One thing to notice here is that it queries the determineUpcCode(...) to attempt to build a hyphen (-) separated code. See UPC Code below for more information on this.

UPC Code (Universal Product Code)

Avalara provides a service called MatrixMaster that allows tracking and calculation of taxes at the UPC level. Contact Avalara to activate this service. This service makes use of a specific Item Code format. In particular, it expects a String that is the UPC code followed by a hyphen (-), followed by the original item code (e.g. Sku ID). For example, 123456789-123. The method to determineItemCode invokes a method called determineUpcCode(...). The default implementation returns null:

protected String determineUpcCode(FulfillmentGroupItem fgItem, AvalaraTaxModuleConfiguration config) {
    return null;
}

You can override this method and determine UPC code, for example, from an extended SKU entitiy. For example:

protected String determineUpcCode(FulfillmentGroupItem fgItem, AvalaraTaxModuleConfiguration config) {
    String sku = null;
    OrderItem orderItem = fgItem.getOrderItem();
    if (orderItem instanceof DiscreteOrderItem) {
        DiscreteOrderItem discreteItem = (DiscreteOrderItem) orderItem;
        sku = discreteItem.getSku();
    } else if (orderItem instanceof BundleOrderItem) {
        BundleOrderItem bundleItem = (BundleOrderItem) orderItem;
        sku = bundleItem.getSku();
    } else if (orderItem instanceof GiftWrapOrderItem) {
        GiftWrapOrderItem giftItem = (GiftWrapOrderItem) orderItem;
        sku = giftItem.getSku();
    }
    if (sku != null && MySku.class.isAssignableFrom(sku.getClass())) {
        return ((MySku)sku).getUpcCode();
    }
    return null;
}

NOTE: As of Broadleaf version 4.0, UPC is available on the default Sku entity.