Add BuyXGetOneFreeDiscount

This commit is contained in:
David Underwood
2026-07-21 12:23:46 -04:00
parent 882c18b5e6
commit 554ce58cbf
6 changed files with 70 additions and 15 deletions
+10
View File
@@ -0,0 +1,10 @@
class BuyXGetOneFreeDiscount
def initialize(unit_price:, trigger_quantity: 2)
@unit_price = unit_price
@trigger_quantity = trigger_quantity.to_f
end
def discount_for_quantity(quantity)
return (quantity / @trigger_quantity).floor * @unit_price
end
end
+5
View File
@@ -0,0 +1,5 @@
class NoDiscount
def discount_for_quantity(quantity)
return 0.00
end
end
+7 -1
View File
@@ -1,8 +1,10 @@
require 'no_discount.rb'
class Product class Product
def initialize(price: 0.00, id:, description: '') def initialize(price: 0.00, id:, discount: nil, description: '')
@price = price @price = price
@id = id @id = id
@description = description @description = description
@discount = discount || NoDiscount.new
end end
def price def price
@@ -13,6 +15,10 @@ class Product
@id @id
end end
def discount
@discount
end
def description def description
@description @description
end end
+1 -1
View File
@@ -17,6 +17,6 @@ class ProductInCheckout
end end
def total def total
@product.price * quantity (@product.price * quantity) - @product.discount.discount_for_quantity(@quantity)
end end
end end
+25
View File
@@ -0,0 +1,25 @@
require "minitest/autorun"
require 'buy_x_get_one_free_discount.rb'
class BuyXGetOneFreeDiscountTest < Minitest::Test
def test_appropriate_discount_is_applied
unit_price = 4.00
(2..4).each do |trigger_quantity|
discount = BuyXGetOneFreeDiscount.new(unit_price: unit_price, trigger_quantity: trigger_quantity)
# Single discount at and above trigger quantity
assert_equal unit_price, discount.discount_for_quantity(trigger_quantity)
assert_equal unit_price, discount.discount_for_quantity(trigger_quantity + 1)
assert_equal unit_price, discount.discount_for_quantity(trigger_quantity + trigger_quantity - 1)
# No discount if less than trigger quantity
assert_equal 0.00, discount.discount_for_quantity(trigger_quantity - 1)
# Double discount if double trigger quantity
assert_equal unit_price * 2, discount.discount_for_quantity(trigger_quantity * 2)
assert_equal unit_price * 2, discount.discount_for_quantity((trigger_quantity * 2) + 1)
end
end
end
+22 -13
View File
@@ -1,13 +1,30 @@
require "minitest/autorun" require "minitest/autorun"
require "checkout.rb" require "checkout.rb"
require "buy_x_get_one_free_discount.rb"
class CheckoutTest < Minitest::Test class CheckoutTest < Minitest::Test
def setup def setup
@shop = Shop.new @shop = Shop.new
@shop.add_product(Product.new(id: 'PI5', price: 60.00)) @shop.add_product(
@shop.add_product(Product.new(id: 'ZERO2W', price: 15.00)) Product.new(
@shop.add_product(Product.new(id: 'PICO2', price: 4.00)) id: 'PI5',
price: 60.00
)
)
@shop.add_product(
Product.new(
id: 'ZERO2W',
price: 15.00,
discount: BuyXGetOneFreeDiscount.new(unit_price: 15.00, trigger_quantity: 2)
)
)
@shop.add_product(
Product.new(
id: 'PICO2',
price: 4.00
)
)
@checkout = Checkout.new(shop: @shop) @checkout = Checkout.new(shop: @shop)
end end
@@ -69,21 +86,13 @@ class CheckoutTest < Minitest::Test
# Discounts # Discounts
def test_that_bogof_applied def test_that_bogof_applied
skip @checkout.add(product_id: 'ZERO2W', quantity: 4) # Should remove 2 Zeros
4.times do
@checkout.add(:ZERO2W) # Should remove 2 Zeros
end
assert_equal 30.00, @checkout.total assert_equal 30.00, @checkout.total
end end
def test_that_bogof_applied_with_odd_number def test_that_bogof_applied_with_odd_number
skip @checkout.add(product_id: 'ZERO2W', quantity: 5) # Should still remove 2 Zeros, 5th is full price
5.times do
@checkout.add(:ZERO2W) # Should still remove 2 Zeros, 5th is full price
end
assert_equal 45.00, @checkout.total assert_equal 45.00, @checkout.total
end end