Interface IShippingCalculator

Shipping calculator calculates shipping totals

Namespace: EPiServer.Commerce.Order
Assembly: Mediachase.Commerce.dll
Version: 10.8.0
Syntax
public interface IShippingCalculator
Examples
    /// <summary>
/// Sample implementation of <see cref="IShippingCalculator"/>.
/// </summary>
public class ShippingCalculatorSample : IShippingCalculator
{
private readonly ILineItemCalculator _lineItemCalculator;
private readonly ServiceCollectionAccessor<IShippingPlugin> _shippingPluginsAccessor;
private readonly IReturnLineItemCalculator _returnLineItemCalculator;
private readonly ITaxCalculator _taxCalculator;

public ShippingCalculatorSample(
ILineItemCalculator lineItemCalculator,
IReturnLineItemCalculator returnLineItemCalculator,
ITaxCalculator taxCalculator,
ServiceCollectionAccessor<IShippingPlugin> shippingPluginsAccessor)
{
_lineItemCalculator = lineItemCalculator;
_returnLineItemCalculator = returnLineItemCalculator;
_taxCalculator = taxCalculator;
_shippingPluginsAccessor = shippingPluginsAccessor;
}

[Obsolete("This method is no longer used, use IOrderGroupCalculator.GetShippingSubTotal instead.")]
public Money GetShippingCost(IOrderGroup orderGroup, IMarket market, Currency currency)
{
var orderGroupCalculator = ServiceLocator.Current.GetInstance<IOrderGroupCalculator>();
return orderGroupCalculator.GetShippingSubTotal(orderGroup);
}

[Obsolete("This method is no longer used, use IOrderFormCalculator.GetShippingSubTotal instead.")]
public Money GetShippingCost(IOrderForm orderForm, IMarket market, Currency currency)
{
var orderFormCalculator = ServiceLocator.Current.GetInstance<IOrderFormCalculator>();
return orderFormCalculator.GetShippingSubTotal(orderForm, market, currency);
}

public Money GetShippingCost(IShipment shipment, IMarket market, Currency currency)
{
var zeroMoney = new Money(0m, currency);
var allShippingMethods = ShippingManager.GetShippingMethods(string.Empty);
var row = allShippingMethods.ShippingMethod.FindByShippingMethodId(shipment.ShippingMethodId);

if (row == null)
{
    return zeroMoney;
}

var type = Type.GetType(row.ShippingOptionRow.ClassName);
var provider = _shippingPluginsAccessor().First(s => s.GetType() == type);

var message = string.Empty;
var rate = provider.GetRate(market, row.ShippingMethodId, shipment, ref message);

if (rate == null)
{
    throw new Exception(string.Format("There is no rate configured for the shipping method {0}: {1}",
        row.ShippingOptionRow.ClassName, message));
}

if (!CurrencyFormatter.CanBeConverted(rate.Money, currency))
{
    throw new InvalidOperationException(
        string.Format("Cannot convert selected shipping's currency({0}) to the target currency({1}).",
            rate.Money.Currency.CurrencyCode, currency.CurrencyCode));
}

return CurrencyFormatter.ConvertCurrency(rate.Money, currency);
}

public Money GetDiscountedShippingAmount(IShipment shipment, IMarket market, Currency currency)
{
//It's the shipping cost with all shipping discounts applied on the shipment.
return GetShippingCost(shipment, market, currency) - shipment.GetShipmentDiscountPrice(currency);
}

public Money GetShippingItemsTotal(IShipment shipment, Currency currency)
{
var itemsTotalAmount = shipment.LineItems
    .Where(x => x.Quantity > 0 && !x.IsGift) // Gift items should not be included in the calculation.
    .Sum(lineItem => _lineItemCalculator.GetDiscountedPrice(lineItem, currency).Amount);

return new Money(itemsTotalAmount, currency);
}

public Money GetShippingReturnItemsTotal(IShipment shipment, Currency currency)
{
//NOTE: the shipment must belong to an IReturnOrderForm.
var itemsTotalAmount = shipment.LineItems.OfType<IReturnLineItem>()
    .Where(x => x.ReturnQuantity > 0 && !x.IsGift) // Gift items should be excluded from the calculation.
    .Sum(returnLineItem => _returnLineItemCalculator.GetDiscountedPrice(returnLineItem, currency).Amount);

return new Money(itemsTotalAmount, currency);
}

public Money GetShipmentDiscountPrice(IShipment shipment, Currency currency)
{
return shipment.GetShipmentDiscountPrice(currency);
}

public ShippingTotals GetShippingTotals(IShipment shipment, IMarket market, Currency currency)
{
var shippingSubtotal = GetShippingItemsTotal(shipment, currency);
var shippingCost = GetShippingCost(shipment, market, currency);
var shippingTax = GetShippingTax(shipment, market, currency);
var lineItemPricesDictionary = shipment.LineItems.ToDictionary(item => item, item => _lineItemCalculator.GetLineItemPrices(item, currency));

return new ShippingTotals(shippingSubtotal, shippingCost, shippingTax, lineItemPricesDictionary);
}

public Money GetShippingTax(IShipment shipment, IMarket market, Currency currency)
{
var shipmentSubtotal = GetShippingItemsTotal(shipment, currency);
return CalculateShippingTax(shipment, market, currency, shipmentSubtotal,
    (item, curr) => _lineItemCalculator.GetDiscountedPrice(item, curr),
    item => item.Quantity);
}

public Money GetSalesTax(IShipment shipment, IMarket market, Currency currency)
{
var shippingAddress = shipment.ShippingAddress;
if (shippingAddress == null)
{
    // The tax rate depends on the shipping address - where line items will be shipped to.
    return new Money(0m, currency);
}

var salesTaxAmount = shipment.LineItems
    .Where(x => x.Quantity > 0 && !x.IsGift) // Gift items should be excluded from the calculation.
    .Sum(item => _lineItemCalculator.GetSalesTax(item, market, currency, shippingAddress).Amount);

return new Money(salesTaxAmount, currency);
}

public Money GetReturnShippingTax(IShipment shipment, IMarket market, Currency currency)
{
var shipmentSubtotal = GetShippingReturnItemsTotal(shipment, currency);
return CalculateShippingTax(shipment, market, currency, shipmentSubtotal,
    (item, curr) => _returnLineItemCalculator.GetDiscountedPrice((IReturnLineItem)item, curr),
    item => item.ReturnQuantity);
}

public Money GetReturnSalesTax(IShipment shipment, IMarket market, Currency currency)
{
var shippingAddress = shipment.ShippingAddress;
if (shippingAddress == null)
{
    // The tax rate depends on the shipping address - where line items will be shipped to.
    return new Money(0m, currency);
}

var returnSalesTaxAmount = shipment.LineItems.OfType<IReturnLineItem>()
    .Where(x => x.ReturnQuantity > 0 && !x.IsGift) // Gift items should be excluded from the calculation.
    .Sum(returnItem => _returnLineItemCalculator.GetSalesTax(returnItem, market, currency, shippingAddress).Amount);

return new Money(returnSalesTaxAmount, currency);
}

public ShippingTotals GetReturnShippingTotals(IShipment shipment, Currency currency)
{
var zeroMoney = new Money(0, currency);
var total = GetShippingReturnItemsTotal(shipment, currency);
var lineItemPrices = shipment.LineItems
    .ToDictionary(item => item, item => _returnLineItemCalculator.GetLineItemPrices((IReturnLineItem)item, currency));

// A return shipment doesn't include any shipping cost and shipping tax.
return new ShippingTotals(total, zeroMoney, zeroMoney, lineItemPrices);
}

private Money CalculateShippingTax(
IShipment shipment,
IMarket market,
Currency currency,
Money shipmentSubtotal,
Func<ILineItem, Currency, Money> getDiscountedPriceFunction,
Func<ILineItem, decimal> getQuantityFunction)
{
// The tax rate depends on the shipping address - where line items will be shipped to.
if (shipment.ShippingAddress == null)
{
    return new Money(0m, currency);
}

var shippingTax = 0m;
var shippingSubTotal = GetDiscountedShippingAmount(shipment, market, currency).Amount;
var lineItemsQuantity = shipment.LineItems.Sum(lineItem => getQuantityFunction(lineItem));

foreach (var item in shipment.LineItems)
{
    var quantity = getQuantityFunction(item);
    if (quantity <= 0)
    {
        continue;
    }

    //The base price used to calculate shipping tax for a line item is the discounted price of the line item distributed on every quantity of the line item.
    var itemDiscountedPrice = getDiscountedPriceFunction(item, currency).Amount;
    var itemShippingSubTotalAmount = shippingSubTotal * (shipmentSubtotal.Amount == 0 ? quantity / lineItemsQuantity : itemDiscountedPrice / shipmentSubtotal.Amount);
    var itemShippingSubTotal = new Money(itemShippingSubTotalAmount, currency);

    shippingTax += _taxCalculator.GetShippingTax(item, market, shipment.ShippingAddress, itemShippingSubTotal).Amount;
}

return new Money(shippingTax, currency).Round();
}
}

Methods

GetDiscountedShippingAmount(IShipment, IMarket, Currency)

Gets the discounted shipping amount for the shipment

Declaration
Money GetDiscountedShippingAmount(IShipment shipment, IMarket market, Currency currency)
Parameters
Type Name Description
IShipment shipment

The shipment

IMarket market

The market to be used in the calculation.

Currency currency

The currency to be used in the calculations

Returns
Type Description
Money

The discounted subtotal of the shipment.

Examples

GetShipmentDiscountPrice(IShipment, Currency)

Gets the shipment discount price.

Declaration
Money GetShipmentDiscountPrice(IShipment shipment, Currency currency)
Parameters
Type Name Description
IShipment shipment

The shipment.

Currency currency

The currency.

Returns
Type Description
Money

The shipment discount price.

GetShippingCost(IOrderForm, IMarket, Currency)

Gets the shipping cost of the orderForm

Declaration
Money GetShippingCost(IOrderForm orderForm, IMarket market, Currency currency)
Parameters
Type Name Description
IOrderForm orderForm

The order form

IMarket market

The market to be used in the calculation.

Currency currency

The currency to be used in the calculations

Returns
Type Description
Money

The shipping cost of the order form.

Examples

GetShippingCost(IOrderGroup, IMarket, Currency)

Gets the shipping cost of the orderGroup

Declaration
Money GetShippingCost(IOrderGroup orderGroup, IMarket market, Currency currency)
Parameters
Type Name Description
IOrderGroup orderGroup

the order group

IMarket market

The market to be used in the calculation.

Currency currency

The currency to be used in the calculations

Returns
Type Description
Money

The shipping cost of the order group.

Examples

GetShippingCost(IShipment, IMarket, Currency)

Gets the shipping cost of the shipment

Declaration
Money GetShippingCost(IShipment shipment, IMarket market, Currency currency)
Parameters
Type Name Description
IShipment shipment

The shipment

IMarket market

The market to be used in the calculation.

Currency currency

The currency to be used in the calculations

Returns
Type Description
Money

The shipping cost of the shipment.

Examples

GetShippingItemsTotal(IShipment, Currency)

Gets the total of extended prices for all line items in the shipment.

Declaration
Money GetShippingItemsTotal(IShipment shipment, Currency currency)
Parameters
Type Name Description
IShipment shipment

The shipment

Currency currency

The currency to be used in the calculations

Returns
Type Description
Money

The subtotal of the shipment.

Examples