Created
October 21, 2017 16:35
-
-
Save emhoracek/c76e5765f9dd40693a6065332fa94834 to your computer and use it in GitHub Desktop.
discounts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Order < Struct.new(:line_items, :discount_name) | |
def discount | |
DiscountDatabase.find_by_name(discount_name) | |
end | |
def discounted_line_item_prices | |
line_items.map do |li| | |
li.discounted_total(discount) | |
end | |
end | |
def total | |
discounted_line_item_prices.reduce(:+) | |
end | |
def display_total | |
"Total ${}" | |
end | |
def display_line_items | |
line_items.map { |li| li.display_discounted(discount) }.join("\n") | |
end | |
def display | |
"#{display_line_items}\n---\nTotal #{total.to_money}" | |
end | |
end | |
class Product < Struct.new(:title, :price) | |
def self.find_by_id(id) | |
product_database[id] | |
end | |
end | |
class LineItem < Struct.new(:product_id, :quantity) | |
def discounted_total (discount) | |
if discount | |
total - total * (discount.eligible_percent(product_id).to_f / 100) | |
else | |
total | |
end | |
end | |
def total | |
product.price * quantity | |
end | |
def product | |
ProductDatabase.find_by_id(product_id) | |
end | |
def display_discount(discount) | |
if discounted_total(discount) != total | |
"(Original Price #{product.price.to_money}) " | |
else | |
"" | |
end | |
end | |
def display_copies | |
if quantity == 1 | |
"1 copy" | |
else | |
"#{quantity } copies" | |
end | |
end | |
def display_discounted(discount) | |
"#{discounted_total(discount).to_money} #{display_discount(discount)}for #{display_copies} of \"#{product.title}\"" | |
end | |
end | |
class Discount < Struct.new(:name, :percent, :type, :products) | |
def eligible_percent (product_id) | |
if type == :all or products.member? product_id | |
percent | |
else | |
0 | |
end | |
end | |
end | |
class DiscountDatabase | |
def self.database | |
{ | |
1 => Discount.new(:WELCOME, 50, :all, nil), # this discount gives 50% off any product | |
2 => Discount.new(:JAC75, 75, :product_list, [1]) # this discount gives a 75% discount off of "Black Jacobins" | |
} | |
end | |
def self.find_by_name(name) | |
row = database.select { |id, discount| discount.name == name } | |
row.values[0] # so bad | |
end | |
end | |
class ProductDatabase | |
def self.database | |
{ | |
1 => Product.new("Black Jacobins", 20_00), | |
2 => Product.new("Freedom Is a Constant Struggle", 15_00) | |
} | |
end | |
def self.find_by_id(id) | |
database[id] | |
end | |
end | |
class OrderDatabase | |
def self.database | |
{ | |
1 => Order.new([LineItem.new(1, 1)], nil), | |
2 => Order.new([LineItem.new(1, 1)], :WELCOME) | |
} | |
end | |
def self.find_by_id(id) | |
database[id] | |
end | |
end | |
class CartApplication | |
def self.display_cart(cart) | |
"Your cart:\n\n" + cart.display() | |
end | |
end | |
class Numeric | |
def to_money | |
sprintf("$%.2f", (self/100)) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require './cart_app' | |
RSpec.describe Order, "#total" do | |
it "should total stuff" do | |
cart = Order.new([LineItem.new(1, 1)], nil) | |
expect(cart.total).to eq 20_00 | |
end | |
it "should include discounts" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1)], :WELCOME ) | |
expect(cart.total).to eq 17_50 | |
end | |
end | |
RSpec.describe Order, "#discount" do | |
it "should total stuff" do | |
cart = Order.new([LineItem.new(1, 1)], nil) | |
expect(cart.discount).to eq nil | |
end | |
it "should include discounts" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1)], :WELCOME ) | |
expect(cart.discount.name).to eq :WELCOME | |
end | |
end | |
RSpec.describe Order, "#discounted_line_items" do | |
it "should total stuff" do | |
cart = Order.new([LineItem.new(1, 1)], nil) | |
expect(cart.discounted_line_item_prices).to eq [20_00] | |
end | |
it "should include discounts" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1)], :WELCOME ) | |
expect(cart.discounted_line_item_prices).to eq [10_00, 7_50] | |
end | |
it "should include discounts" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1)], :JAC75) | |
expect(cart.discounted_line_item_prices).to eq [5_00, 15_00] | |
end | |
end | |
RSpec.describe Order, "#display" do | |
it "should display an order" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1) ], :WELCOME) | |
expected_display = | |
"""$10.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\" | |
$7.50 (Original Price $15.00) for 1 copy of \"Freedom Is a Constant Struggle\" | |
--- | |
Total $17.50""" | |
expect(cart.display).to eq expected_display | |
end | |
end | |
RSpec.describe LineItem, "#total" do | |
it "should total the line item" do | |
line_item = LineItem.new(1, 1) | |
expect(line_item.total).to eq 20_00 | |
end | |
end | |
RSpec.describe LineItem, "#discounted_total" do | |
it "should total the line item" do | |
line_item = LineItem.new(1, 1) | |
discount = DiscountDatabase.find_by_name(:WELCOME) | |
expect(line_item.discounted_total(discount)).to eq 10_00 | |
end | |
it "should total the line item" do | |
line_item = LineItem.new(1, 1) | |
expect(line_item.discounted_total(nil)).to eq 20_00 | |
end | |
end | |
RSpec.describe LineItem, "#display" do | |
it "should display the line item" do | |
line_item = LineItem.new(1, 1) | |
discount = DiscountDatabase.find_by_name(:WELCOME) | |
expected_display = | |
"$10.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\"" | |
expect(line_item.display_discounted(discount)).to eq expected_display | |
end | |
end | |
RSpec.describe ProductDatabase, "#find_product_by_id" do | |
it "should find the correct product" do | |
product = ProductDatabase.find_by_id(1) | |
expect(product.title).to eq "Black Jacobins" | |
product = ProductDatabase.find_by_id(2) | |
expect(product.title).to eq "Freedom Is a Constant Struggle" | |
end | |
end | |
RSpec.describe DiscountDatabase, "#find_discount_by_name" do | |
it "should find the correct discount" do | |
discount = DiscountDatabase.find_by_name(:WELCOME) | |
expect(discount.percent).to eq 50 | |
discount = DiscountDatabase.find_by_name(:JAC75) | |
expect(discount.percent).to eq 75 | |
end | |
end | |
RSpec.describe Discount, "#eligible_percent" do | |
context "An :all-type discount" do | |
it "should give the same percent for all product ids" do | |
discount = DiscountDatabase.find_by_name(:WELCOME) | |
expect(discount.eligible_percent(1)).to eq 50 | |
expect(discount.eligible_percent(2)).to eq 50 | |
end | |
end | |
context "A product specific discount" do | |
it "should give the correct percent for that product" do | |
discount = DiscountDatabase.find_by_name(:JAC75) | |
expect(discount.eligible_percent(1)).to eq 75 | |
end | |
it "should give 0 percent for all other products" do | |
discount = DiscountDatabase.find_by_name(:JAC75) | |
expect(discount.eligible_percent(2)).to eq 0 | |
end | |
end | |
end | |
RSpec.describe CartApplication, "#display_cart" do | |
it "should display a cart with an :all discount" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1) ], :WELCOME) | |
expected_display = | |
"""Your cart: | |
$10.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\" | |
$7.50 (Original Price $15.00) for 1 copy of \"Freedom Is a Constant Struggle\" | |
--- | |
Total $17.50""" | |
expect(CartApplication.display_cart(cart)).to eq expected_display | |
end | |
it "should display a cart with a product discount" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1)] , :JAC75) | |
CartApplication.display_cart(cart) | |
expected_display = | |
"""Your cart: | |
$5.00 (Original Price $20.00) for 1 copy of \"Black Jacobins\" | |
$15.00 for 1 copy of \"Freedom Is a Constant Struggle\" | |
--- | |
Total $20.00""" | |
expect(CartApplication.display_cart(cart)).to eq expected_display | |
end | |
it "should display a cart with no discount" do | |
cart = Order.new([ LineItem.new(1, 1), | |
LineItem.new(2, 1)] , nil) | |
CartApplication.display_cart(cart) | |
expected_display = | |
"""Your cart: | |
$20.00 for 1 copy of \"Black Jacobins\" | |
$15.00 for 1 copy of \"Freedom Is a Constant Struggle\" | |
--- | |
Total $35.00""" | |
expect(CartApplication.display_cart(cart)).to eq expected_display | |
end | |
it "should display a cart with multiples of a product" do | |
cart = Order.new([ LineItem.new(1, 3), | |
LineItem.new(2, 5)] , nil) | |
CartApplication.display_cart(cart) | |
expected_display = | |
"""Your cart: | |
$60.00 for 3 copies of \"Black Jacobins\" | |
$75.00 for 5 copies of \"Freedom Is a Constant Struggle\" | |
--- | |
Total $135.00""" | |
expect(CartApplication.display_cart(cart)).to eq expected_display | |
end | |
it "should display a cart with multiples of a product and discount" do | |
cart = Order.new([ LineItem.new(1, 3), | |
LineItem.new(2, 5)] , :WELCOME) | |
CartApplication.display_cart(cart) | |
expected_display = | |
"""Your cart: | |
$30.00 (Original Price $20.00) for 3 copies of \"Black Jacobins\" | |
$37.50 (Original Price $15.00) for 5 copies of \"Freedom Is a Constant Struggle\" | |
--- | |
Total $67.50""" | |
expect(CartApplication.display_cart(cart)).to eq expected_display | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment