public void AddItemToCheckout(int sku, decimal quantity, MeasurmentUnits buyUnit, DiscountRule discountRule)
        {
            // First get the product with the corresponding SKU from repository
            var product = _productsRepo.GetProduct(sku);

            if (product == null)
            {
                throw new ArgumentException($"Cannot find product with SKU : {sku}");
            }

            if (product.UnitPrice <= 0)
            {
                throw new ArgumentOutOfRangeException("Cannot add a product with invalid price");
            }

            if (quantity <= 0)
            {
                throw new ArgumentOutOfRangeException("Cannot add a product with negative or zero quantity");
            }

            if (product.MeasurmentUnit == MeasurmentUnits.PIECE && quantity != Math.Round(quantity))
            {
                throw new ArgumentException("Cannot add product sold by number with a floating decimal quantity");
            }

            if (product.MeasurmentUnit != buyUnit)
            {
                try
                {
                    // get the quantity corresponding to the sell unit, rounded to 3 decimals
                    quantity = Math.Round(GetQuantityFromUnit(quantity, product.MeasurmentUnit, buyUnit), 3);
                }
                catch (Exception e)
                {
                    throw new ArgumentException(e.Message + $": Sell Unit {product.MeasurmentUnit}, Buy Unit {buyUnit}");
                }
            }

            if (discountRule != null)
            {
                discountRule = ConfigureDiscountRuleParams(discountRule.Id, product.UnitPrice);
            }

            // Finally add a "quantity" of this product to the list of
            // checkout items if all the checking conditions are met
            _checkoutRepo.AddItem(product, quantity, buyUnit, discountRule);
        }
        public void AddItem(Product product, decimal quantity, MeasurmentUnits buyUnit, DiscountRule discountRule)
        {
            product.DiscountRule = discountRule;

            // create a CheckoutItem object from the provided parameters
            var checkoutItem = new CheckoutItem
            {
                Product  = product,
                Quantity = quantity,
                BuyUnit  = buyUnit,
                Price    = product.UnitPrice * quantity
            };

            // Set a unique ID and increment the static counter
            checkoutItem.Id = _id;
            Interlocked.Increment(ref _id);

            // add the item to the checkout list
            _checkoutItems.Add(checkoutItem);
        }
Example #3
0
        [InlineData(4, 800, MeasurmentUnits.MILLILITRE, 1)]  // item with SKU = 4 costs $1.25/litre (so what does 800 millilitres cost?)
        public void Test_CanCalculateTotalSingleItemPerWeightOrVolume(int id, decimal quantity, MeasurmentUnits buyUnit, decimal expectedPrice)
        {
            var checkoutService = Subject();

            // add the sequence of inline data
            checkoutService.AddItemToCheckout(id, quantity, buyUnit, null);
            // verify that the calulated price is equal to the expected price
            Assert.Equal(expectedPrice, checkoutService.CalculateTotal());
        }
        // returns the quantity equivalent to sell unit based on the buy unit
        private decimal GetQuantityFromUnit(decimal quantity, MeasurmentUnits saleUnit, MeasurmentUnits buyUnit)
        {
            string message = "Not compatible buy and sell units";

            switch (saleUnit)
            {
            /***** Mass Conversion *****/
            // Convert to pounds
            case MeasurmentUnits.POUND:
                if (buyUnit == MeasurmentUnits.OUNCE)
                {
                    return(MassConversion.OuncesToPounds(quantity));
                }
                if (buyUnit == MeasurmentUnits.GRAM)
                {
                    return(MassConversion.GramsToPounds(quantity));
                }
                if (buyUnit == MeasurmentUnits.KILOGRAM)
                {
                    return(MassConversion.KilogramsToPounds(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            // Convert to Kilograms
            case MeasurmentUnits.KILOGRAM:
                if (buyUnit == MeasurmentUnits.GRAM)
                {
                    return(MassConversion.GramsToKilograms(quantity));
                }
                if (buyUnit == MeasurmentUnits.POUND)
                {
                    return(MassConversion.PoundsToKilograms(quantity));
                }
                if (buyUnit == MeasurmentUnits.OUNCE)
                {
                    return(MassConversion.OuncesToKilograms(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            // Convert to Grams
            case MeasurmentUnits.GRAM:
                if (buyUnit == MeasurmentUnits.OUNCE)
                {
                    return(MassConversion.OuncesToGrams(quantity));
                }
                if (buyUnit == MeasurmentUnits.POUND)
                {
                    return(MassConversion.PoundsToGrams(quantity));
                }
                if (buyUnit == MeasurmentUnits.KILOGRAM)
                {
                    return(MassConversion.KilogramsToGrams(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            // Convert to ounces
            case MeasurmentUnits.OUNCE:
                if (buyUnit == MeasurmentUnits.POUND)
                {
                    return(MassConversion.PoundsToOunces(quantity));
                }
                if (buyUnit == MeasurmentUnits.GRAM)
                {
                    return(MassConversion.GramsToOunces(quantity));
                }
                if (buyUnit == MeasurmentUnits.KILOGRAM)
                {
                    return(MassConversion.KilogramsToOunces(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            /***** Volume Conversion *****/
            case MeasurmentUnits.LITRE:
                if (buyUnit == MeasurmentUnits.GALLON)
                {
                    return(VolumeConversion.GallonsToLitres(quantity));
                }
                if (buyUnit == MeasurmentUnits.MILLILITRE)
                {
                    return(VolumeConversion.MillilitresToLitres(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            case MeasurmentUnits.GALLON:
                if (buyUnit == MeasurmentUnits.LITRE)
                {
                    return(VolumeConversion.LitresToGallons(quantity));
                }
                if (buyUnit == MeasurmentUnits.MILLILITRE)
                {
                    return(VolumeConversion.MillilitresToGallons(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            case MeasurmentUnits.MILLILITRE:
                if (buyUnit == MeasurmentUnits.LITRE)
                {
                    return(VolumeConversion.LitresToMillilitres(quantity));
                }
                if (buyUnit == MeasurmentUnits.GALLON)
                {
                    return(VolumeConversion.GallonsToMillilitres(quantity));
                }
                else
                {
                    throw new ArgumentException(message);
                }

            default:
                throw new ArgumentException(message);
            }
        }