internal decimal?Calculate(string type, int days, RentalFees rentalFees)
        {
            if (days <= 0)
            {
                logger.LogError($"Unable to calculate price for negative day count: days = {days}!");
                return(null);
            }

            switch (type)
            {
            case "Heavy":
                return(rentalFees.OneTimeFee +
                       days * rentalFees.PremiumDailyFee);

            case "Regular":
                return(rentalFees.OneTimeFee +
                       Math.Min(2, days) * rentalFees.PremiumDailyFee +
                       Math.Max(0, days - 2) * rentalFees.RegularDailyFee);

            case "Specialized":
                return(Math.Min(3, days) * rentalFees.PremiumDailyFee +
                       Math.Max(0, days - 3) * rentalFees.RegularDailyFee);

            default:
                logger.LogError($"Unable to calculate price for unknown equipment type: {type}!");
                return(null);
            }
        }
示例#2
0
        public void CalculateCorrectPrice(
            Mock <OrderItemPriceCalculator> sutMock)
        {
            var rentalFees = new RentalFees
            {
                OneTimeFee      = 1,
                RegularDailyFee = 10,
                PremiumDailyFee = 100
            };

            var testCases = new[]
            {
                new { type = "Heavy", days = 1, price = 101 },        // 1 +  1x100
                new { type = "Heavy", days = 3, price = 301 },        // 1 +  3x100
                new { type = "Heavy", days = 18, price = 1801 },      // 1 + 18x100

                new { type = "Regular", days = 1, price = 101 },      // 1 + 1x100
                new { type = "Regular", days = 2, price = 201 },      // 1 + 2x100
                new { type = "Regular", days = 3, price = 211 },      // 1 + 2x100 + 1x10
                new { type = "Regular", days = 7, price = 251 },      // 1 + 2x100 + 5x10

                new { type = "Specialized", days = 1, price = 100 },  // 1x100
                new { type = "Specialized", days = 3, price = 300 },  // 3x100
                new { type = "Specialized", days = 4, price = 310 },  // 3x100 +  1x10
                new { type = "Specialized", days = 28, price = 550 }, // 3x100 + 25x10
            };

            testCases.ToList().ForEach(t =>
                                       Assert.Equal(t.price, sutMock.Object.Calculate(t.type, t.days, rentalFees)));
        }
示例#3
0
 public Price <TCurrency> CalculatePrice <TCurrency>(RentalFees <TCurrency> rentalFees, int rentalDays) where TCurrency : Currency
 {
     if (rentalDays <= 3)
     {
         return(rentalFees.PremiumDaily * rentalDays);
     }
     else
     {
         return(rentalFees.PremiumDaily * 3 + rentalFees.RegularDaily * (rentalDays - 3));
     }
 }
示例#4
0
        public void TestConstructor()
        {
            var oneTime      = new Price <DummyCurrency>(1, new DummyCurrency());
            var premiumDaily = new Price <DummyCurrency>(2, new DummyCurrency());
            var regularDaily = new Price <DummyCurrency>(3, new DummyCurrency());
            var prices       = new RentalFees <DummyCurrency>(oneTime, premiumDaily, regularDaily);

            // if properties would have its own price type (class), these asserts would become irrelevant,
            // as compiler would ensure incorrect price type won't be assigned to a property.
            Assert.Equal(oneTime, prices.OneTime);
            Assert.Equal(premiumDaily, prices.PremiumDaily);
            Assert.Equal(regularDaily, prices.RegularDaily);
        }
        public void TestSpecializedEquipment(int oneTime, int premiumDaily, int regularDaily, int days, int expected)
        {
            var specialized = new SpecializedEquipment();

            Assert.Equal(1, specialized.LoyaltyPoints);

            var prices = new RentalFees <DummyCurrency>(
                DummyCurrency.CreatePrice(oneTime),
                DummyCurrency.CreatePrice(premiumDaily),
                DummyCurrency.CreatePrice(regularDaily));
            var expectedPrice = DummyCurrency.CreatePrice(expected);

            Assert.Equal(expectedPrice, specialized.CalculatePrice(prices, days));
        }
        public void TestHeavyEquipment(int oneTime, int premiumDaily, int regularDaily, int days, int expected)
        {
            var heavy = new HeavyEquipment();

            Assert.Equal(2, heavy.LoyaltyPoints);

            var prices = new RentalFees <DummyCurrency>(
                DummyCurrency.CreatePrice(oneTime),
                DummyCurrency.CreatePrice(premiumDaily),
                DummyCurrency.CreatePrice(regularDaily));
            var expectedPrice = DummyCurrency.CreatePrice(expected);

            Assert.Equal(expectedPrice, heavy.CalculatePrice(prices, days));
        }
示例#7
0
 public void DoesNotCalculateForUnknownType(
     Mock <OrderItemPriceCalculator> sutMock,
     RentalFees rentalFees, string type, int days)
 {
     Assert.Null(sutMock.Object.Calculate(type, days, rentalFees));
 }
示例#8
0
 public void DoesNotCalculateForZeroDays(
     Mock <OrderItemPriceCalculator> sutMock,
     RentalFees rentalFees)
 {
     Assert.Null(sutMock.Object.Calculate("Heavy", 0, rentalFees));
 }
示例#9
0
 public void DoesNotCalculateForNegativeDays(
     Mock <OrderItemPriceCalculator> sutMock,
     RentalFees rentalFees, int days)
 {
     Assert.Null(sutMock.Object.Calculate("Heavy", -1 * days, rentalFees));
 }
示例#10
0
        public static Invoice Create <TCurrency>(IEnumerable <EquipmentOrder> orderLines, RentalFees <TCurrency> fees) where TCurrency : Currency, new()
        {
            Price <TCurrency> total = new Price <TCurrency>(0, new TCurrency());
            int loyaltyPoints       = 0;
            var lines = orderLines.Select(orderLine =>
            {
                var price = orderLine.CalculatePrice(fees);
                total     = total.Add(price);
                // TODO: this logic is a part of "LoyaltyPoints" type
                loyaltyPoints += orderLine.CalculateLoyaltyPoints();
                return(price.Print());
            }).ToList();

            return(new Invoice(total.Print(), loyaltyPoints, lines));
        }
示例#11
0
 public Price <TCurrency> CalculatePrice <TCurrency>(RentalFees <TCurrency> fees) where TCurrency : Currency =>
 ParseEquipmentType(Type).CalculatePrice(fees, RentalDays);
示例#12
0
 public Price <TCurrency> CalculatePrice <TCurrency>(RentalFees <TCurrency> rentalFees, int rentalDays) where TCurrency : Currency
 {
     return(rentalFees.OneTime + rentalFees.PremiumDaily * rentalDays);
 }