wunder 0.1.0 → 0.1.3

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
  SHA256:
3
- metadata.gz: 3e8f6b22d9b6d0c9044da576131e9d7f3bd3313f695873fe451789458ca0564c
4
- data.tar.gz: be323501c72c54d920bbd96132eb2da25cb3945f708826b029164647d1a3b858
3
+ metadata.gz: 20f583583705c30caecbe64d86d42c51fa75a81c70d825fded9aa914596dfdd2
4
+ data.tar.gz: 6bb8d8b8423368dc407632cda431e8aac60b47c5bd79406b04a17580fbf1b605
5
5
  SHA512:
6
- metadata.gz: a0aa9d6fc612de24191aff79c8315fdfa2dcdf0c0e0212de0aee34bafcb3e63630116a794ad90584ffb4f7ee1b1717a2de8b9736d42d92ecc3cbd19cce6f18f0
7
- data.tar.gz: 59ab31d94eb31ed66352e5ad23f4d4b44ec4111b7a9a80e569a3985b02ba0f01bbd8128cef556f93636d0ae6ebaf96f9df08369c21838c0c93c4c16081d8f94d
6
+ metadata.gz: 9476befdb75097f7dac10e039e6a136bb672c2a52015ffc0e62067264c61be9fe965e15662052c4af6a8d0ae9655907e49ab2ea2e0424ef8e3107dbcf5cc8e43
7
+ data.tar.gz: 0a2a50de553eacd6f20a8f56177c5aac5155b2f1ba6cfd1bad0a749d4ea4ea1d683d1b68c98217799e024b464595b8d9cce1fc6529c80bb8672ab8c4a5bf48ca
data/Gemfile.lock CHANGED
@@ -15,11 +15,13 @@ GEM
15
15
  coderay (1.1.2)
16
16
  concurrent-ruby (1.0.5)
17
17
  diff-lcs (1.3)
18
+ docile (1.3.1)
18
19
  faker (1.8.7)
19
20
  i18n (>= 0.7)
20
21
  i18n (1.0.1)
21
22
  concurrent-ruby (~> 1.0)
22
23
  jaro_winkler (1.5.1)
24
+ json (2.1.0)
23
25
  method_source (0.9.0)
24
26
  money (6.11.3)
25
27
  i18n (>= 0.6.4, < 1.1)
@@ -56,6 +58,11 @@ GEM
56
58
  rubocop-rspec (1.25.1)
57
59
  rubocop (>= 0.53.0)
58
60
  ruby-progressbar (1.9.0)
61
+ simplecov (0.16.1)
62
+ docile (~> 1.1)
63
+ json (>= 1.8, < 3)
64
+ simplecov-html (~> 0.10.0)
65
+ simplecov-html (0.10.2)
59
66
  sub-inspector (0.1.5)
60
67
  rubocop (~> 0.55)
61
68
  rubocop-rspec (~> 1.25.1)
@@ -75,6 +82,7 @@ DEPENDENCIES
75
82
  rake (~> 10.0)
76
83
  rspec (~> 3.0)
77
84
  rubocop (~> 0.57)
85
+ simplecov (~> 0.16)
78
86
  sub-inspector (= 0.1.5)
79
87
  wunder!
80
88
 
data/README.md CHANGED
@@ -1,18 +1,16 @@
1
1
  [![Build Status](https://travis-ci.org/basicsaki/wunder.svg?branch=master)](https://travis-ci.org/basicsaki/wunder)
2
2
 
3
3
 
4
- # Checkout
4
+ # Wunder
5
5
 
6
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/checkout`. To experiment with that code, run `bin/console` for an interactive prompt.
7
-
8
- TODO: Delete this and the text above, and describe your gem
6
+ Sample ruby code for a checkout system with flexible rules.
9
7
 
10
8
  ## Installation
11
9
 
12
10
  Add this line to your application's Gemfile:
13
11
 
14
12
  ```ruby
15
- gem 'checkout'
13
+ gem 'wunder'
16
14
  ```
17
15
 
18
16
  And then execute:
@@ -23,15 +21,84 @@ Or install it yourself as:
23
21
 
24
22
  $ gem install checkout
25
23
 
26
- ## Usage
24
+ ## Steps to add a new rule
25
+
26
+ Create a new file in the folder
27
+
28
+ lib/wunder/promotional/rule/*.rb
29
+
30
+ Capture any value or paramters in the initialize method.
31
+
32
+ Make sure that the below mentioned methods are available in the file.
33
+
34
+ If the discount is on basket define adjustable method as mentioned below.
35
+
36
+ Total is the parameter after discounts on individual items.
37
+ Define calculate_discounted_price to compute the new value after discounts.
38
+ return false if your rule has only item specific discounts.
39
+
40
+ def adjustable?(total)
41
+ return true if total > value
42
+ false
43
+ end
44
+
45
+ def calculate_discounted_price(basket_item, discount_type)
46
+ if discount_type == "percentage"
47
+ discount = compute_discount(basket_item)
48
+ basket_item.product.price = discount
49
+ elsif discount_type == "flat_rate"
50
+ basket_item.product.price = value
51
+ end
52
+ end
53
+
54
+ If the discount is on an item define eligible method as mentioned below.Item is the individual item scaned during the checkout.
55
+ Define calculate_total_discounted_price to compute the new value after discounts.
56
+ return false if your rule has only basket specific discounts.
57
+
58
+ def eligible?(_item)
59
+ false
60
+ end
61
+
62
+ def calculate_total_discounted_price(total, discount_type)
63
+ if discount_type == "percentage"
64
+ discount_price = total - ((total * value) / 100)
65
+ elsif discount_type == "flat_rate"
66
+ discount_price = total
67
+ end
68
+ discount_price
69
+ end
27
70
 
28
- TODO: Write usage instructions here
71
+ Methods in concerns/rule_validations can be used readily to validate the input parameters while capturing the rule.
29
72
 
30
- ## Development
73
+ ##Example
31
74
 
32
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
75
+ An interface example has been added at path wunder/lib/interface.rb to calculate and add existing rules.
33
76
 
34
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
77
+ ruby lib/interface.rb
78
+
79
+ To run the tests
80
+
81
+ rspec spec
82
+
83
+ To check rubocop style guidelines
84
+
85
+ rubocop
86
+
87
+ To check dependent gem venerabilites
88
+
89
+ bundle audit
90
+
91
+
92
+ #Note
93
+ For rubocop enforcements using a gem sub-inspector for ruby gems.
94
+
95
+
96
+ #Ruby documentation
97
+ https://www.rubydoc.info/gems/wunder
98
+
99
+ ##Future Scope
100
+ Making seperate modules for checkout,promotional rules and parsing products.
101
+ Adding priority to rules as many rules can be applied to many products. The order in which the rules are applied can be be sorted.
35
102
 
36
103
  ## Contributing
37
104
 
@@ -44,3 +111,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
44
111
  ## Code of Conduct
45
112
 
46
113
  Everyone interacting in the Checkout project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/checkout/blob/master/CODE_OF_CONDUCT.md).
114
+
data/lib/interface.rb CHANGED
@@ -4,36 +4,34 @@ require_relative "./wunder.rb"
4
4
  # Parser
5
5
  # new expects csv file path,validate {true or false},use mock file true or false
6
6
  parser = Parser.new("", true, true)
7
- parser.process_file
8
7
 
9
- # Product Collection
10
- products = parser.products
8
+ label = "Percentage discount on prices"
9
+ label1 = "Flat_rate discount on prices"
11
10
 
12
- # promotion
13
- promotion = Promotion.new("new_year", "1234")
14
11
 
15
12
  # rules
16
- quantity_rule_1 = Promotional::Rule::QuantityPrice.new(1, 10)
17
- quantity_rule_2 = Promotional::Rule::QuantityPrice.new(1, 10)
18
-
19
- # promotional rules
20
- label_1 = "Flat_rate discount on prices"
21
- label_2 = "percentage discount on prices"
22
-
23
- promotion_rule_1 = PromotionalRule.new(label_2, "percentage", true, quantity_rule_2)
24
- promotion_rule_2 = PromotionalRule.new(label_1, "flat_rate", true, quantity_rule_1)
13
+ quantity_rule1 = Promotional::Rule::ItemQuantityPriceRule.new(1, 10)
14
+ quantity_rule2 = Promotional::Rule::BasketRule.new(20)
15
+ # promotion
16
+ promotion = Promotion.new("New Year Flat Discount", "code_115")
17
+ promotion_rule1 = PromotionalRule.new(label, "percentage", true, quantity_rule1)
18
+ promotion_rule2 = PromotionalRule.new(label, "flat_rate", true, quantity_rule1)
19
+ promotion_rule3 = PromotionalRule.new(label1, "percentage", false, quantity_rule2)
20
+ promotion_rule4 = PromotionalRule.new(label1, "flat_rate", false, quantity_rule2)
21
+ rules = [promotion_rule1,promotion_rule2,promotion_rule3, promotion_rule4]
22
+ promotion.add_rules_in_bulk(rules)
25
23
 
26
24
 
27
- promotion.add_rules_in_bulk([promotion_rule_2,promotion_rule_1])
25
+ #File processing
26
+ parser.process_file
27
+ products = parser.products
28
28
 
29
- # promotional Rules
30
29
  # Checkout interface
31
30
  # scan(item) #remove_scan(item)
32
-
33
31
  co = Checkout.new(promotion.promotion_rules)
34
-
35
32
  co.scan(products[0])
36
33
  co.scan(products[1])
34
+ co.remove_scan(products[1])
37
35
  co.scan(products[2])
38
36
 
39
37
  table = Print.new([co]).table
@@ -1,9 +1,11 @@
1
1
  class Adjustment
2
- attr_reader :basket, :promotional_rules, :basket_without_discounts
2
+ attr_reader :basket, :promotional_rules
3
3
 
4
4
  def initialize(basket, promotional_rules)
5
5
  @basket = basket
6
6
  @promotional_rules = promotional_rules
7
+ @product_promotional_rules = []
8
+ @basket_promotional_rules = []
7
9
  @applied_promotional_rules = []
8
10
  end
9
11
 
@@ -31,10 +33,11 @@ class Adjustment
31
33
  end
32
34
 
33
35
  def apply_basket_discounts(items_total)
34
- @basket_promotional_rules = eligible_basket_promotional_discounts
36
+ @basket_promotional_rules =
37
+ eligible_basket_promotional_discounts(items_total)
35
38
 
36
39
  unless @basket_promotional_rules.empty?
37
- basket_promotional_rules.each do |promotional_rule|
40
+ @basket_promotional_rules.each do |promotional_rule|
38
41
  items_total = promotional_rule.calculate_total(items_total)
39
42
  end
40
43
  end
@@ -56,9 +59,9 @@ class Adjustment
56
59
  end
57
60
  end
58
61
 
59
- def eligible_basket_promotional_discounts
62
+ def eligible_basket_promotional_discounts(total)
60
63
  promotional_rules.select do |promo_rule|
61
- promo_rule.on_item == false
64
+ promo_rule.on_item == false && promo_rule.rule.adjustable?(total)
62
65
  end
63
66
  end
64
67
  end
data/lib/wunder/basket.rb CHANGED
@@ -19,6 +19,7 @@ class Basket
19
19
 
20
20
  def remove_item(product)
21
21
  item = items.find_product(product.product_code)
22
+ return if item.nil?
22
23
  if item.quantity == 1
23
24
  items.delete(item)
24
25
  else
@@ -1,5 +1,6 @@
1
1
  class ItemCollection < Array
2
2
  def find_product(product_code)
3
+ @item = nil
3
4
  each do |item|
4
5
  @item = item if item.product.product_code == product_code
5
6
  end
@@ -1,8 +1,8 @@
1
1
  module RuleValidations
2
2
  DISCOUNT_TYPES = %w[percentage flat_rate].freeze
3
3
 
4
- def should_be_present(name, attribute)
5
- raise "#{name} Should be present" if attribute == "" || attribute.nil?
4
+ def should_be_present(name, attr)
5
+ raise "#{name}.capitalize should be present" if attr == "" || attr.nil?
6
6
  end
7
7
 
8
8
  def check_discount_type(discount_type)
@@ -15,16 +15,11 @@ module RuleValidations
15
15
  raise "atleast fill out #{name}" if attr1.empty? && attr2.empty?
16
16
  end
17
17
 
18
- def atleast_one_should_be_present(name, attr1, attr2)
19
- raise "either fill out #{name}" if
20
- attr1.empty? == false && attr2.empty? == false
21
- end
22
-
23
18
  def should_be_a_number(name, attribute)
24
19
  raise "#{name} should be a number" if attribute.is_a?(Numeric) == false
25
20
  end
26
21
 
27
- def should_be_less_than(name, attribute, number)
22
+ def should_be_more_than(name, attribute, number)
28
23
  raise "#{name} should be >= #{number}" if attribute < number
29
24
  end
30
25
 
@@ -4,7 +4,7 @@ class Product
4
4
  def initialize(product_code, name, price, no_validate = false)
5
5
  @product_code = product_code
6
6
  @name = name
7
- @price = BigDecimal(price)
7
+ @price = price.nil? ? nil : BigDecimal(price, 2)
8
8
 
9
9
  validate if no_validate == false
10
10
  end
@@ -13,5 +13,6 @@ class Product
13
13
  [product_code, name, price].each do |parameter|
14
14
  raise ArgumentError, "ProductParameterMissing" if parameter.nil?
15
15
  end
16
+ nil
16
17
  end
17
18
  end
@@ -0,0 +1,40 @@
1
+ module Promotional
2
+ module Rule
3
+ class BasketRule < PromotionalRule
4
+ attr_reader :value
5
+
6
+ def initialize(value, no_validate = false)
7
+ @value = value
8
+
9
+ validate if no_validate == false
10
+ end
11
+
12
+ def adjustable?(total)
13
+ return true if total > value
14
+ false
15
+ end
16
+
17
+ def eligible?(_item)
18
+ false
19
+ end
20
+
21
+ def calculate_total_discounted_price(total, discount_type)
22
+ if discount_type == "percentage"
23
+ discount_price = total - ((total * value) / 100)
24
+ elsif discount_type == "flat_rate"
25
+ discount_price = total
26
+ end
27
+
28
+ discount_price
29
+ end
30
+
31
+ def validate
32
+ should_be_present("BasketRule::Value", value)
33
+ should_be_a_number("BasketRule::Value",
34
+ value)
35
+ should_be_more_than("BasketRule::MinQuantity",
36
+ value, 1)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,6 +1,6 @@
1
1
  module Promotional
2
2
  module Rule
3
- class QuantityPrice < PromotionalRule
3
+ class ItemQuantityPriceRule < PromotionalRule
4
4
  attr_reader :minimum_quantity, :value
5
5
 
6
6
  def initialize(minimum_quantity, value, no_validate = false)
@@ -14,21 +14,25 @@ module Promotional
14
14
  item.quantity >= minimum_quantity
15
15
  end
16
16
 
17
+ def adjustable?(_total)
18
+ false
19
+ end
20
+
17
21
  def calculate_discounted_price(basket_item, discount_type)
18
- if discount_type == "percentage" && eligible?(basket_item)
22
+ if discount_type == "percentage"
19
23
  discount = compute_discount(basket_item)
20
24
  basket_item.product.price = discount
21
- elsif discount_type == "flat_rate" && eligible?(basket_item)
25
+ elsif discount_type == "flat_rate"
22
26
  basket_item.product.price = value
23
27
  end
24
28
  end
25
29
 
26
- def calulate_total_discounted_price(total); end
27
-
28
30
  def validate
29
- should_be_present("QuantityPrice::Value", value)
30
- should_be_a_number("QuantiyPrice::MinimumQuantity", minimum_quantity)
31
- should_be_less_than("QuantityPrice::MinQuantity", minimum_quantity, 1)
31
+ should_be_present("ItemQuantityPriceRule::Value", value)
32
+ should_be_a_number("ItemQuantityPriceRule::MinimumQuantity",
33
+ minimum_quantity)
34
+ should_be_more_than("ItemQuantityPriceRule::MinQuantity",
35
+ minimum_quantity, 1)
32
36
  end
33
37
 
34
38
  private
@@ -18,6 +18,10 @@ class PromotionalRule
18
18
  raise "Should be defined by the respective rule"
19
19
  end
20
20
 
21
+ def adjustable?(_total)
22
+ raise "Should be defined by the respective rule"
23
+ end
24
+
21
25
  def validate
22
26
  should_be_present("label", label)
23
27
  check_discount_type(discount_type)
@@ -1,3 +1,3 @@
1
1
  module Wunder
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.1.3".freeze
3
3
  end
data/wunder.gemspec CHANGED
@@ -36,13 +36,12 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency "terminal-table","~> 1.8"
37
37
 
38
38
  spec.add_development_dependency "pry", "~> 0.11"
39
+ spec.add_development_dependency "simplecov","~> 0.16"
39
40
  spec.add_development_dependency "faker", "~> 1.8"
40
41
  spec.add_development_dependency "rubocop", "~> 0.57"
41
42
  spec.add_development_dependency "sub-inspector", "0.1.5"
42
-
43
43
  spec.add_development_dependency "bundler", "~> 1.16"
44
44
  spec.add_development_dependency "bundler-audit","~> 0.6"
45
-
46
45
  spec.add_development_dependency "rake", "~> 10.0"
47
46
  spec.add_development_dependency "rspec", "~> 3.0"
48
47
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wunder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akhilesh
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-23 00:00:00.000000000 Z
11
+ date: 2018-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: money
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.16'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.16'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: faker
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -184,7 +198,8 @@ files:
184
198
  - lib/wunder/print.rb
185
199
  - lib/wunder/product.rb
186
200
  - lib/wunder/promotion.rb
187
- - lib/wunder/promotional/rule/quantity_price.rb
201
+ - lib/wunder/promotional/rule/basket_rule.rb
202
+ - lib/wunder/promotional/rule/item_quantity_price_rule.rb
188
203
  - lib/wunder/promotional_rule.rb
189
204
  - lib/wunder/version.rb
190
205
  - wunder.gemspec