Ejemplo n.º 1
0
        /// <summary>
        /// Build and return the currently applicable sales pricing strategy.
        /// </summary>
        /// <returns></returns>
        public ISalePricingStrategy GetSalePricingStrategy()
        {
            // Always (re)read in all promotions.
            // TODO: make location configurable.
            var promotions = new PointOfSaleFileReader(_fileManager).ReadPromotionCatalog("PromotionCatalog.json");

            // Construct a composite pricing strategy.
            CompositePricingStrategy overallStrategy;

            // TODO: could use reflection in the future to construct class instances
            if (promotions.OverallStrategy.Equals("BestForCustomer"))
            {
                overallStrategy = new BestForCustomerPricingStrategy();
            }
            else if (promotions.OverallStrategy.Equals("BestForStore"))
            {
                overallStrategy = new BestForStorePricingStrategy();
            }
            else
            {
                throw new InvalidOperationException(
                          $"'{promotions.OverallStrategy}' is an unknown pricing strategy, " +
                          "supported values are 'BestForCustomer' or 'BestForStore'.");
            }

            // Must always add Line Item strategies first which mutates the sale with line item discounts.
            // However, in the future, the 'BestForStore' strategy may want to apply these after any transactional discounts instead.
            overallStrategy.Add(new LineItemBuyNGetOnePricingStrategy(promotions.SalesLineItemDiscounts));
            overallStrategy.Add(new LineItemQuantityPricingStrategy(promotions.SalesLineItemDiscounts));

            // Add other (probably transactional) strategies as required here.

            return(overallStrategy);
        }
        public void ReadProductCatalogShouldDeserializeMultipleProducts()
        {
            var products = new List <Product>()
            {
                new Product("Macintosh Apple", 1.0m),
                new Product("Delicious Apple", 1.23m),
            };

            var mockFileManager = SetupFileManagerWithProductCatalog(products);

            var result = new PointOfSaleFileReader(mockFileManager.Object)
                         .ReadProductCatalog("mock.json");

            Assert.That(result.Products, Is.Not.Null);
            Assert.That(result.Products.Count, Is.EqualTo(products.Count));

            // Verify deserialization of JSON
            Assert.That(result.Products[0].Id, Is.EqualTo(products[0].Id));
            Assert.That(result.Products[0].Price, Is.EqualTo(products[0].Price));

            Assert.That(result.Products[1].Id, Is.EqualTo(products[1].Id));
            Assert.That(result.Products[1].Price, Is.EqualTo(products[1].Price));

            mockFileManager.Verify();
        }
        public void ReadPromotionCatalogShouldRemoveInvalidSalesLineItemDiscounts()
        {
            var invalidDiscounts = new List <SalesLineItemDiscount>()
            {
                new SalesLineItemDiscount()
                {
                    Discount          = "-10%", // cannot have negative discounts
                    EffectiveFrom     = DateTime.Now.AddHours(-1),
                    EffectiveTo       = DateTime.Now.AddHours(1),
                    ProductId         = "Granola",
                    ThresholdQuantity = 3
                },
                new SalesLineItemDiscount()
                {
                    Discount          = "$10",
                    EffectiveFrom     = DateTime.Now.AddHours(-1),
                    EffectiveTo       = DateTime.Now.AddHours(1),
                    ProductId         = "Greek Salad",
                    ThresholdQuantity = 0 // cannot have 0 thresholds
                },
                new SalesLineItemDiscount()
                {
                    Discount          = "$10",
                    EffectiveFrom     = DateTime.Now.AddHours(1),
                    EffectiveTo       = DateTime.Now.AddHours(-1), // Cannot have To < From
                    ProductId         = "Tuna Salad",
                    ThresholdQuantity = 1
                },
                new SalesLineItemDiscount()
                {
                    Discount          = "$10",
                    EffectiveFrom     = DateTime.Now.AddHours(1),
                    EffectiveTo       = DateTime.Now.AddHours(-1), // Cannot have To < From
                    ProductId         = "",                        // cannot have empty product ids
                    ThresholdQuantity = 1
                }
            };

            var mockFileManager = SetupFileManagerWithLineItemDiscounts(invalidDiscounts);

            var result = new PointOfSaleFileReader(mockFileManager.Object)
                         .ReadPromotionCatalog("mock.json");

            foreach (var d in invalidDiscounts)
            {
                Assert.That(d.IsValid(), Is.False, "Expected discount to be invalid.");
            }

            Assert.That(result.SalesLineItemDiscounts.Count, Is.EqualTo(0),
                        "All invalid discounts should have been filtered out.");
        }
        public void ReadProductCatalogShouldTrimProductId()
        {
            var products = new List <Product>()
            {
                new Product(" Macintosh Apple ", 1.0m)
            };

            var mockFileManager = SetupFileManagerWithProductCatalog(products);

            var result = new PointOfSaleFileReader(mockFileManager.Object)
                         .ReadProductCatalog("mock.json");

            Assert.That(result.Products, Is.Not.Null);
            Assert.That(result.Products.Count, Is.EqualTo(1));
            Assert.That(result.Products[0].Id, Is.EqualTo("Macintosh Apple"),
                        "File reader should trim the product Id field.");

            mockFileManager.Verify();
        }
Ejemplo n.º 5
0
        private static ProductCatalog ReadProductCatalog()
        {
            ProductCatalog catalog;

            try
            {
                WriteLine("Reading ProductCatalog.json...");
                catalog = new PointOfSaleFileReader().ReadProductCatalog("ProductCatalog.json");
                WriteLine($"Found {catalog.Products.Count} product(s) in catalog.");
                WriteLine();
            }
            catch (Exception ex)
            {
                WriteLine("Error reading product catalog.");
                WriteLine($"{ex.Message}");
                WriteLine($"{ex.InnerException?.Message}");
                WriteLine("Please have a system administrator correct the error.");
                return(null);
            }

            return(catalog);
        }
        public void ReadPromotionCatalogShouldDeserializeMultipleProducts()
        {
            var discounts = new List <SalesLineItemDiscount>()
            {
                new SalesLineItemDiscount()
                {
                    Discount          = "10%",
                    EffectiveFrom     = DateTime.Now.AddHours(-1),
                    EffectiveTo       = DateTime.Now.AddHours(1),
                    ProductId         = "Granola",
                    ThresholdQuantity = 3
                },
                new SalesLineItemDiscount()
                {
                    Discount          = "$10",
                    EffectiveFrom     = DateTime.Now.AddHours(-1),
                    EffectiveTo       = DateTime.Now.AddHours(1),
                    ProductId         = "Greek Salad",
                    ThresholdQuantity = 5
                }
            };

            var mockFileManager = SetupFileManagerWithLineItemDiscounts(discounts);

            var result = new PointOfSaleFileReader(mockFileManager.Object)
                         .ReadPromotionCatalog("mock.json");

            Assert.That(result.SalesLineItemDiscounts, Is.Not.Null);
            Assert.That(result.SalesLineItemDiscounts.Count, Is.EqualTo(discounts.Count));

            // Verify deserialization of JSON
            Assert.That(result.SalesLineItemDiscounts[0].Discount, Is.EqualTo(discounts[0].Discount));
            Assert.That(result.SalesLineItemDiscounts[0].EffectiveFrom, Is.EqualTo(discounts[0].EffectiveFrom));
            Assert.That(result.SalesLineItemDiscounts[0].EffectiveTo, Is.EqualTo(discounts[0].EffectiveTo));
            Assert.That(result.SalesLineItemDiscounts[0].ProductId, Is.EqualTo(discounts[0].ProductId));
            Assert.That(result.SalesLineItemDiscounts[0].ThresholdQuantity, Is.EqualTo(discounts[0].ThresholdQuantity));

            mockFileManager.Verify();
        }
        public void ReadProductCatalogShouldIgnoreDuplicateProducts()
        {
            var products = new List <Product>()
            {
                new Product("Macintosh Apple", 1.0m),
                new Product("Delicious Apple", 2.0m),
                new Product("Macintosh Apple", 3.0m),
                new Product("Delicious Apple", 4.0m),
            };

            var mockFileManager = SetupFileManagerWithProductCatalog(products);

            var result = new PointOfSaleFileReader(mockFileManager.Object).ReadProductCatalog("mock.json");

            Assert.That(result.Products, Is.Not.Null);
            Assert.That(result.Products.Count, Is.EqualTo(2),
                        "Duplicate products should be ignored, only the first instance is used.");
            Assert.That(result.Products[0].Price, Is.EqualTo(products[0].Price));
            Assert.That(result.Products[1].Price, Is.EqualTo(products[1].Price));

            mockFileManager.Verify();
        }