Skip to content

Commit db412c3

Browse files
author
John Ollier
committed
Share mock db. Add discounts.
1 parent 67907bb commit db412c3

9 files changed

+156
-34
lines changed

Lib/basket.rb

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
class Basket
22
attr_reader :purchases
33

4-
def initialize(catalogue)
4+
def initialize(catalogue, discount_rules)
55
# the class is called basket, lets think of a different descriptive name
66
@purchases = Hash.new
77
@catalogue = catalogue
88
@catalogue.products_by_code.each_key { |p_code| @purchases[p_code] = 0 }
9+
@discount_rules = discount_rules
910
end
1011

1112
def show
@@ -18,7 +19,16 @@ def show
1819
message_lines << checkout_line(product.name, quantity, price)
1920
end
2021
end
21-
message_lines << total_line(total)
22+
subtotal = total
23+
message_lines << total_line(subtotal)
24+
@discount_rules.each do |discount_rule|
25+
discount = discount_rule.calculate_discount(@catalogue, @purchases)
26+
if discount > 0
27+
subtotal = subtotal - discount
28+
message_lines << discount_rule.discount_line( format_price( discount ) )
29+
end
30+
end
31+
message_lines << total_line(subtotal)
2232
message_lines
2333
end
2434

Lib/main.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
require './basket'
22
require './catalogue'
3+
require './multiple_purchase_free_discount'
4+
require './multiple_purchase_reduced_price_discount'
35

46
def print_message(lines)
57
lines.each { |line| puts line }
@@ -13,7 +15,10 @@ def print_message(lines)
1315
finish = false
1416

1517
catalogue = Catalogue.new(db)
16-
basket = Basket.new(catalogue)
18+
buy_fruit_tea_offer = MultiplePurchaseFreeDiscount.new(2, 'FR1')
19+
reduced_price_strawbs_offer = MultiplePurchaseReducedPriceDiscount.new(3, 'SR1', 450)
20+
discount_rules = [buy_fruit_tea_offer, reduced_price_strawbs_offer]
21+
basket = Basket.new(catalogue, discount_rules)
1722

1823
while !finish
1924
puts "Please enter command from: add [product code], remove [product_code], checkout"
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class MultiplePurchaseFreeDiscount
2+
3+
def initialize(multiple, product_code)
4+
@multiple = multiple
5+
@product_code = product_code
6+
end
7+
8+
def product_code
9+
@product_code
10+
end
11+
12+
def calculate_discount(catalogue, purchases)
13+
product_price = catalogue.products_by_code[@product_code].price
14+
product_price * (purchases[@product_code] / 2)
15+
end
16+
17+
def discount_line( discount )
18+
"Buy #{@multiple} get one free discount £#{discount}"
19+
end
20+
21+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class MultiplePurchaseReducedPriceDiscount
2+
3+
def initialize(multiple, product_code, reduced_price)
4+
@multiple = multiple
5+
@product_code = product_code
6+
@reduced_price = reduced_price
7+
end
8+
9+
def product_code
10+
@product_code
11+
end
12+
13+
def calculate_discount(catalogue, purchases)
14+
product_price = catalogue.products_by_code[@product_code].price
15+
if purchases[@product_code] >= @multiple
16+
(product_price - @reduced_price) * purchases[@product_code]
17+
else
18+
0
19+
end
20+
21+
end
22+
23+
def discount_line(discount)
24+
"Buy #{@multiple} get reduced price discount £#{discount}"
25+
end
26+
27+
end

Spec/basket_spec.rb

+10-20
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,14 @@
11
require 'basket'
22
require 'catalogue'
3+
require 'mock_db'
34

4-
# here's a simple mock class, but for anything more complex use a mocking framework
5-
class MockDB
6-
def execute(s)
7-
# do nothing
8-
end
9-
10-
def get_first_value(s)
11-
nil
12-
end
13-
end
14-
15-
db = MockDB.new
5+
db = MockDb.new
166

177
describe Basket do
188
catalogue = Catalogue.new(db)
199
describe '#initialize' do
2010
it "is empty initially" do
21-
basket = Basket.new(catalogue)
11+
basket = Basket.new(catalogue, [])
2212
# when testing methods test the data not a formatted message containing the data
2313
expect(basket.purchases['FR1']).to eq(0)
2414
expect(basket.purchases['SR1']).to eq(0)
@@ -27,14 +17,14 @@ def get_first_value(s)
2717
end
2818
describe '#add' do
2919
it "can add a valid item" do
30-
basket = Basket.new(catalogue)
20+
basket = Basket.new(catalogue, [])
3121
basket.add("FR1")
3222
expect(basket.purchases['FR1']).to eq(1)
3323
expect(basket.purchases['SR1']).to eq(0)
3424
expect(basket.purchases['CF1']).to eq(0)
3525
end
3626
it "will not add an invalid item" do
37-
basket = Basket.new(catalogue)
27+
basket = Basket.new(catalogue, [])
3828
basket.add("ZZZ")
3929
expect(basket.purchases['FR1']).to eq(0)
4030
expect(basket.purchases['SR1']).to eq(0)
@@ -43,7 +33,7 @@ def get_first_value(s)
4333
end
4434
describe '#remove' do
4535
it "can remove a valid item if present" do
46-
basket = Basket.new(catalogue)
36+
basket = Basket.new(catalogue, [])
4737
basket.add("FR1")
4838
basket.add("FR1")
4939
basket.remove("FR1")
@@ -52,7 +42,7 @@ def get_first_value(s)
5242
expect(basket.purchases['CF1']).to eq(0)
5343
end
5444
it "will not remove an invalid item" do
55-
basket = Basket.new(catalogue)
45+
basket = Basket.new(catalogue, [])
5646
basket.remove("ZZZ")
5747
expect(basket.purchases['FR1']).to eq(0)
5848
expect(basket.purchases['SR1']).to eq(0)
@@ -61,11 +51,11 @@ def get_first_value(s)
6151
end
6252
describe '#total' do
6353
it "will be zero initially" do
64-
basket = Basket.new(catalogue)
54+
basket = Basket.new(catalogue, [])
6555
expect(basket.total).to eq(0)
6656
end
6757
it "will calculate the running total" do
68-
basket = Basket.new(catalogue)
58+
basket = Basket.new(catalogue, [])
6959
basket.add("FR1")
7060
basket.add("FR1")
7161
basket.add("CF1")
@@ -74,7 +64,7 @@ def get_first_value(s)
7464
end
7565
describe '#show' do
7666
it "will show product names and quantities" do
77-
basket = Basket.new(catalogue)
67+
basket = Basket.new(catalogue, [])
7868
basket.add("FR1")
7969
basket.add("FR1")
8070
basket.add("CF1")

Spec/catalogue_spec.rb

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
require 'catalogue'
2+
require 'mock_db'
23

3-
class MockDB
4-
def execute(s)
5-
# do nothing
6-
end
7-
8-
def get_first_value(s)
9-
return nil
10-
end
11-
end
12-
13-
db = MockDB.new
4+
db = MockDb.new
145

156
describe Catalogue do
167
describe '#initialize' do

Spec/mock_db.rb

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# here's a simple mock class, but for anything more complex use a mocking framework
2+
class MockDb
3+
def execute(s)
4+
# do nothing
5+
end
6+
7+
def get_first_value(s)
8+
nil
9+
end
10+
end

Spec/multiple_purchase_free_spec.rb

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
require 'mock_db'
2+
require 'multiple_purchase_free_discount'
3+
4+
db = MockDb.new
5+
6+
describe MultiplePurchaseFreeDiscount do
7+
catalogue = Catalogue.new(db)
8+
describe '#calculate_discount' do
9+
it "is zero under threshold" do
10+
rule = MultiplePurchaseFreeDiscount.new(2, 'FR1')
11+
purchases = {'FR1' => 1, 'SR1' => 0, 'CF1' => 0}
12+
discount = rule.calculate_discount(catalogue, purchases)
13+
expect(discount).to eq(0)
14+
end
15+
it "is same as price on threshold" do
16+
rule = MultiplePurchaseFreeDiscount.new(2, 'FR1')
17+
purchases = {'FR1' => 2, 'SR1' => 0, 'CF1' => 0}
18+
discount = rule.calculate_discount(catalogue, purchases)
19+
expect(discount).to eq(311)
20+
end
21+
it "is same as price just over threshold" do
22+
rule = MultiplePurchaseFreeDiscount.new(2, 'FR1')
23+
purchases = {'FR1' => 3, 'SR1' => 0, 'CF1' => 0}
24+
discount = rule.calculate_discount(catalogue, purchases)
25+
expect(discount).to eq(311)
26+
end
27+
it "is twice price for twice threshold" do
28+
rule = MultiplePurchaseFreeDiscount.new(2, 'FR1')
29+
purchases = {'FR1' => 4, 'SR1' => 0, 'CF1' => 0}
30+
discount = rule.calculate_discount(catalogue, purchases)
31+
expect(discount).to eq(622)
32+
end
33+
end
34+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
require 'mock_db'
2+
require 'multiple_purchase_reduced_price_discount'
3+
4+
db = MockDb.new
5+
6+
describe MultiplePurchaseReducedPriceDiscount do
7+
catalogue = Catalogue.new(db)
8+
describe '#calculate_discount' do
9+
it "is zero under threshold" do
10+
rule = MultiplePurchaseReducedPriceDiscount.new(3, 'SR1', 450)
11+
purchases = {'SR1' => 2, 'FR1' => 0, 'CF1' => 0 }
12+
discount = rule.calculate_discount(catalogue, purchases)
13+
expect(discount).to eq(0)
14+
end
15+
it "is difference between prices on threshold" do
16+
rule = MultiplePurchaseReducedPriceDiscount.new(3, 'SR1', 450)
17+
purchases = {'SR1' => 3, 'FR1' => 0, 'CF1' => 0}
18+
discount = rule.calculate_discount(catalogue, purchases)
19+
expect(discount).to eq(150)
20+
end
21+
it "is difference between prices over threshold" do
22+
rule = MultiplePurchaseReducedPriceDiscount.new(3, 'SR1', 450)
23+
purchases = {'SR1' => 4, 'FR1' => 0, 'CF1' => 0}
24+
discount = rule.calculate_discount(catalogue, purchases)
25+
expect(discount).to eq(200)
26+
end
27+
it "is zero for other product" do
28+
rule = MultiplePurchaseReducedPriceDiscount.new(3, 'SR1', 450)
29+
purchases = {'SR1' => 0, 'FR1' => 1, 'CF1' => 2}
30+
discount = rule.calculate_discount(catalogue, purchases)
31+
expect(discount).to eq(0)
32+
end
33+
end
34+
end

0 commit comments

Comments
 (0)