public void CalculateOrderWeight_ReturnCorrectWeight()
        {
            var order = new SalesOrder
            {
                Lines = new List <SalesOrderLine>
                {
                    new SalesOrderLine
                    {
                        Product = new Product
                        {
                            Weight = 12m
                        }
                    },
                    new SalesOrderLine
                    {
                        Product = new Product
                        {
                            Weight = 18m
                        }
                    }
                }
            };

            // Act
            var weight = order.GetOrderShippingWeight();

            // Assert
            Assert.Equal(30, weight);
        }
        /// <summary>
        /// Given an order, calculate the best shipping amount according to ShippingWeightRate rule
        /// </summary>
        /// <param name="order"></param>
        /// <returns>The shipping amount sent and total shipping cost</returns>
        public Tuple <decimal, decimal> CalculateWeightBasedOptimalShippingAmount(SalesOrder order)
        {
            var shippingCost   = 0m;
            var shippingWeight = order.GetOrderShippingWeight();

            if (shippingWeight >= 1 && shippingWeight <= 5)
            {
                shippingCost = shippingWeight * 10;
            }
            else if (shippingWeight > 5 && shippingWeight <= 50 / 7)
            {
                // If weight is between 5kg and 7kg, shipping 5kg with $5 is the optimum option
                shippingCost   = 50m;
                shippingWeight = 5m;
            }
            else if (shippingWeight > 50 / 7 && shippingWeight < 10)
            {
                shippingCost = shippingWeight * 7;
            }
            else
            {
                shippingCost = shippingWeight * 20;
            }

            return(new Tuple <decimal, decimal>(shippingWeight, shippingCost));
        }
        public void CalculateOrderWeightWithNullProductList_ReturnZero()
        {
            var order = new SalesOrder();

            // Act
            var weight = order.GetOrderShippingWeight();

            // Assert
            Assert.Equal(0m, weight);
        }
        /// <summary>
        /// Given an order, calculate the best shipping amount according to ShippingPriceRate rule
        /// </summary>
        /// <param name="order"></param>
        /// <returns>The shipping amount sent and total shipping cost</returns>
        public Tuple <decimal, decimal> CalculatePriceBasedOptimalShippingAmount(SalesOrder order)
        {
            var totalPrice = order.GetOrderPrice();

            // From the ShippingPriceRate rule, we can see that we should send as much amount as possible

            var shippingCost   = 0m;
            var shippingWeight = order.GetOrderShippingWeight();

            if (totalPrice >= 0 && totalPrice <= 50)
            {
                shippingCost = shippingWeight * 5.5m;
            }
            else if (totalPrice > 50 && totalPrice < 100)
            {
                // As shipping rate between $50 and $100 is zero, the optimised shipping amount is max at 50kg
                if (shippingWeight <= 50)
                {
                    shippingCost = shippingWeight * 5.5m;
                }
                else
                {
                    shippingCost = shippingWeight * 0m;
                }
            }
            else if (totalPrice >= 100 && totalPrice <= 500)
            {
                shippingCost = shippingWeight * 10m;
            }
            else if (totalPrice > 500 && totalPrice < 1000)
            {
                // There is no rule for price rages [500, 1000], so assume that there is no cost for shipping
                shippingCost = 0;
            }
            else if (totalPrice >= 1000)
            {
                shippingCost = shippingWeight * 15m;
            }

            return(Tuple.Create(shippingWeight, shippingCost));
        }
        /// <summary>
        /// Given an order, calculate the best shipping amount according to ShippingAPIRate rule
        /// </summary>
        /// <param name="order"></param>
        /// <returns>The shipping amount sent and total shipping cost</returns>
        public Tuple <decimal, decimal> CalculateThridPartyBasedOptimalShippingAmount(SalesOrder order)
        {
            var shippingCost   = 0m;
            var shippingWeight = order.GetOrderShippingWeight();

            if (shippingWeight >= 0 && shippingWeight < 10)
            {
                shippingCost = shippingWeight * _client.GetRate(0, 0, shippingWeight);
            }
            else if (shippingWeight >= 10 && shippingWeight <= 30)
            {
                shippingCost = shippingWeight * (_client.GetRate(0, 0, shippingWeight) + 5);
            }
            else if (shippingWeight > 30 && shippingWeight <= 35)
            {
                shippingCost = shippingWeight * (_client.GetRate(0, 0, shippingWeight) * 1.075m);
            }
            else if (shippingWeight > 35)
            {
                shippingCost = shippingWeight * _client.GetRate(0, 0, shippingWeight);
            }

            return(new Tuple <decimal, decimal>(shippingWeight, shippingCost));
        }