unit4-checkout 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 86c9a4b5ced5591d1e29fab651f213c6b2650bb4704e11635161b3af16076442
4
- data.tar.gz: 015c9dcccbc32478e8ac41875d506588c1319835a57764e985d1cb4140396bcc
3
+ metadata.gz: 3539766a2698101358c85167d1f34d563461cdc23b24098439e1948c2e815fba
4
+ data.tar.gz: 40bc469e6c776039f1d2d424b73d9904e08546181af2f95a117fbd9b4e39d553
5
5
  SHA512:
6
- metadata.gz: 9918c0698cae46a2e02bf767b000a4da06173a023f72b8bae9d4694d09e6b3a92e0a2b1fbceaab4438635253a2bc3a5f9e198f1c6d4079ef8dc9567c174f1aea
7
- data.tar.gz: e511b5b0a2ddf526f51ee5adbbece0c8ba91642203a18ba806100f8c4348e76f6c5218fbb21c31ba2dce68703723b7bd94da078d2fbfdb7adcb8182609bca0c0
6
+ metadata.gz: 7abf3c6c31eeaff5105c9f966d8751e14e94aeb585c31a7a6c3e42321797429ce6ae1e6a7fcd083e30801df9b4795144be22967bb5d759c81ca94af447ce146d
7
+ data.tar.gz: d5c3abb4a0ce0c7599fc5193d44d73560b7de229b1bdb8c9a1607ee71ab2dd569a860292487a9b05fac605082f950a0e6d001fc20a9e119940b03490c6e4a073
data/Gemfile CHANGED
@@ -14,5 +14,3 @@ gem "rubocop", "~> 1.21"
14
14
  gem "activerecord"
15
15
 
16
16
  gem "erb"
17
-
18
- # gem "sqlite3"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- unit4-checkout (0.1.0)
4
+ unit4-checkout (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,20 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_record"
4
- require "erb"
5
-
6
3
  class Checkout
7
- attr_reader :promotional_rules, :total, :basket, :price_discount_applied_flag
4
+ attr_reader :total
8
5
 
9
- # {product_discounts: {001: {count:2, price: 3.25}, 004: {count:2, price: 3.25}}, total_price_discount: $50}
10
- def initialize(promotional_rules)
11
- # maybe raise another error if keys aren't ids or total price, possibly total_item_count
12
- raise TypeError, "expected a Hash, got #{promotional_rules.class.name}" unless promotional_rules.is_a? Hash
6
+ def initialize(promotional_rules = {})
7
+ raise PromotionalRulesTypeError, promotional_rules.class.name unless promotional_rules.is_a? Hash
8
+ raise PromotionalRulesForbiddenKeys unless correct_keys?(promotional_rules)
13
9
 
14
10
  @promotional_rules = promotional_rules
15
11
  @total = 0
16
12
  @basket = Basket.new
17
- establish_connection
13
+ create_db_connection
14
+ end
15
+
16
+ def correct_keys?(promotional_rules)
17
+ (promotional_rules.keys - %i[product_discounts total_price_discount]).empty?
18
+ end
19
+
20
+ def create_db_connection
21
+ Connection.new
18
22
  end
19
23
 
20
24
  # maybe facilitate scanning multiple items at once
@@ -23,46 +27,78 @@ class Checkout
23
27
  # check for item id
24
28
  add_to_basket(item)
25
29
  calculate_total(item)
26
- puts "#{item.capitalize} has been added to the basket successfully!"
30
+ puts "Item with ID '#{item}' has been added to the basket successfully!"
27
31
  end
28
32
 
29
33
  def calculate_total(item)
30
- item_price = find_item_price(item)
31
- new_discount_available?(item) ? apply_discounts : @total += item_price
32
- @total
34
+ item_price = item_price(item)
35
+ if @total_price_discount_applied_flag
36
+ item_discounted?(item) ? apply_item_and_total_discount(item, item_price) : apply_total_discount_on_item(item_price)
37
+ else
38
+ item_discounted?(item) ? apply_item_discount(item, item_price) : @total += item_price
39
+ apply_total_discount if total_price_discounted?
40
+ end
41
+ @total = @total.round(2)
42
+ end
43
+
44
+ def item_price(item)
45
+ # TODO: facilitate DB name different from products, i.e. ask gem user for db name???
46
+ PriceQuery.new(item).find_price
47
+ end
48
+
49
+ def apply_item_and_total_discount(item, item_price)
50
+ item_prom_rules = @promotional_rules[:product_discounts][item]
51
+ item_basket_count = @basket.items[item]
52
+ total_discount = (1 - @promotional_rules[:total_price_discount][:percent] / 100.00)
53
+ @total += item_and_total(item_basket_count, item_prom_rules, total_discount, item_price)
33
54
  end
34
55
 
35
- def find_item_price(item)
36
- query = "SELECT * FROM 'users' WHERE 'users'.'id' = ?"
37
- sanitized_query = ActiveRecord::Base.sanitize_sql_array([query, item])
38
- execute_statement(sanitized_query)
39
- ActiveRecord::Base.connection.exec_query(sanitized_query)
56
+ def item_and_total(item_basket_count, item_prom_rules, total_discount, item_price)
57
+ if item_basket_count == item_prom_rules[:count]
58
+ (item_basket_count * item_prom_rules[:price] - (item_basket_count - 1) * item_price) * total_discount
59
+ else
60
+ item_basket_count * item_prom_rules[:price] * total_discount
61
+ end
40
62
  end
41
63
 
42
- def apply_discounts; end
64
+ def apply_total_discount_on_item(item_price)
65
+ @total += item_price * (1 - @promotional_rules[:total_price_discount][:percent] / 100.00)
66
+ end
43
67
 
44
- def new_discount_available?(item); end
68
+ def item_discounted?(item)
69
+ return false unless item_in_discounts?(item)
45
70
 
46
- def execute_statement(sql)
47
- results = ActiveRecord::Base.connection.exec_query(sql)
48
- results if results.present?
71
+ @basket.items[item] >= @promotional_rules[:product_discounts][item][:count]
49
72
  end
50
73
 
51
- def establish_connection
52
- db_config = setup_db_config
53
- ActiveRecord::Base.establish_connection(adapter: db_config["adapter"], database: db_config["database"])
74
+ def item_in_discounts?(item)
75
+ @promotional_rules[:product_discounts] && @promotional_rules[:product_discounts][item]
54
76
  end
55
77
 
56
- def setup_db_config
57
- if defined? Rails && defined? Rails.env
58
- Rails.application.config.database_configuration[Rails.env]
59
- else
60
- # TODO: use current database instead of development
61
- YAML.safe_load(ERB.new(File.read("./config/database.yml")).result, aliases: true)["development"]
62
- end
78
+ def apply_item_discount(item, item_price)
79
+ item_prom_rules = @promotional_rules[:product_discounts][item]
80
+ item_basket_count = @basket.items[item]
81
+ @total += if item_basket_count == item_prom_rules[:count]
82
+ item_basket_count * item_prom_rules[:price] - (item_basket_count - 1) * item_price
83
+ else
84
+ item_prom_rules[:price]
85
+ end
63
86
  end
64
87
 
65
- # maybe add remove item function
88
+ def total_price_discounted?
89
+ return false unless total_price_in_discounts?
90
+
91
+ @total >= @promotional_rules[:total_price_discount][:price]
92
+ end
93
+
94
+ def total_price_in_discounts?
95
+ @promotional_rules[:total_price_discount] && @promotional_rules[:total_price_discount][:price]
96
+ end
97
+
98
+ def apply_total_discount
99
+ @total *= (1 - @promotional_rules[:total_price_discount][:percent] / 100.00)
100
+ @total_price_discount_applied_flag = true
101
+ end
66
102
 
67
103
  def add_to_basket(item)
68
104
  @basket.items[item] ? @basket.items[item] += 1 : @basket.items[item] = 1
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "erb"
5
+
6
+ class Connection
7
+ def initialize
8
+ db_config = setup_db_config
9
+ ActiveRecord::Base.establish_connection(adapter: db_config["adapter"], database: db_config["database"])
10
+ end
11
+
12
+ def setup_db_config
13
+ defined?(Rails) && defined?(Rails.env) ? rails_db_config : non_rails_db_config
14
+ end
15
+
16
+ def rails_db_config
17
+ Rails.application.config.database_configuration[Rails.env]
18
+ end
19
+
20
+ def non_rails_db_config
21
+ # TODO: use current database instead of development
22
+ YAML.safe_load(ERB.new(File.read("./config/database.yml")).result, aliases: true)["development"]
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PromotionalRulesTypeError < TypeError
4
+ def initialize(class_name, msg = "expected a Hash, got ", exception_type = "custom")
5
+ msg += class_name
6
+ @exception_type = exception_type
7
+ super(msg)
8
+ end
9
+ end
10
+
11
+ class PromotionalRulesForbiddenKeys < TypeError
12
+ def initialize(msg = "expected Hash with optional keys 'product_discounts' and 'total_price_discount", exception_type = "custom")
13
+ @exception_type = exception_type
14
+ super(msg)
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ class PriceQuery
2
+
3
+ def initialize(item)
4
+ @sanitized_query = prepare_sql_statement(item)
5
+ end
6
+
7
+ def prepare_sql_statement(item)
8
+ # TODO: keep seen items in cache or variable !!!!!!!!!
9
+ ActiveRecord::Base.sanitize_sql_array(["SELECT 'products'.'price' FROM 'products' WHERE 'products'.'id' = ?", item])
10
+ end
11
+
12
+ def find_price
13
+ results = ActiveRecord::Base.connection.exec_query(@sanitized_query)
14
+ results.rows.first.first if results.present?
15
+ end
16
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Unit4
4
4
  module Checkout
5
- VERSION = "0.1.2"
5
+ VERSION = "0.2.1"
6
6
  end
7
7
  end
@@ -3,6 +3,9 @@
3
3
  require_relative "checkout/version"
4
4
  require_relative "checkout/checkout"
5
5
  require_relative "checkout/basket"
6
+ require_relative "checkout/connection"
7
+ require_relative "checkout/price_query"
8
+ require_relative "checkout/exceptions"
6
9
 
7
10
  module Unit4
8
11
  module Checkout
metadata CHANGED
@@ -1,16 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unit4-checkout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boyan Georgiev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-21 00:00:00.000000000 Z
11
+ date: 2022-07-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Initial commit
13
+ description: A Ruby gem that helps the user implement a checkout system by supplying
14
+ only the promotional rules
14
15
  email:
15
16
  - bbgeorgiev96@gmail.com
16
17
  executables: []
@@ -26,10 +27,14 @@ files:
26
27
  - lib/unit4/checkout.rb
27
28
  - lib/unit4/checkout/basket.rb
28
29
  - lib/unit4/checkout/checkout.rb
30
+ - lib/unit4/checkout/connection.rb
31
+ - lib/unit4/checkout/exceptions.rb
32
+ - lib/unit4/checkout/price_query.rb
29
33
  - lib/unit4/checkout/version.rb
30
34
  - sig/unit4/checkout.rbs
31
35
  homepage: https://github.com/BoyanGeorgiev96/unit4-checkout
32
- licenses: []
36
+ licenses:
37
+ - MIT
33
38
  metadata:
34
39
  allowed_push_host: https://rubygems.org/
35
40
  homepage_uri: https://github.com/BoyanGeorgiev96/unit4-checkout
@@ -52,5 +57,5 @@ requirements: []
52
57
  rubygems_version: 3.3.3
53
58
  signing_key:
54
59
  specification_version: 4
55
- summary: Initial commit
60
+ summary: Checkout gem for Unit4 technical task
56
61
  test_files: []