def test_basket_discount_multiple_bundle_offers(self): # With bundle offer on all shampoo buy 3 get the cheapest free self.bundle_offer_all_shampoo = BundleOffer([self.test_products[3], self.test_products[4], self.test_products[5] ], 3) # With bundle offer on small shampoo and sardines buy 2 get the cheapest free self.bundle_offer_small_shampoo_and_sardines = BundleOffer([self.test_products[3], self.test_products[2] ], 2) self.test_basket = Basket(self.test_catalouge, [ self.bundle_offer_all_shampoo, self.bundle_offer_small_shampoo_and_sardines ]) # Add 1 sardines self.test_basket.add_product(self.test_products[2], 1) # Add 3 small shampoo self.test_basket.add_product(self.test_products[3], 3) # Add 2 medium shampoo self.test_basket.add_product(self.test_products[4], 2) # Add 3 large shampoo self.test_basket.add_product(self.test_products[5], 3) # One large shampoo for free (3.5) # Two small shampoo for free (4.00) # Total: 7.5 self.assertEqual(self.test_basket.calculate_discount(), 7.5) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[2].price + self.test_products[3].price * 3 + self.test_products[4].price * 2 + self.test_products[5].price * 3 - self.test_basket.calculate_discount(), 2))
def test_basket_discount_percent_offer(self): # With Sardines 25% discount self.percentage_offer = PercentageOffer(self.test_products[2], 0.25) self.test_basket = Basket(self.test_catalouge, [self.percentage_offer]) # Add 2 Baked Beans self.test_basket.add_product(self.test_products[0], 2) # Add 1 Biscuits self.test_basket.add_product(self.test_products[1]) # Add 2 Sardines self.test_basket.add_product(self.test_products[2], 2) self.assertEqual(self.test_basket.calculate_discount(), 2 * round_half_up(self.test_products[2].price * 0.25, 2)) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[0].price * 2 + self.test_products[1].price + self.test_products[2].price * 2 - self.test_basket.calculate_discount(), 2))
def test_percentage_offer_discount(self): # Baked Beans buy one get one free self.test_offer = PercentageOffer(self.test_products[0], 0.25) self.test_basket = Basket(self.test_catalouge) self.assertEqual(self.test_offer.get_discount(self.test_basket.products)[0], 0.00) self.test_basket.add_product(self.test_products[0], 1) self.assertEqual(self.test_offer.get_discount( self.test_basket.products)[0], round_half_up(self.test_products[0].price * 0.25, 2) ) # Add 1 more Baked Beans for a total of 2 self.test_basket.add_product(self.test_products[0], 1) self.assertEqual(self.test_offer.get_discount( self.test_basket.products)[0], round_half_up(self.test_products[0].price * 0.25, 2) )
def calculate_total(self): """ Calculates the total that applies to the items currently in the basket after applied discounts --- Returns: float, the total that applies to the items currently in the basket after applied discounts """ return round_half_up( self.calculate_subtotal() - self.calculate_discount(), 2)
def test_basket_discount_percent_and_buy_2_get_1_free_offers(self): # With Baked Beans buy 2 get 1 free and 25% discount self.buy_and_get_free_offer = BuyAndGetFreeOffer(self.test_products[0], 2, 1) self.percentage_offer = PercentageOffer(self.test_products[0], 0.25) self.test_basket = Basket(self.test_catalouge, [self.buy_and_get_free_offer, self.percentage_offer]) # Add 4 Baked Beans self.test_basket.add_product(self.test_products[0], 4) # Add 1 Biscuits self.test_basket.add_product(self.test_products[1]) # Baked Beans Buy 2 get one free: 0.99 # Baked Beans 25% percent discount: 0.99 * 0.25 = 0.25 # Total: 0.99 + 0.25 = 1.24 self.assertEqual(self.test_basket.calculate_discount(), 1.24) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[0].price * 4 + self.test_products[1].price - self.test_basket.calculate_discount(), 2)) # Add 4 Baked Beans self.test_basket.add_product(self.test_products[0], 4) # Buy 2 get 1 free twice: 0.99 * 2 = 1.98 # Percentage discount on remaining 2: 0.99 * 0.25 * 2 = 0.50 # total: 1.98 + 0.50 = 2.48 self.assertEqual(self.test_basket.calculate_discount(), 2.48) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[0].price * 8 + self.test_products[1].price - self.test_basket.calculate_discount(), 2)) # With Baked Beans buy 2 get 1 free and 50% discount self.buy_and_get_free_offer = BuyAndGetFreeOffer(self.test_products[0], 2, 1) self.percentage_offer = PercentageOffer(self.test_products[0], 0.50) self.test_basket = Basket(self.test_catalouge, [self.buy_and_get_free_offer, self.percentage_offer]) # Add 4 Baked Beans self.test_basket.add_product(self.test_products[0], 4) # Add 1 Biscuits self.test_basket.add_product(self.test_products[1]) # Baked Beans Buy 2 get one free: 0 # Baked Beans 50% percent discount: 0.99 * 0.5 = 2.00 # Total: 2.00 self.assertEqual(self.test_basket.calculate_discount(), 2.00) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[0].price * 4 + self.test_products[1].price - self.test_basket.calculate_discount(), 2))
def calculate_discount(self): """ Calculates the total discount that applies to the items currently in the basket --- Returns: float, the total discount that applies to the items currently in the basket """ products_for_discount = Basket.get_basket_products_copy(self.products) best_discount, best_products_used = self.__search_best_offer( self.offers, products_for_discount) return round_half_up(best_discount, 2)
def calculate_subtotal(self): """ Calculates the subtotal for the items currently in the basket --- Returns: float, the subtotal for the items currently in the basket """ subtotal = 0 for product_name in self.products: price = self.products[product_name].product.price quantity = self.products[product_name].quantity subtotal += price * quantity return round_half_up(subtotal, 2)
def test_basket_discount_buy_2_get_1_free(self): # With Baked Beans buy 2 get 1 free self.buy_and_get_free_offer = BuyAndGetFreeOffer(self.test_products[0], 2, 1) self.test_basket = Basket(self.test_catalouge, [self.buy_and_get_free_offer]) # Add 4 Baked Beans self.test_basket.add_product(self.test_products[0], 4) # Add 1 Biscuits self.test_basket.add_product(self.test_products[1]) self.assertEqual(self.test_basket.calculate_discount(), 0.99) # Add 4 Baked Beans self.test_basket.add_product(self.test_products[0], 4) self.assertEqual(self.test_basket.calculate_discount(), 1.98) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[0].price * 8 + self.test_products[1].price - self.test_basket.calculate_discount(), 2))
def test_basket_discount_all_offers(self): # With bundle offer on all shampoo buy 3 get the cheapest free self.bundle_offer_all_shampoo = BundleOffer([self.test_products[3], self.test_products[4], self.test_products[5] ], 3) # With bundle offer on small shampoo and sardines buy 2 get the cheapest free self.bundle_offer_small_shampoo_and_sardines = BundleOffer([self.test_products[3], self.test_products[2] ], 2) self.buy_and_get_free_offer_baked_beans = BuyAndGetFreeOffer(self.test_products[0], 2, 1) self.percentage_offer_baked_beans = PercentageOffer(self.test_products[0], 0.25) self.test_basket = Basket(self.test_catalouge, [ self.bundle_offer_all_shampoo, self.bundle_offer_small_shampoo_and_sardines, self.buy_and_get_free_offer_baked_beans, self.percentage_offer_baked_beans ]) # Add 4 Baked Beans self.test_basket.add_product(self.test_products[0], 4) # Add 1 Biscuits self.test_basket.add_product(self.test_products[1]) # Add 1 sardines self.test_basket.add_product(self.test_products[2], 1) # Add 3 small shampoo self.test_basket.add_product(self.test_products[3], 3) # Add 2 medium shampoo self.test_basket.add_product(self.test_products[4], 2) # Add 3 large shampoo self.test_basket.add_product(self.test_products[5], 3) # Baked Beans Buy 2 get one free: 0.99 # Baked Beans 25% percent discount: 0.99 * 0.25 = 0.25 # One large shampoo for free (3.5) # Two small shampoo for free (4.00) # Total: 7.5 + 0.99 + 0.25 = 8.74 self.assertEqual(self.test_basket.calculate_discount(), 8.74) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[0].price * 4 + self.test_products[1].price + self.test_products[2].price + self.test_products[3].price * 3 + self.test_products[4].price * 2 + self.test_products[5].price * 3 - self.test_basket.calculate_discount(), 2))
def get_discount(self, basket_products): """ Given a dict of BaksetProducts, get the next best discount --- Params: basket_products: dict, the basket_products to calculate the next best discount from --- Returns: float, the next best discount dict, dict of product names(key) and their quantity(value) used in the discount """ discount = 0 if (self.product in basket_products and basket_products[self.product].quantity >= 1): discount = basket_products[ self.product].product.price * self.discount_percent return round_half_up(discount, 2), {self.product: 1} return discount, {}
def test_basket_discount_bundle_offer(self): # With bundle offer on all shampoo buy 3 get the cheapest free self.test_offer = BundleOffer([self.test_products[3], self.test_products[4], self.test_products[5] ], 3) self.test_basket = Basket(self.test_catalouge, [self.test_offer]) # Add 2 small shampoo self.test_basket.add_product(self.test_products[3], 2) # Add 1 medium shampoo self.test_basket.add_product(self.test_products[4]) # Add 3 large shampoo self.test_basket.add_product(self.test_products[5], 3) # One large shampoo for free (3.5) and One small shampoo for free (2.00) # Total: 5.5 self.assertEqual(self.test_basket.calculate_discount(), 5.5) self.assertEqual(self.test_basket.calculate_total(), round_half_up(self.test_products[3].price * 2 + self.test_products[4].price + self.test_products[5].price * 3 - self.test_basket.calculate_discount(), 2))