Решение на Трета задача от Георги Вацов

Обратно към всички решения

Към профила на Георги Вацов

Резултати

  • 0 точки от тестове
  • 0 бонус точки
  • 0 точки общо
  • 0 успешни тест(а)
  • 19 неуспешни тест(а)

Код

class Inventory
attr_accessor :product_list, :coupon_list
def initialize
@product_list = Array.new
@coupon_list = Array.new
end
def register(prod_name, prod_price, prod_promo = {})
new_product = Product.new prod_name, prod_price, prod_promo
@product_list.push new_product
end
def register_coupon(coupon_name, coupon_value)
new_coupon = Coupon.new coupon_name, coupon_value
@coupon_list.push new_coupon
end
def new_cart(inventory)
cart = Cart.new @product_list, @coupon_list
end
end
class Product
attr_accessor :name, :price, :promotion, :has_promotion
def initialize(name, price, promotion)
@name = name
@price = price
if !promotion.empty?
@promotion = Promotion.new promotion.to_a[0][0], promotion.to_a[0][1]
@has_promotion = true
end
end
end
class Promotion
attr_accessor :promo_name, :promo_value
def initialize(promo_name, promo_value)
@promo_name = promo_name
@promo_value = promo_value
end
end
class Coupon
attr_accessor :coupon_name, :coupon_value
def initialize(coupon_name, coupon_value)
@coupon_name = coupon_name
@coupon_value = coupon_value
end
end
class BoughtProduct
attr_accessor :product_name, :quantity, :regular_price, :discount, :promo_name
def initialize(name, qty, reg_price, discount = 0, promo_name = '')
@product_name = name
@quantity = qty
@regular_price = reg_price
@discount = discount
@promo_name = promo_name
end
end
class Cart
attr_accessor :bought_products, :sum, :product_list, :coupon_list, :discount
def initialize(products, coupons)
@bought_products = Array.new
@sum = 0
@product_list = products
@coupon_list = coupons
end
def get_product_by_name(product_name)
product = @product_list.each do |product|
if product.name == product_name
return product
end
end
raise "Invalid product!"
end
def get_coupon_by_name(coupon_name)
coupon = @coupon_list.each do |coupon|
if coupon.coupon_name == coupon_name
return coupon
end
end
raise "Invalid coupon!"
end
def add(prod_name, quantity)
product_to_add = get_product_by_name(prod_name)
raise "Invalid product added to cart." if product_to_add.nil?
reg_price = quantity * product_to_add.price.to_f
disc = 0
promo_name = ''
disc = calculate_discount(product_to_add, quantity) if product_to_add.has_promotion
promo_name = product_to_add.promotion.promo_name if product_to_add.has_promotion
push_product BoughtProduct.new(prod_name, quantity, reg_price, disc, promo_name)
end
def push_product(product)
bought_products.push product
end
def total
@sum = 0
bought_products.each do |product|
@sum += (product.regular_price - product.discount)
end
sum
end
def use(coupon_name)
coupon = get_coupon_by_name(coupon_name)
@discount = case coupon.coupon_value.to_a[0][0]
when :percent
(total * coupon.coupon_value.to_a[0][1]) / 100
when :amount
total - coupon.coupon_value.to_a[0][1].to_i
else
raise "Invalid coupon!"
end
end
def calculate_discount(prod, qty)
promo_value = prod.promotion.promo_value
@discount = case prod.promotion.promo_name
when :get_one_free
@discount = ((qty / promo_value).to_i) * prod.price.to_f
when :package
package_discount(prod, qty, promo_value)
when :threshold
(qty - promo_value.to_a[0][0]) * (prod.price.to_f * promo_value.to_a[0][1] / 100)
end
end
def package_discount(prod, qty, promo_value)
@discount = ((qty / promo_value.to_a[0][0]).to_i) * promo_value.to_a[0][0] *
(prod.price.to_f * promo_value.to_a[0][1] / 100)
end
def invoice
InvoiceUtils.print_header
bought_products.each do |bought_product|
formatted_price = '%.2f' % bought_product.regular_price
formatted_discount = '%.2f' % bought_product.discount
InvoiceUtils.print_product_line(
bought_product.product_name, bought_product.quantity, formatted_price)
InvoiceUtils.print_promo_line(bought_product)
end
InvoiceUtils.print_footer('%.2f' % (total - @discount).to_f)
end
end
class InvoiceUtils
def InvoiceUtils.print_header
puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
puts "| Name".ljust(45) + "qty |" + "price |".rjust(11)
puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
end
def InvoiceUtils.print_product_line(prod_name, qty, price)
puts "| #{prod_name.ljust(43)}" + " #{qty.to_s.rjust(2)} |" + "#{price.rjust(9)} |"
end
def InvoiceUtils.print_promo_line(bought_product)
if bought_product.discount > 0
formatted_discount = '%.2f' % (bought_product.discount * (-1))
puts "| #{bought_product.promo_name.to_s.ljust(44)} |" +
"#{formatted_discount.to_s.rjust(9)} |"
end
end
def InvoiceUtils.print_footer(total)
puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
puts "| TOTAL".ljust(45) + " |" + "#{total} |".rjust(11)
puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
end
end

Лог от изпълнението

FFFFFFFFFFFFFFFFFFF

Failures:

  1) Inventory with no discounts can tell the total price of all products
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:41:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Inventory with no discounts has some constraints on prices and counts
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:52:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Inventory with no discounts can print an invoice
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:69:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Inventory with a 'buy X, get one free' promotion grants every nth item for free
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:91:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Inventory with a 'buy X, get one free' promotion grants 2 items free, when 8 purchased and every 3rd is free
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:99:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Inventory with a 'buy X, get one free' promotion shows the discount in the invoice
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:108:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Inventory with a '% off for every n' promotion gives % off for every group of n
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:130:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Inventory with a '% off for every n' promotion does not discount for extra items, that don't fit in a group
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:140:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) Inventory with a '% off for every n' promotion shows the discount in the invoice
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:151:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  10) Inventory with a '% off of every item after the nth' promotion gives a discount for every item after the nth
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:173:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  11) Inventory with a '% off of every item after the nth' promotion does not give a discount if there are no more than n items in the cart
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:180:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  12) Inventory with a '% off of every item after the nth' promotion shows the discount in the ivnoice
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:194:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  13) Inventory with a '% off' coupon gives % off of the total
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:217:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  14) Inventory with a '% off' coupon applies the coupon discount after product promotions
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:227:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  15) Inventory with a '% off' coupon shows the discount in the invoice
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:237:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  16) Inventory with an 'amount off' coupon subtracts the amount form the total
     Failure/Error: inventory.register_coupon 'TEATIME', amount: '10.00'.to_d
     NoMethodError:
       undefined method `to_d' for "10.00":String
     # /tmp/d20111115-5847-psd50y/spec.rb:256:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  17) Inventory with an 'amount off' coupon does not result in a negative total
     Failure/Error: inventory.register_coupon 'TEATIME', amount: '10.00'.to_d
     NoMethodError:
       undefined method `to_d' for "10.00":String
     # /tmp/d20111115-5847-psd50y/spec.rb:266:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  18) Inventory with an 'amount off' coupon shows the discount in the invoice
     Failure/Error: inventory.register_coupon 'TEA-TIME', amount: '10.00'.to_d
     NoMethodError:
       undefined method `to_d' for "10.00":String
     # /tmp/d20111115-5847-psd50y/spec.rb:276:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  19) Inventory with multiple discounts can print an invoice
     Failure/Error: let(:cart) { inventory.new_cart }
     ArgumentError:
       wrong number of arguments (0 for 1)
     # /tmp/d20111115-5847-psd50y/solution.rb:19:in `new_cart'
     # /tmp/d20111115-5847-psd50y/spec.rb:35:in `block (2 levels) in <top (required)>'
     # /tmp/d20111115-5847-psd50y/spec.rb:303:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.59321 seconds
19 examples, 19 failures

Failed examples:

rspec /tmp/d20111115-5847-psd50y/spec.rb:38 # Inventory with no discounts can tell the total price of all products
rspec /tmp/d20111115-5847-psd50y/spec.rb:47 # Inventory with no discounts has some constraints on prices and counts
rspec /tmp/d20111115-5847-psd50y/spec.rb:64 # Inventory with no discounts can print an invoice
rspec /tmp/d20111115-5847-psd50y/spec.rb:88 # Inventory with a 'buy X, get one free' promotion grants every nth item for free
rspec /tmp/d20111115-5847-psd50y/spec.rb:96 # Inventory with a 'buy X, get one free' promotion grants 2 items free, when 8 purchased and every 3rd is free
rspec /tmp/d20111115-5847-psd50y/spec.rb:104 # Inventory with a 'buy X, get one free' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-psd50y/spec.rb:127 # Inventory with a '% off for every n' promotion gives % off for every group of n
rspec /tmp/d20111115-5847-psd50y/spec.rb:137 # Inventory with a '% off for every n' promotion does not discount for extra items, that don't fit in a group
rspec /tmp/d20111115-5847-psd50y/spec.rb:147 # Inventory with a '% off for every n' promotion shows the discount in the invoice
rspec /tmp/d20111115-5847-psd50y/spec.rb:170 # Inventory with a '% off of every item after the nth' promotion gives a discount for every item after the nth
rspec /tmp/d20111115-5847-psd50y/spec.rb:177 # Inventory with a '% off of every item after the nth' promotion does not give a discount if there are no more than n items in the cart
rspec /tmp/d20111115-5847-psd50y/spec.rb:190 # Inventory with a '% off of every item after the nth' promotion shows the discount in the ivnoice
rspec /tmp/d20111115-5847-psd50y/spec.rb:213 # Inventory with a '% off' coupon gives % off of the total
rspec /tmp/d20111115-5847-psd50y/spec.rb:223 # Inventory with a '% off' coupon applies the coupon discount after product promotions
rspec /tmp/d20111115-5847-psd50y/spec.rb:233 # Inventory with a '% off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-psd50y/spec.rb:254 # Inventory with an 'amount off' coupon subtracts the amount form the total
rspec /tmp/d20111115-5847-psd50y/spec.rb:264 # Inventory with an 'amount off' coupon does not result in a negative total
rspec /tmp/d20111115-5847-psd50y/spec.rb:274 # Inventory with an 'amount off' coupon shows the discount in the invoice
rspec /tmp/d20111115-5847-psd50y/spec.rb:295 # Inventory with multiple discounts can print an invoice

История (1 версия и 0 коментара)

Георги обнови решението на 07.11.2011 15:18 (преди около 13 години)

+class Inventory
+ attr_accessor :product_list, :coupon_list
+
+ def initialize
+ @product_list = Array.new
+ @coupon_list = Array.new
+ end
+
+ def register(prod_name, prod_price, prod_promo = {})
+ new_product = Product.new prod_name, prod_price, prod_promo
+ @product_list.push new_product
+ end
+
+ def register_coupon(coupon_name, coupon_value)
+ new_coupon = Coupon.new coupon_name, coupon_value
+ @coupon_list.push new_coupon
+ end
+
+ def new_cart(inventory)
+ cart = Cart.new @product_list, @coupon_list
+ end
+end
+
+class Product
+ attr_accessor :name, :price, :promotion, :has_promotion
+
+ def initialize(name, price, promotion)
+ @name = name
+ @price = price
+ if !promotion.empty?
+ @promotion = Promotion.new promotion.to_a[0][0], promotion.to_a[0][1]
+ @has_promotion = true
+ end
+ end
+
+end
+
+class Promotion
+ attr_accessor :promo_name, :promo_value
+
+ def initialize(promo_name, promo_value)
+ @promo_name = promo_name
+ @promo_value = promo_value
+ end
+end
+
+class Coupon
+ attr_accessor :coupon_name, :coupon_value
+
+ def initialize(coupon_name, coupon_value)
+ @coupon_name = coupon_name
+ @coupon_value = coupon_value
+ end
+end
+
+class BoughtProduct
+ attr_accessor :product_name, :quantity, :regular_price, :discount, :promo_name
+
+ def initialize(name, qty, reg_price, discount = 0, promo_name = '')
+ @product_name = name
+ @quantity = qty
+ @regular_price = reg_price
+ @discount = discount
+ @promo_name = promo_name
+ end
+end
+
+class Cart
+ attr_accessor :bought_products, :sum, :product_list, :coupon_list, :discount
+
+ def initialize(products, coupons)
+ @bought_products = Array.new
+ @sum = 0
+ @product_list = products
+ @coupon_list = coupons
+ end
+
+ def get_product_by_name(product_name)
+ product = @product_list.each do |product|
+ if product.name == product_name
+ return product
+ end
+ end
+ raise "Invalid product!"
+ end
+
+ def get_coupon_by_name(coupon_name)
+ coupon = @coupon_list.each do |coupon|
+ if coupon.coupon_name == coupon_name
+ return coupon
+ end
+ end
+ raise "Invalid coupon!"
+ end
+
+ def add(prod_name, quantity)
+ product_to_add = get_product_by_name(prod_name)
+ raise "Invalid product added to cart." if product_to_add.nil?
+
+ reg_price = quantity * product_to_add.price.to_f
+ disc = 0
+ promo_name = ''
+
+ disc = calculate_discount(product_to_add, quantity) if product_to_add.has_promotion
+ promo_name = product_to_add.promotion.promo_name if product_to_add.has_promotion
+ push_product BoughtProduct.new(prod_name, quantity, reg_price, disc, promo_name)
+ end
+
+ def push_product(product)
+ bought_products.push product
+ end
+
+ def total
+ @sum = 0
+ bought_products.each do |product|
+ @sum += (product.regular_price - product.discount)
+ end
+ sum
+ end
+
+ def use(coupon_name)
+ coupon = get_coupon_by_name(coupon_name)
+ @discount = case coupon.coupon_value.to_a[0][0]
+ when :percent
+ (total * coupon.coupon_value.to_a[0][1]) / 100
+ when :amount
+ total - coupon.coupon_value.to_a[0][1].to_i
+ else
+ raise "Invalid coupon!"
+ end
+ end
+
+ def calculate_discount(prod, qty)
+ promo_value = prod.promotion.promo_value
+ @discount = case prod.promotion.promo_name
+ when :get_one_free
+ @discount = ((qty / promo_value).to_i) * prod.price.to_f
+ when :package
+ package_discount(prod, qty, promo_value)
+ when :threshold
+ (qty - promo_value.to_a[0][0]) * (prod.price.to_f * promo_value.to_a[0][1] / 100)
+ end
+ end
+
+ def package_discount(prod, qty, promo_value)
+ @discount = ((qty / promo_value.to_a[0][0]).to_i) * promo_value.to_a[0][0] *
+ (prod.price.to_f * promo_value.to_a[0][1] / 100)
+ end
+
+ def invoice
+ InvoiceUtils.print_header
+ bought_products.each do |bought_product|
+ formatted_price = '%.2f' % bought_product.regular_price
+ formatted_discount = '%.2f' % bought_product.discount
+ InvoiceUtils.print_product_line(
+ bought_product.product_name, bought_product.quantity, formatted_price)
+ InvoiceUtils.print_promo_line(bought_product)
+ end
+ InvoiceUtils.print_footer('%.2f' % (total - @discount).to_f)
+ end
+end
+
+class InvoiceUtils
+ def InvoiceUtils.print_header
+ puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
+ puts "| Name".ljust(45) + "qty |" + "price |".rjust(11)
+ puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
+ end
+
+ def InvoiceUtils.print_product_line(prod_name, qty, price)
+ puts "| #{prod_name.ljust(43)}" + " #{qty.to_s.rjust(2)} |" + "#{price.rjust(9)} |"
+ end
+
+ def InvoiceUtils.print_promo_line(bought_product)
+ if bought_product.discount > 0
+ formatted_discount = '%.2f' % (bought_product.discount * (-1))
+ puts "| #{bought_product.promo_name.to_s.ljust(44)} |" +
+ "#{formatted_discount.to_s.rjust(9)} |"
+ end
+ end
+
+ def InvoiceUtils.print_footer(total)
+ puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
+ puts "| TOTAL".ljust(45) + " |" + "#{total} |".rjust(11)
+ puts "+" + "".rjust(48, '-') + "+" + "".rjust(10, '-') + "+"
+ end
+end