cash_register 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52a2bb5fc6d54dc472ab92d68f6948f4a250c206
4
- data.tar.gz: cd84b56a3b90ff8398aeae47d67ed1c4c10a2861
3
+ metadata.gz: 0b6e16af5305bd7b90f3dce3eab1641d4b499a48
4
+ data.tar.gz: b8593e873e1e91fd160590e731daa64fc307070d
5
5
  SHA512:
6
- metadata.gz: 34037ca8c24eccd8baca97d9146352651e02802abd1af9561c01068f0dec0a57954385b99dde67b09b19e9d9d86a20c81bbbfd92e5ccd5e0d13721dc79f94667
7
- data.tar.gz: aa20a28b7e31b74aea28930588c36f388b548a385a1a8d8691686ed4cc78ee866d4232fc6190ef74e90aa0b42937553a57c834ce9a8612adc6992d4c3c239eb0
6
+ metadata.gz: d283e22982a79dede3e124b965e52484006fc783b18ad66b888bdd60d1d41966e8ce45bcffa995557354ba5521f8e91dcb04edcd9fed74f4d3f6a077ee026f17
7
+ data.tar.gz: d7d9695fd22acdb2aa341570ed94c23dfe640917fe56ff8f7f65c49d408a45c707f0adc8d7657caa37b1239b6353bee2fa1e6e6492cdf7ba5ef498c15f97124a
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ A basic cash register
2
+
3
+ 商店里进行购物结算时会使用收银机系统,这台收银机会在结算时根据客户的购物车中的商品和商店正在进行的优惠活动进行结算和打印购物小票。
4
+
5
+ 已知商品信息包含:名称,数量单位,单价,类别和条形码(伪)。
6
+ 已知我们可以对收银机进行设置,使之支持各种优惠。
7
+
8
+ 我们需要实现一个名为打印小票的小模块,收银机会将输入的数据转换成一个JSON数据然后一次性传给我们这个小模块,我们将从控制台中输出结算清单的文本。
9
+
10
+ 输入格式(样例):
11
+ ```Ruby
12
+ [
13
+ 'ITEM000001',
14
+ 'ITEM000001',
15
+ 'ITEM000001',
16
+ 'ITEM000001',
17
+ 'ITEM000001',
18
+ 'ITEM000003-2',
19
+ 'ITEM000005',
20
+ 'ITEM000005',
21
+ 'ITEM000005'
22
+ ]
23
+ ```
24
+ 其中对'ITEM000003-2'来说,"-"之前的是标准的条形码,"-"之后的是数量。
25
+ 当我们购买需要称量的物品的时候,由称量的机器生成此类条形码,收银机负责识别生成小票。
26
+
27
+ 该商店正在对部分商品进行“买二赠一”的优惠活动和对部分商品进行95折的优惠活动。其中:
28
+ * “买二赠一”是指,每当买进两个商品,就可以免费再买一个相同商品。
29
+ * “95折”是指,在计算小计的时候按单价的95%计算每个商品。
30
+ * 每一种优惠都详细标记了哪些条形码对应的商品可以享受此优惠。
31
+ * 店员设置,当“95折”和“买二赠一”发生冲突的时候,也就是一款商品既符合享受“买二赠一”优惠的条件,又符合享受“95折”优惠的 * 条件时,只享受“买二赠一”优惠。
32
+ * 要求写代码支持上述的功能,并根据输入和设置的不同,输出下列小票。
33
+ 小票内容及格式(样例):
34
+
35
+ 当购买的商品中,有符合“买二赠一”优惠条件的商品时:
36
+ ```Ruby
37
+ ***<没钱赚商店>购物清单***
38
+ 名称:可口可乐,数量:3瓶,单价:3.00(元),小计:6.00(元)
39
+ 名称:羽毛球,数量:5个,单价:1.00(元),小计:4.00(元)
40
+ 名称:苹果,数量:2斤,单价:5.50(元),小计:11.00(元)
41
+ ----------------------
42
+ 买二赠一商品:
43
+ 名称:可口可乐,数量:1瓶
44
+ 名称:羽毛球,数量:1个
45
+ ----------------------
46
+ 总计:21.00(元)
47
+ 节省:4.00(元)
48
+ **********************
49
+ ```
50
+ 当购买的商品中,没有符合“买二赠一”优惠条件的商品时:
51
+ ```Ruby
52
+ ***<没钱赚商店>购物清单***
53
+ 名称:可口可乐,数量:3瓶,单价:3.00(元),小计:9.00(元)
54
+ 名称:羽毛球,数量:5个,单价:1.00(元),小计:5.00(元)
55
+ 名称:苹果,数量:2斤,单价:5.50(元),小计:11.00(元)
56
+ ----------------------
57
+ 总计:25.00(元)
58
+ **********************
59
+ ```
60
+ 当购买的商品中,有符合“95折”优惠条件的商品时
61
+ ```Ruby
62
+ ***<没钱赚商店>购物清单***
63
+ 名称:可口可乐,数量:3瓶,单价:3.00(元),小计:9.00(元)
64
+ 名称:羽毛球,数量:5个,单价:1.00(元),小计:5.00(元)
65
+ 名称:苹果,数量:2斤,单价:5.50(元),小计:10.45(元),节省0.55(元)
66
+ ----------------------
67
+ 总计:24.45(元)
68
+ 节省:0.55(元)
69
+ **********************
70
+ ```
71
+ 当购买的商品中,有符合“95折”优惠条件的商品,又有符合“买二赠一”优惠条件的商品时
72
+ ```Ruby
73
+ ***<没钱赚商店>购物清单***
74
+ 名称:可口可乐,数量:3瓶,单价:3.00(元),小计:6.00(元)
75
+ 名称:羽毛球,数量:6个,单价:1.00(元),小计:4.00(元)
76
+ 名称:苹果,数量:2斤,单价:5.50(元),小计:10.45(元),节省0.55(元)
77
+ ----------------------
78
+ 买二赠一商品:
79
+ 名称:可口可乐,数量:1瓶
80
+ 名称:羽毛球,数量:2个
81
+ ----------------------
82
+ 总计:20.45(元)
83
+ 节省:4.55(元)
84
+ **********************
85
+ ```
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+ #商品类
3
+ module CashRegister
4
+ class Deal
5
+ attr_accessor :code, :name, :price, :unit
6
+ def initialize(args)
7
+ assign_attributes(args)
8
+ end
9
+
10
+ private
11
+ def assign_attributes(args)
12
+ args.each do |attribute, value|
13
+ send "#{attribute}=", value
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+ #商品列表
3
+ require 'json'
4
+ module CashRegister
5
+ module Deals
6
+ class InvalidDealError < ::StandardError
7
+ end
8
+ class << self
9
+ def init_deals(deals_json_path)
10
+ @deals ||= {}
11
+ (JSON.parse(File.read(deals_json_path)) rescue []).map do |deal|
12
+ @deals[deal['code']] = Deal.new(deal)
13
+ end
14
+ end
15
+
16
+ def find_by_code(code = '')
17
+ deal = @deals[code]
18
+ raise InvalidDealError if deal.nil?
19
+ deal
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ require_relative "normal_item"
3
+ module CashRegister
4
+ class DiscountItem < NormalItem
5
+ def saving
6
+ deal.price * count * 0.05
7
+ end
8
+
9
+ def billing
10
+ total = super
11
+ total - saving
12
+ end
13
+
14
+ def to_s
15
+ super + ",节省:#{format_price saving}(元)"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: UTF-8
2
+ module CashRegister
3
+ class FreeItem < NormalItem
4
+ def to_s
5
+ "名称:#{deal.name},数量:#{count}#{deal.unit}"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module CashRegister
2
+ module Helper
3
+ def format_price(price)
4
+ format('%.2f', price)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ module CashRegister
3
+ class ListItem
4
+ attr_accessor :deal, :count
5
+ attr_reader :free_item, :item
6
+
7
+ def initialize(code, count)
8
+ @deal = Deals.find_by_code(code)
9
+ @count = count
10
+ @item ||= if Promotions.is_two_for_one?(deal.code)
11
+ free_num = count/3
12
+ @free_item = FreeItem.new(deal, free_num)
13
+ Two4OneItem.new(deal, count)
14
+ elsif Promotions.is_discount?(deal.code)
15
+ DiscountItem.new(deal, count)
16
+ else
17
+ NormalItem.new(deal, count)
18
+ end
19
+ end
20
+
21
+ def to_s
22
+ item.to_s
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+ require_relative "helper"
3
+
4
+ module CashRegister
5
+ class NormalItem
6
+ include CashRegister::Helper
7
+ attr_accessor :deal, :count
8
+
9
+ def initialize(deal, count)
10
+ @deal = deal
11
+ @count = count
12
+ end
13
+
14
+ def billing
15
+ @billing ||= deal.price * count
16
+ end
17
+
18
+ def saving
19
+ 0
20
+ end
21
+
22
+ def to_s
23
+ "名称:#{deal.name},数量:#{count}#{deal.unit},单价:#{format_price deal.price}(元),小计:#{format_price billing}(元)"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ require 'json'
2
+ module CashRegister
3
+ #促销列表
4
+ module Promotions
5
+ class << self
6
+ def init_promotions(promotions_json_path)
7
+ @promotions ||= {}
8
+ (JSON.parse(File.read(promotions_json_path)) rescue []).map do |promotion|
9
+ @promotions[promotion['type']] = promotion['deals']
10
+ end
11
+ end
12
+
13
+ def is_two_for_one?(code = '')
14
+ (@promotions['TWO_FOR_ONE_FREE'] || []).include?(code)
15
+ end
16
+
17
+ def is_discount?(code = '')
18
+ (@promotions['DISCOUNT'] || []).include?(code)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+ module CashRegister
3
+ class Two4OneItem < NormalItem
4
+ def billing
5
+ @billing ||= deal.price * (count - count/3)
6
+ end
7
+
8
+ def saving
9
+ @saving ||= deal.price * count - billing
10
+ end
11
+ end
12
+ end
data/lib/cash_register.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # encoding: UTF-8
2
2
  require 'json'
3
3
  Dir["#{File.dirname(__FILE__)}/cash_register/*.rb"].sort.each { |f| require f }
4
-
4
+ require_relative 'cash_register/helper'
5
5
  module CashRegister
6
6
  class << self
7
- include Util
7
+ include CashRegister::Helper
8
8
 
9
9
  def output_bill(input_list)
10
10
  output = []
@@ -24,10 +24,6 @@ module CashRegister
24
24
  output
25
25
  end
26
26
 
27
- def root
28
- File.dirname __dir__
29
- end
30
-
31
27
  private
32
28
  def dashed_line
33
29
  '-'*22
@@ -38,7 +34,6 @@ module CashRegister
38
34
  end
39
35
 
40
36
  def output_summary(items)
41
- p items.map(&:billing)
42
37
  output = []
43
38
  output << dashed_line
44
39
  total_payment = items.map(&:billing).inject(&:+)
@@ -59,8 +54,7 @@ module CashRegister
59
54
  free_items.map{ |free_item| free_item.to_s }
60
55
  end
61
56
 
62
- def read_list(input_list)
63
- input_list_path = File.join(CashRegister.root, input_list)
57
+ def read_list(input_list_path)
64
58
  (JSON.parse(File.read(input_list_path)) rescue []).inject({}) do |mem, input_item|
65
59
  code, count = input_item.split('-')
66
60
  mem[code] ||= 0
@@ -6,8 +6,12 @@ RSpec.describe CashRegister::Deals do
6
6
  CashRegister::Deals.init_deals('spec/fixture/all_deals.json')
7
7
  end
8
8
 
9
- it "Deals" do
9
+ it "Valid Deal" do
10
10
  deal = CashRegister::Deals.find_by_code('ITEM000001')
11
11
  expect(deal.name).to eq('可口可乐')
12
12
  end
13
+
14
+ it "Invalid Deal" do
15
+ expect{ CashRegister::Deals.find_by_code('ITEM00') }.to raise_error(CashRegister::Deals::InvalidDealError)
16
+ end
13
17
  end
@@ -0,0 +1,9 @@
1
+ require_relative '../../lib/cash_register/helper'
2
+
3
+ RSpec.describe CashRegister::Helper do
4
+ include CashRegister::Helper
5
+
6
+ it "format price" do
7
+ expect(format_price(1)).to eq('1.00')
8
+ end
9
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cash_register
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Clark King
@@ -30,16 +30,26 @@ executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
+ - README.md
33
34
  - lib/cash_register.rb
35
+ - lib/cash_register/deal.rb
36
+ - lib/cash_register/deals.rb
37
+ - lib/cash_register/discount_item.rb
38
+ - lib/cash_register/free_item.rb
39
+ - lib/cash_register/helper.rb
40
+ - lib/cash_register/list_item.rb
41
+ - lib/cash_register/normal_item.rb
42
+ - lib/cash_register/promotions.rb
43
+ - lib/cash_register/two4one_item.rb
34
44
  - spec/cash_register/deal_spec.rb
35
45
  - spec/cash_register/deals_spec.rb
36
46
  - spec/cash_register/discount_item_spec.rb
37
47
  - spec/cash_register/free_item_spec.rb
48
+ - spec/cash_register/helper_spec.rb
38
49
  - spec/cash_register/list_item_spec.rb
39
50
  - spec/cash_register/normal_item_spec.rb
40
51
  - spec/cash_register/promotions_spec.rb
41
52
  - spec/cash_register/two4one_item_spec.rb
42
- - spec/cash_register/util_spec.rb
43
53
  - spec/cash_register_spec.rb
44
54
  - spec/fixture/all_deals.json
45
55
  - spec/fixture/deals_dual_promotion.json
@@ -78,11 +88,11 @@ test_files:
78
88
  - spec/cash_register/free_item_spec.rb
79
89
  - spec/cash_register/two4one_item_spec.rb
80
90
  - spec/cash_register/deal_spec.rb
91
+ - spec/cash_register/helper_spec.rb
81
92
  - spec/cash_register/normal_item_spec.rb
82
93
  - spec/cash_register/deals_spec.rb
83
94
  - spec/cash_register/list_item_spec.rb
84
95
  - spec/cash_register/discount_item_spec.rb
85
- - spec/cash_register/util_spec.rb
86
96
  - spec/cash_register/promotions_spec.rb
87
97
  - spec/spec_helper.rb
88
98
  - spec/cash_register_spec.rb
@@ -1,9 +0,0 @@
1
- require_relative '../../lib/cash_register/util'
2
-
3
- RSpec.describe CashRegister::Util do
4
- include CashRegister::Util
5
-
6
- it "format price" do
7
- expect(format_price(1)).to eq('1.00')
8
- end
9
- end