wunder 0.1.0 → 0.1.3

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: 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