Concept - Shipping

Introduction

Intention

For an internationally operating store, it is necessary to have a flexible and generally valid shipping component.

It is required to charge shipping costs according to the location to which the items will be shipped. It must be possible to have different shipping methods whose costs may vary depending on the destination and the attributes of the shipment itself.

Different products must be classified according to their shipping requirements, like products that can only be shipped individually. The Web store must be able to identify such products and charge them differently, if necessary.

Furthermore, the customer should be able to have individual line items of his cart shipped to different locations. Such apportionments must be viewable by customers, modifiable and must be included in the shipping charge calculation.

The shop manager needs the ability to provide different shipping costs for certain products, like additional costs or different shipping charges.

Locations need to be known to the Web store, that is, the Web store has to be able to recognize a certain location. There must be a mapping between geographical objects of the "real world" (like a city, a country, a postal code), and objects which the shop manager can manipulate, like defining shipping costs and rules for them.

Due to legal restrictions and certain business needs, the shipping components must provide more flexible rules. While via assigning a shipping method to a destination, you can define positive rules (which enable shipping), the shop manager needs the power to control exceptions. Certain products are forbidden in some countries, some will cost an extra fee, some raise extra shipping costs.

Therefore, a rule handling is needed to override the general shipping configuration and handle such exceptions, because they have huge impact on the business itself.

References

Have a look at the corresponding cookbook for related common questions.

Shipping Artifacts

Geo Objects and Destination Regions

A shipping engine must handle geographical objects and aggregate them to useful, business-relevant units. Thus, the shipping engine needs two artifacts:

  • The geo object, which represents a real geographic object and
  • A destination region, which aggregates them and enables them to be given a name.

Geo Object

Geo objects represent countries, states, provinces, counties, cities or postal codes (or anything that may reasonably be called a distinguishable location). They are stored once per installation, as they are considered master data that should not differ across multiple stores. There is no UI to manage geo objects, but there is the ability to import/export them at the central administration level (Operations).

Destination Region

A destination region aggregates one-to-many geo objects to a named region. Regions can be mutually exclusive (like the region GB has the excluded region Channel Islands, so the geo objects of the Channel Islands will not be part of the region GB).

As opposed to the geo objects, destination regions are managed at channel level.

Freight Classes and Shipping Methods

A freight class is a classification element to identify and group similar products from a shipping point of view. It specifies how a product is shipped and where it can be shipped.

Shipping methods represent a carrier (abstract). They are used to display the carrier at the service level in the storefront. Each shipping method has at least one shipping charge plan. In the standard implementation, there are five types of charge plans: weight based, (order) value based, item count based, flat rate and flex based (several charge plans, with a certain selector). Charge plans can be copied or shared from other shipping methods.

Shipping Eligibility

Shipping Rules

The concept of shipping rules allow to freely create rules, not just configuring some predefined restrictions.

Each rule consists of three parts:

  • Body, with name, localized description etc,
  • Condition, where several atomic conditions (like product's SKU is 123321) are linked via AND or OR relations, and
  • Action, which basically defines what is the consequence if that rule is true.

The shipping rules created via the UI are stored in the database using the data model of promotion rules. But the shipping rules are actually translated from the data model of bc_ruleengine to the business rule language that can be processed via the rule engine. So this requires some kind of mapping software, the ShippingRuleMapper. This component is configurable via an XML file named shippingruleconfiguration.xml, which can be provided with every cartridge.

Note

When a new configuration is loaded with a new cartridge, the new settings overwrite the existing ones. That is, the last cartridge wins, and overwritten configurations are no longer effective.

Shipping Conditions and Actions UI

The number of selectable conditions is determined by the different instances of condition descriptors registered at the ShippingConditionDescriptorRegistry. For further information of that concept, please refer to the   promotions framework description.

The selectable actions are generally hard-coded in the ShippingRuleAction_52 template.

Shipping Rule Business Objects

Due to the fact that persistent objects are not transferable and are mostly related to other complex types, there is a mapping to "simpler" business objects, which the rule engine can easily handle. There are some predefined types. The necessary information of the persistent objects (POs) or the business objects (BOs) of the business object framework is mapped to simple, easy-to-handle objects, which will be transferred to the working memory of the rule engine. (The rule engine can also handle the POs or BOs directly, but Intershop strongly recommends to avoid this functionality.)

Shipping rule business objects are always created by their factory. Objects that need to provide the ability for extension extend the AbstractExtensibleObject. Every factory needs to be registered at the ShippingRuleObjectMapper via the component framework.

In the current implementation, the following factories and their according objects are available:

  • BillToCountryFactory
    • BillToCountry
  • BillToLocationFactory
    • BillToLocation
  • BillToRegionFactory
    • BillToRegion
  • BillToStateProvinceFactory
    • BillToStateProvince
  • CatalogCategoryFactory
    • CatalogCategory
  • ConsumerGroupFactory
    • ConsumerGroup
  • CountryFactory
    • Country
  • FreightClassFactory
    • FreightClass
  • LocationFactory
    • Location
  • ProductFactory
    • Product
  • RegionFactory
    • Region
  • ShippingMethodFactory
    • ShippingMethod
  • StateProvinceFactory
    • StateProvince

Shipping Rule Execution

The ShippingRuleExecutor is the component that actually executes rules, that is, the one that processes the in-going information, starts a rule engine session, and processes the results to make them usable in further business processes.

These are classes that implement the AbstractRuleExecutor and an interface for special needs (i.e., the intended input and output for convenience). The mapping, if necessary, is done inside that class as well as the rule execution.

There are different types of ShippingRuleExecutors, distinguished by their purpose (what are the parameters, and what kind of result is expected).

For every shipping rule action, there is a dedicated rule executor instance created via the component framework:

Shipping Action

Shipping Rule Executor Component

Shipping Rule Executor Class

Item: Surcharge

shippingSurchargeRuleExecutor

ShippingExtraChargeRuleExecutor

Item: Import Surcharge

shippingImportSurchargeRuleExecutor

ShippingExtraChargeRuleExecutor

Item: Geographical Surcharge

shippingGeographicalSurchargeRuleExecutor

ShippingExtraChargeRuleExecutor

Item: Exclude from Shipping

shippingRestrictionRuleExecutor

RestrictionRuleExecutor

Item: Override Shipping Charge

shippingOverrideRuleExecutor

ShippingExtraChargeRuleExecutor

Item: Eligible Shipping Method

shippingEligibilityRuleExecutor

ShippingEligibilityRuleExecutor

Bucket: Surcharge

shippingBucketSurchargeRuleExecutor

ShippingExtraChargeRuleExecutor

Bucket: Override Shippping Charge

shippingBucketBucketOverrideRuleExecutor

ShippingExtraChargeRuleExecutor

Storefront and Calculation

Shipping Charge Plan Tax Calculation

There are 5 different types of plans how to spread the shipping costs on the line items. This means also a different tax calculation for them.

Example:

There is a basket with 3 line items.

  1. Line Item with product A full tax (20%) with an amount of 50 € and weight of 1000g.
  2. Line Item with product B reduced tax(10%) with an amount of 30 € and weight of 2000g.
  3. Line Item with product C no tax(0%) with an amount of 20 € and weight of 3000g.

It is a total basket amount of 100 €.

The shipping costs are set on 10 €. All values are net amounts.

Note

The default splitting of the shipping costs on the line items is the Item Count Based. If the default is not defined the Weight Based is taken.

Scenario Flat Rate

The 10 € are divided equal on the 3 line items. So there are 3.33 € for each line item. For the first line there is 20% tax, so the shipping tax amount for this line item is 3.33 € * 0.20 = 0.67 €.

For the second line it is 3.33 € * 0.10 = 0.33 €.

And finally for the last there is no tax, so the total shipping tax is 0.67 € + 0.33 € = 1.00 €.

Scenario Weight Based

In the Weight Based case the 10 € is divided as followed: total weight/line item weight * shipping amount.

For line item 1 it is 1000g/6000g * 10 € = 10/6 € = 1.67 €.

For line item 2 it is 2000g/6000g * 10 € = 10/3 € = 3.33 €.

For line item 3 it is 3000g/6000g * 10 € = 10/2 € = 5.00 €.

The shipping tax is for line item 1 is 1.67 € * 0.2 = 0.33 €.

The shipping tax is for line item 2 is 3.33 € * 0.1 = 0.33 €.

For the last line item there is no tax, so the total tax is 0.66 €.

Scenario Order Value Based

In this case the 10 € is divided as followed: total basket amount/line item amount * shipping amount.

For line item 1 it is 50 €/100 € * 10 € = 0.5 * 10 € = 5 €.

For line item 1 it is 30 €/100 € * 10 € = 3/10 * 10 € = 3 €.

For line item 1 it is 20 €/100 € * 10 € = 2/10 * 10 € = 2 €.

The shipping tax is for line item 1 is 5 € * 0.2 = 1 €.

The shipping tax is for line item 2 is 3 € * 0.1 = 0.3 €.

For the last line item there is no tax, so the total tax is 1.3 €.

Scenario Item Count Based

This scenario is taxation wise calculated identically to Flat Rate scenario. The difference here is only that different total shipping amounts can be defined in respect to the total quantity of the basket items.

Scenario Advanced

In this scenario the total shipping costs and the shipping charge plan can be defined independently. But in the end, the selected shipping charge plan defines the tax calculation.

Note

These rules are also applied to distribute the bucket surcharges (including surcharge tax) to the line items.

Shipping Bucket

A shipping bucket is an aggregation of line items.


In the reference implementation, line items of a shipping bucket have the same destination and the same shipping method (BasketShippingBucketBO). There is also an BasketShippingMethodSelectionBucketBO. As this kind of bucket is used for storefront user interaction purposes (like selecting a shipping option for several buckets), the key used for its creation is not only the destination and the selected shipping method, but also the set of shipping methods that is eligible for every line item.

For this the standard comes with two kind of bucket interfaces. Those instances are created by one of the 2 composer that comes with the Intershop standard implementation.

While the basic ShippingBucketComposer interface represents functionality that is used to do a real composing inside the basket calculation which is saved in an attribute of the basket table.
The BasketShippingMethodSelectionBucketComposer is used to offer grouping functionality in the shipping method selection step only. Its results are transient.

The Business Object Layer offers 2 extensions for both use cases.

BasketBOShippingBucketExtension
/**
 * This extension covers all shipping bucket related functionality for the basket
 * business object.
 */
public interface BasketBOShippingBucketExtension extends BusinessObjectExtension<BasketBO>
{
    /**
     * The ID of the created extensions which can be used to get them from the business object later.
     */
    public static final String EXTENSION_ID = "ShippingBucket";
    /**
     * Returns shipping buckets composed from the line items in this line item
     * container. Composition is done based on:
     * <ul>
     * <li>ship-to address
     * <li>ship-from address
     * <li>shipping method
     * <ul>
     * whereas the ship-from address is optional. A specific line item can be
     * only assigned to one shipping bucket at the same time.
     *
     * @return shipping buckets composed from the line items in this line item
     *         container
     */
    public Collection<BasketShippingBucketBO> getBasketShippingBucketBOs();

    /**
     * Returns a shipping bucket which covers all product line items with the
     * provided address, shipping method and ship alone flag.
     * 
     * @param address
     *            the address
     * @param shippingMethod
     *            the shipping method
     * @param shipAlone
     *            the isShipAlone flag
     * @return the shipping bucket
     */
    public BasketShippingBucketBO getBasketShippingBucketBO(AddressBO address, BasketShippingMethodBO shippingMethod,
                                                            boolean shipAlone);

}
BasketBOShippingMethodExtension
/**
 * This extension covers all shipping method related functionality for the
 * basket business object.
 * 
 * @author Frank E. Hofmann
 * 
 */
public interface BasketBOShippingMethodExtension extends BusinessObjectExtension<BasketBO>
{
    /**
     * The ID of the created extensions which can be used to get them from the
     * business object later.
     */
    public static final String EXTENSION_ID = "ShippingMethod";
    
    public Collection<BasketShippingMethodSelectionBucketBO> getBasketShippingMethodSelectionBucketBOs();
    
    /**
     * Returns a collection of bucket but filtered. This version does not contains digital shipping buckets
     * like E-Mail-Shipping Buckets.
     * 
     * @return A collection of buckets.
     */
    public Collection<BasketShippingMethodSelectionBucketBO> getNonDigitalBasketShippingMethodSelectionBucketBOs();
    
    public Set<BasketShippingMethodSelectionBucketBO> getBasketShippingMethodSelectionBucketBOsAsSet();
    
    public Collection<EligibleShippingMethodBO> getEligibleShippingMethodBOs();
      
    /**
     * Returns a shipping bucket which covers all product line items with the
     * provided address, shipping method and ship alone flag.
     * 
     * @param address
     *            the address
     * @param shippingMethod
     *            the shipping method
     * @param shipAlone
     *            the isShipAlone flag
     * @return the shipping bucket
     */
    public BasketShippingMethodSelectionBucketBO getBasketShippingMethodSelectionBucketBO(AddressBO address,
                    BasketShippingMethodBO shippingMethod, boolean shipAlone);
}
public interface ShippingBucketComposer
{
    public List<ShippingBucket> composeShippingBuckets(LineItemCtnr lineItemCtnr);

    public List<ShippingBucket> composeShippingBuckets(Set<LineItem> lineItemSet);
}

All shipping-related independent business component implementations, contracts and instances are defined in bc_shipping.

bc_shipping
└───staticfiles
    └───cartridge
       └───components
           └───implementations.component

Hence, the current definition of the shipping bucket composer is:

contracts.component
<components xmlns="http://www.intershop.de/component/2010">
  <contract name="ShippingBucketComposer"
            class="com.intershop.component.shipping.capi.shippingbucketcomposer.ShippingBucketComposer" />
</components>

Calculation

The calculation is split into several steps, which correspond to the different charges that may apply to a bucket or a ProductLineItem, and the hierarchy of the different charges between each other.

The entire calculation is done via the following rules, which are a part of the calculation rule set.

Rule

Description

ShippingBucketCreationRule

Creates the buckets used for calculation

ShippingExtraChargeCalculatorRule

Determines all additional charges that may be applied

ShippingPLIChargeCalculatorRule

Does the individual calculation of the bucket costs according to the line items, and splits the bucket costs down to PLI costs

ShippingGroupedChargeCalculatorRule

Sums surcharges grouped by the identifier of the rule that adds the surcharge

CalculateTaxSumsPerRateRule

Separates all taxes by its tax rates

BucketCostDistributionRule

Distributes the amount of surcharges

AddMoneyRule

Determines the total shipping costs finally

RoundMoneyRule

Rounds the given money items

MultiplyMoneyWithPercentageRule

Multiplies prices with an percentage value

Note

 A bucket depends from service line Items that are created within the SetSelectedShippingMethod pipelet by the class ShippingMethodHandler.

Disclaimer
The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.
Home
Knowledge Base
Product Releases
Log on to continue
This Knowledge Base document is reserved for registered customers.
Log on with your Intershop Entra ID to continue.
Write an email to supportadmin@intershop.de if you experience login issues,
or if you want to register as customer.