November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
The following calculation services are available to calculate order totals in different levels.
When you create an order (cart, purchase order, or payment plan) through the IOrderRepository, a shipment is created. Order calculators calculate only line items that belong to a shipment. This is a changed behavior from the way it worked with workflow activities.
The IOrderGroupTotalsCalculator makes calculations for the IOrderGroup, its IOrderForms, IShipments, and ILineItems.
The method calls all calculators to calculate the values.
public void GetTotals(IOrderGroup orderGroup, IOrderGroupTotalsCalculator calculator)
{
var calculatedTotals = calculator.GetTotals(orderGroup);
Debug.WriteLine("Handling total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, calculatedTotals.HandlingTotal);
Debug.WriteLine("Shipping total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, calculatedTotals.ShippingTotal);
Debug.WriteLine("Sub total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, calculatedTotals.SubTotal);
Debug.WriteLine("Tax total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, calculatedTotals.TaxTotal);
Debug.WriteLine("Total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, calculatedTotals.Total);
foreach (var form in orderGroup.Forms)
{
var orderFormTotals = calculatedTotals[form];
Debug.WriteLine("Handling total for order form '{0}': {1}", form.OrderFormId, orderFormTotals.HandlingTotal);
Debug.WriteLine("Shipping total for order form '{0}': {1}", form.OrderFormId, orderFormTotals.ShippingTotal);
Debug.WriteLine("Sub total for order form '{0}': {1}", form.OrderFormId, orderFormTotals.SubTotal);
Debug.WriteLine("Tax total for order form '{0}': {1}", form.OrderFormId, orderFormTotals.TaxTotal);
Debug.WriteLine("Discount total for order form '{0}': {1}", form.OrderFormId, orderFormTotals.DiscountTotal);
Debug.WriteLine("Total for order form '{0}': {1}", form.OrderFormId, orderFormTotals.Total);
foreach (var shipment in form.Shipments)
{
var shipmentTotals = orderFormTotals[shipment];
Debug.WriteLine("Shipping cost for shipment '{0}': {1}", shipment.ShipmentId, shipmentTotals.ShippingCost);
Debug.WriteLine("Shipping tax for shipment '{0}': {1}", shipment.ShipmentId, shipmentTotals.ShippingTax);
Debug.WriteLine("Items total for shipment '{0}': {1}", shipment.ShipmentId, shipmentTotals.ItemsTotal);
foreach (var item in shipment.LineItems)
{
Debug.WriteLine("Extended price for '{0}': {1}", item.Code, shipmentTotals[item]);
}
}
}
}
The LineItemCalculator calculates a line item's extended price and discounted price.
public void GetExtendedPrice(ILineItem lineItem, ILineItemCalculator lineItemCalculator)
{
var extendedPrice = lineItemCalculator.GetExtendedPrice(lineItem, Currency.USD);
Debug.WriteLine("Extended price for '{0}': {1}", lineItem.Code, extendedPrice);
}
public void GetDiscountedPrice(ILineItem lineItem, ILineItemCalculator lineItemCalculator)
{
var extendedPrice = lineItemCalculator.GetDiscountedPrice(lineItem, Currency.USD);
Debug.WriteLine("Discounted price for '{0}': {1}", lineItem.Code, extendedPrice);
}
By inheriting from the default implementation of the interface, DefaultLineItemCalculator, you can override the extended price calculation. Just override the CalculateExtendedPrice method.
public class LineItemCalculatorSample : DefaultLineItemCalculator
{
protected override Money CalculateExtendedPrice(ILineItem lineItem, Currency currency)
{
var rawExtendedPrice = lineItem.PlacedPrice * lineItem.Quantity - ((LineItem)lineItem).LineItemDiscountAmount - ((LineItem)lineItem).OrderLevelDiscountAmount;
var result = rawExtendedPrice < 0 ? 0 : rawExtendedPrice;
return new Money(result, currency);
}
}
The default implementation validates that the extended price is not negative after the calculation. To change the behavior, override the ValidateExtendedPrice method.
public class LineItemCalculatorSample : DefaultLineItemCalculator
{
protected override void ValidateExtendedPrice(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Extended price must be greater than 0");
}
}
}
The ShippingCalculator calculates the shipping cost of an order, order form, and shipment. It also calculates the total amount of line items in the shipment.
public void GetShippingCost(IOrderGroup orderGroup, IShippingCalculator shipmentCalculator, ICurrentMarket currentMarket)
{
var shipmentCost = shipmentCalculator.GetShippingCost(orderGroup, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Shipping cost for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, shipmentCost);
}
public void GetShippingCost(IOrderForm orderForm, IShippingCalculator shipmentCalculator, ICurrentMarket currentMarket)
{
var shipmentCost = shipmentCalculator.GetShippingCost(orderForm, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Shipping cost for order form '{0}': {1}", orderForm.OrderFormId, shipmentCost);
}
public void GetShippingCost(IShipment shipment, IShippingCalculator shipmentCalculator, ICurrentMarket currentMarket)
{
var shipmentCost = shipmentCalculator.GetShippingCost(shipment, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Shipping cost for shipment '{0}': {1}", shipment.ShipmentId, shipmentCost);
}
public void GetShippingItemsTotal(IShipment shipment, IShippingCalculator shipmentCalculator)
{
var shippingItemsTotal = shipmentCalculator.GetShippingItemsTotal(shipment, Currency.USD);
Debug.WriteLine("Shipping items total for '{0}': {1}", shipment.ShipmentId, shippingItemsTotal);
}
public void GetDiscountedShippingAmount(IShipment shipment, IShippingCalculator shipmentCalculator, ICurrentMarket currentMarket)
{
var discountedShippingAmount = shipmentCalculator.GetDiscountedShippingAmount(shipment, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Discounted shipping amount for shipment '{0}': {1}", shipment.ShipmentId, discountedShippingAmount);
}
public void GetShipmentDiscountPrice(IShipment shipment, IShippingCalculator shippingCalculator)
{
var shipmentDiscountedPrice = shippingCalculator.GetShipmentDiscountPrice(shipment, Currency.USD);
Debug.WriteLine("Shipment discounted price for '{0}': {1}", shipment.ShipmentId, shipmentDiscountedPrice);
}
By inheriting from the default implementation of the interface, DefaultShippingCalculator, you can override the shipping cost calculation. To change that calculation, override one or several CalculateShippingCost methods. To change the calculation of shipping items' total, override the CalculateShippingItemsTotal method.
public class ShippingCalculatorSample : DefaultShippingCalculator
{
private readonly ILineItemCalculator _lineItemCalculator;
public ShippingCalculatorSample(ILineItemCalculator lineItemCalculator, IReturnLineItemCalculator returnLineItemCalculator)
: base(lineItemCalculator, returnLineItemCalculator)
{
_lineItemCalculator = lineItemCalculator;
}
protected override Money CalculateShippingCost(IOrderGroup orderGroup, IMarket market, Currency currency)
{
//iterate over all order forms in this order group and sum the results.
var shippingTotal = orderGroup.Forms
.Sum(form => GetShippingCost(form, market, currency).Amount);
return new Money(shippingTotal, currency);
}
protected override Money CalculateShippingCost(IOrderForm orderForm, IMarket market, Currency currency)
{
//iterate over all shipments in this order form and sum the results.
var result = orderForm.Shipments
.Sum(shipment => GetShippingCost(shipment, market, currency).Amount - ((Shipment)shipment).ShippingDiscountAmount);
return new Money(result, currency);
}
protected override Money CalculateShippingCost(IShipment shipment, IMarket market, Currency currency)
{
//find the shipping method assigned to the shipment
var shippingMethods = ShippingManager.GetShippingMethods(String.Empty);
var row = shippingMethods.ShippingMethod.FindByShippingMethodId(shipment.ShippingMethodId);
//get the instance of the shipping provider.
var type = Type.GetType(row.ShippingOptionRow.ClassName);
var provider = (IShippingGateway)Activator.CreateInstance(type, market);
//get the rate for this shipment
var message = String.Empty;
var rate = provider.GetRate(row.ShippingMethodId, shipment as Shipment, ref message);
//convert result to correct currency and return.
return rate != null ?
CurrencyFormatter.ConvertCurrency(rate.Money, currency) :
new Money(0, currency);
}
protected override Money CalculateShippingItemsTotal(IShipment shipment, Currency currency)
{
//calculate the total price of all line items
var result = 0m;
foreach (var lineItem in shipment.LineItems.Where(x => x.Quantity > 0))
{
var extemdedPrice = _lineItemCalculator.GetExtendedPrice(lineItem, currency);
result += extemdedPrice.Amount;
}
return new Money(result, currency);
}
}
The default implementation validates that the shipment cost is not negative after the calculation. To change the behavior, override the method ValidateShipmentCostForOrder, ValidateShipmentCostForOrderForm, ValidateShipmentCostForShipment, or ValidateShippingItemTotal, depending on which validation you should override.
public class ShippingCalculatorSample : DefaultShippingCalculator
{
public ShippingCalculatorSample(ILineItemCalculator lineItemCalculator, IReturnLineItemCalculator returnLineItemCalculator)
: base(lineItemCalculator, returnLineItemCalculator)
{
}
protected override void ValidateShippingCostForOrder(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Shipment cost must be greater than 0");
}
}
protected override void ValidateShippingCostForOrderForm(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Shipment cost must be greater than 0");
}
}
protected override void ValidateShippingCostForShipment(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Shipment cost must be greater than 0");
}
}
protected override void ValidateShippingItemTotal(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Shipping item total must be greater than 0");
}
}
}
The TaxCalculator calculates the tax for order group, order form and shipment.
public void GetTaxTotal(IOrderGroup orderGroup, ITaxCalculator taxCalculator, ICurrentMarket currentMarket)
{
var taxTotal = taxCalculator.GetTaxTotal(orderGroup, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Tax total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, taxTotal);
}
public void GetTaxTotal(IOrderForm orderForm, ITaxCalculator taxCalculator, ICurrentMarket currentMarket)
{
var taxTotal = taxCalculator.GetTaxTotal(orderForm, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Tax total for order form '{0}': {1}", orderForm.OrderFormId, taxTotal);
}
public void GetReturnTaxTotal(IReturnOrderForm returnOrderForm, ITaxCalculator taxCalculator, ICurrentMarket currentMarket)
{
var returnTaxTotal = taxCalculator.GetReturnTaxTotal(returnOrderForm, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Tax total for return order form '{0}': {1}", returnOrderForm.OrderFormId, returnTaxTotal);
}
public void GetShippingTaxTotal(IShipment shipment, ITaxCalculator taxCalculator, ICurrentMarket currentMarket)
{
var shippingTaxTotal = taxCalculator.GetShippingTaxTotal(shipment, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Shipping tax total for shipment '{0}': {1}", shipment.ShipmentId, shippingTaxTotal);
}
public void GetShippingReturnTaxTotal(IShipment shipment, ITaxCalculator taxCalculator, ICurrentMarket currentMarket)
{
var shippingReturnTaxTotal = taxCalculator.GetShippingReturnTaxTotal(shipment, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("The tax total for return shipment '{0}': {1}", shipment.ShipmentId, shippingReturnTaxTotal);
}
By inheriting from the default implementation of the interface, DefaultTaxCalculator, you can override the calculation of tax total. Just override one or several of the following:
public class TaxCalculatorOverridingDefault : DefaultTaxCalculator
{
public TaxCalculatorOverridingDefault(
IContentRepository contentRepository,
ReferenceConverter referenceConverter,
IShippingCalculator shippingCalculator,
ILineItemCalculator lineItemCalculator,
IReturnLineItemCalculator returnLineItemCalculator)
: base(contentRepository, referenceConverter, shippingCalculator, lineItemCalculator, returnLineItemCalculator)
{
}
//override this to implement custom tax total calculation for an order group.
protected override Money CalculateTaxTotal(IOrderGroup orderGroup, IMarket market, Currency currency)
{
return new Money(0, currency);
}
//override this to implement custom tax total calculation for an order form.
protected override Money CalculateTaxTotal(IOrderForm orderForm, IMarket market, Currency currency)
{
return new Money(0, currency);
}
//override this to implement custom tax total calculation for a return order form.
protected override Money CalculateReturnTaxTotal(IReturnOrderForm returnOrderForm, IMarket market, Currency currency)
{
return new Money(0, currency);
}
//override this to implement custom shipping tax calculation for a shipment.
protected override Money CalculateShippingTaxTotal(IShipment shipment, IMarket market, Currency currency)
{
return new Money(0, currency);
}
//override this to implement custom shipping tax calculation for a return shipment.
protected override Money CalculateShippingReturnTaxTotal(IShipment shipment, IMarket market, Currency currency)
{
return new Money(0, currency);
}
//override this to implement custom tax category retrieval.
protected override string GetTaxCategoryNameById(int taxCategoryId)
{
return string.Empty;
}
//override this to implement custom tax values retrieval.
protected override IEnumerable<ITaxValue> GetTaxValues(string taxCategory, string languageCode, IOrderAddress orderAddress)
{
return new[] { new TaxValue() };
}
}
The default implementation validates that the tax is not negative after the calculation. To change the behavior, override the following, depending on which validation you should override:
public class TaxCalculatorOverridingDefault : DefaultTaxCalculator
{
public TaxCalculatorOverridingDefault(
IContentRepository contentRepository,
ReferenceConverter referenceConverter,
IShippingCalculator shippingCalculator,
ILineItemCalculator lineItemCalculator,
IReturnLineItemCalculator returnLineItemCalculator)
: base(contentRepository, referenceConverter, shippingCalculator, lineItemCalculator, returnLineItemCalculator)
{
}
protected override void ValidateTaxTotalForOrder(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Shipping item total must be greater than 0");
}
}
protected override void ValidateTaxTotalForOrderForm(Money money)
{
if (money.Amount <= 0)
{
throw new ValidationException("Shipping item total must be greater than 0");
}
}
}
The OrderFormCalculator calculates the handling total, sub total, and total for an order form.
public void GetOrderGroupTotals(IOrderForm orderForm, IOrderFormCalculator orderFormCalculator, ICurrentMarket currentMarket)
{
var handlingTotal = orderFormCalculator.GetHandlingTotal(orderForm, Currency.USD);
var subTotal = orderFormCalculator.GetSubTotal(orderForm, Currency.USD);
var total = orderFormCalculator.GetTotal(orderForm, currentMarket.GetCurrentMarket(), Currency.USD);
Debug.WriteLine("Handling total for order form '{0}': {1}", orderForm.OrderFormId, handlingTotal);
Debug.WriteLine("Sub total for order form '{0}': {1}", orderForm.OrderFormId, subTotal);
Debug.WriteLine("Total for order form '{0}': {1}", orderForm.OrderFormId, total);
}
By inheriting from the default implementation of the interface, DefaultOrderFormCalculator, you can override the calculations. Just override one or several of the methods:
The default implementation validates that the total is not negative after the calculation. To change the behavior, override the following, depending on which validation you should override.
The OrderGroupCalculator calculates an order's handling total, sub total, and total.
public void GetOrderGroupTotals(IOrderGroup orderGroup, IOrderGroupCalculator orderGroupCalculator, ICurrentMarket currentMarket)
{
var handlingTotal = orderGroupCalculator.GetHandlingTotal(orderGroup);
var subTotal = orderGroupCalculator.GetSubTotal(orderGroup);
var total = orderGroupCalculator.GetTotal(orderGroup);
Debug.WriteLine("Handling total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, handlingTotal);
Debug.WriteLine("Sub total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, subTotal);
Debug.WriteLine("Total for order '{0}': {1}", orderGroup.OrderLink.OrderGroupId, total);
}
By inheriting from the default implementation of the interface, DefaultOrderGroupCalculator, you override the calculations. Just override one or several CalculateHandlingTotal, CalculateSubtotal, or CalculateTotal methods.
The default implementation validates that the total is not negative after the calculation. To change the behavior, override the ValidateHandlingTotal, ValidateSubtotal, or ValidateTotal method, depending on which validation you should override.
Last updated: Apr 16, 2018