solidus_volume_pricing 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +35 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +8 -4
  5. data/.rubocop_todo.yml +126 -0
  6. data/CHANGELOG.md +57 -0
  7. data/Gemfile +18 -4
  8. data/Guardfile +3 -1
  9. data/README.md +53 -48
  10. data/Rakefile +2 -0
  11. data/app/assets/javascripts/spree/backend/solidus_volume_pricing.js +1 -15
  12. data/app/controllers/spree/admin/volume_price_models_controller.rb +2 -1
  13. data/app/controllers/spree/admin/volume_prices_controller.rb +3 -1
  14. data/app/decorators/controllers/solidus_volume_pricing/spree/admin/variants_controller_decorator.rb +42 -0
  15. data/app/decorators/helpers/solidus_volume_pricing/spree/base_helper_decorator.rb +31 -0
  16. data/app/decorators/models/solidus_volume_pricing/spree/line_item_decorator.rb +18 -0
  17. data/app/decorators/models/solidus_volume_pricing/spree/user_decorator.rb +17 -0
  18. data/app/decorators/models/solidus_volume_pricing/spree/variant_decorator.rb +21 -0
  19. data/app/models/solidus_volume_pricing/price_display.rb +47 -0
  20. data/app/models/solidus_volume_pricing/pricer.rb +95 -0
  21. data/app/models/solidus_volume_pricing/pricing_options.rb +20 -0
  22. data/app/models/spree/volume_price.rb +43 -26
  23. data/app/models/spree/volume_price_model.rb +6 -4
  24. data/app/overrides/spree/admin/shared/_settings_sub_menu/add_volume_price_model_admin_menu_links.html.erb.deface +5 -0
  25. data/app/overrides/views_decorator.rb +2 -0
  26. data/app/views/spree/admin/shared/_vp_product_tab.html.erb +2 -2
  27. data/app/views/spree/admin/variants/_edit_fields.html.erb +5 -32
  28. data/app/views/spree/admin/variants/volume_prices.html.erb +9 -36
  29. data/app/views/spree/admin/volume_price_models/_form.html.erb +6 -2
  30. data/app/views/spree/admin/volume_price_models/_list.html.erb +8 -4
  31. data/app/views/spree/admin/volume_price_models/_select.html.erb +17 -0
  32. data/app/views/spree/admin/volume_price_models/edit.html.erb +7 -6
  33. data/app/views/spree/admin/volume_price_models/index.html.erb +7 -5
  34. data/app/views/spree/admin/volume_price_models/new.html.erb +5 -5
  35. data/app/views/spree/admin/volume_prices/_table.html.erb +26 -0
  36. data/app/views/spree/admin/volume_prices/_volume_price_fields.html.erb +6 -6
  37. data/app/views/spree/products/_volume_pricing.html.erb +8 -8
  38. data/bin/rails +3 -2
  39. data/config/locales/de.yml +17 -3
  40. data/config/locales/en.yml +21 -2
  41. data/config/locales/pt.yml +6 -2
  42. data/config/locales/ru.yml +6 -2
  43. data/config/locales/sv.yml +6 -2
  44. data/config/locales/tr.yml +6 -2
  45. data/config/routes.rb +3 -1
  46. data/db/migrate/20081119145604_create_volume_prices.rb +3 -1
  47. data/db/migrate/20110203174010_change_display_name_for_volume_prices.rb +3 -1
  48. data/db/migrate/20111206173307_prefix_volume_pricing_table_names.rb +3 -1
  49. data/db/migrate/20121115043422_add_discount_type_column.rb +3 -1
  50. data/db/migrate/20150513200904_add_role_to_volume_price.rb +3 -1
  51. data/db/migrate/20150603143015_create_spree_volume_price_models.rb +3 -1
  52. data/lib/generators/solidus_volume_pricing/install/install_generator.rb +3 -5
  53. data/lib/solidus_volume_pricing.rb +5 -1
  54. data/lib/solidus_volume_pricing/engine.rb +5 -22
  55. data/lib/solidus_volume_pricing/range_from_string.rb +36 -0
  56. data/lib/solidus_volume_pricing/version.rb +5 -3
  57. data/solidus_volume_pricing.gemspec +6 -14
  58. data/spec/controllers/spree/admin/variants_controller_spec.rb +18 -15
  59. data/spec/factories/volume_price_factory.rb +7 -5
  60. data/spec/features/manage_volume_price_models_feature_spec.rb +5 -3
  61. data/spec/features/manage_volume_prices_feature_spec.rb +6 -4
  62. data/spec/helpers/base_helper_spec.rb +3 -1
  63. data/spec/lib/solidus_volume_pricing/range_from_string_spec.rb +61 -0
  64. data/spec/models/solidus_volume_pricing/pricer_spec.rb +673 -0
  65. data/spec/models/solidus_volume_pricing/pricing_options_spec.rb +57 -0
  66. data/spec/models/spree/line_item_spec.rb +24 -21
  67. data/spec/models/spree/order_spec.rb +4 -2
  68. data/spec/models/spree/variant_spec.rb +3 -303
  69. data/spec/models/spree/volume_price_spec.rb +153 -49
  70. data/spec/spec_helper.rb +5 -38
  71. data/spec/support/shoulda.rb +11 -0
  72. metadata +37 -173
  73. data/.hound.yml +0 -40
  74. data/.travis.yml +0 -12
  75. data/CONTRIBUTING.md +0 -81
  76. data/app/controllers/spree/admin/variants_controller_decorator.rb +0 -32
  77. data/app/helpers/spree/base_helper_decorator.rb +0 -19
  78. data/app/models/spree/line_item_decorator.rb +0 -13
  79. data/app/models/spree/user_decorator.rb +0 -10
  80. data/app/models/spree/variant_decorator.rb +0 -104
  81. data/app/overrides/spree/admin/shared/sub_menu/_configuration/add_volume_price_model_admin_menu_links.html.erb.deface +0 -3
  82. data/app/views/spree/admin/volume_prices/_edit_fields.html.erb +0 -31
  83. data/spec/support/capybara.rb +0 -12
  84. data/spec/support/database_cleaner.rb +0 -21
  85. data/spec/support/factory_girl.rb +0 -7
  86. data/spec/support/spree.rb +0 -10
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe SolidusVolumePricing::PricingOptions do
6
+ let(:user) do
7
+ build_stubbed(:user)
8
+ end
9
+
10
+ it 'inherits from default pricing options class' do
11
+ expect(described_class < Spree::Variant::PricingOptions).to be(true)
12
+ end
13
+
14
+ describe 'new instances' do
15
+ subject do
16
+ described_class.new(quantity: 10, user: user)
17
+ end
18
+
19
+ it 'have a quantity attribute' do
20
+ expect(subject.quantity).to eq(10)
21
+ end
22
+
23
+ it 'have a user attribute' do
24
+ expect(subject.user).to eq(user)
25
+ end
26
+
27
+ it 'desired_attributes dont have quantity key' do
28
+ expect(subject.desired_attributes).not_to have_key(:quantity)
29
+ end
30
+
31
+ it 'desired_attributes dont have user key' do
32
+ expect(subject.desired_attributes).not_to have_key(:user)
33
+ end
34
+ end
35
+
36
+ describe '.from_line_item' do
37
+ subject do
38
+ described_class.from_line_item(line_item)
39
+ end
40
+
41
+ let(:order) do
42
+ build_stubbed(:order, user: user)
43
+ end
44
+
45
+ let(:line_item) do
46
+ build_stubbed(:line_item, quantity: 2, order: order)
47
+ end
48
+
49
+ it 'sets quantity to quantity of line item' do
50
+ expect(subject.quantity).to eq(2)
51
+ end
52
+
53
+ it 'sets user to user of line item' do
54
+ expect(subject.user).to eq(user)
55
+ end
56
+ end
57
+ end
@@ -1,34 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Spree::LineItem, type: :model do
4
+ let(:order) { create(:order) }
5
+ let(:variant) { create(:variant, price: 10) }
6
+ let(:line_item) { order.line_items.first }
7
+ let(:role) { create(:role) }
8
+
2
9
  before do
3
- @order = create(:order)
4
- @variant = create(:variant, price: 10)
5
- @variant.volume_prices.create! amount: 9, discount_type: 'price', range: '(2+)'
6
- @order.contents.add(@variant, 1)
7
- @line_item = @order.line_items.first
8
- @role = create(:role)
10
+ variant.volume_prices.create! amount: 9, discount_type: 'price', range: '(2+)'
11
+ order.contents.add(variant, 1)
9
12
  end
10
13
 
11
14
  it 'updates the line item price when the quantity changes to match a range and has no role' do
12
- expect(@line_item.price.to_f).to be(10.00)
13
- @order.contents.add(@variant, 1)
14
- expect(@order.line_items.first.price.to_f).to be(9.00)
15
+ expect(line_item.price.to_f).to be(10.00)
16
+ order.contents.add(variant, 1)
17
+ expect(order.line_items.first.price.to_f).to be(9.00)
15
18
  end
16
19
 
17
20
  it 'updates the line item price when the quantity changes to match a range and role matches' do
18
- @order.user.spree_roles << @role
19
- Spree::Config.volume_pricing_role = @role.name
20
- expect(@order.user.has_spree_role? @role.name.to_sym).to be(true)
21
- @variant.volume_prices.first.update(role_id: @role.id)
22
- expect(@line_item.price.to_f).to be(10.00)
23
- @order.contents.add(@variant, 1)
24
- expect(@order.line_items.first.price.to_f).to be(9.00)
21
+ order.user.spree_roles << role
22
+ stub_spree_preferences(volume_pricing_role: role.name)
23
+ expect(order.user.has_spree_role?(role.name.to_sym)).to be(true)
24
+ variant.volume_prices.first.update(role_id: role.id)
25
+ expect(line_item.price.to_f).to be(10.00)
26
+ order.contents.add(variant, 1)
27
+ expect(order.line_items.first.price.to_f).to be(9.00)
25
28
  end
26
29
 
27
30
  it 'does not update the line item price when the variant role and order role don`t match' do
28
- expect(@order.user.has_spree_role? @role.name.to_sym).to be(false)
29
- @variant.volume_prices.first.update(role_id: @role.id)
30
- expect(@line_item.price.to_f).to be(10.00)
31
- @order.contents.add(@variant, 1)
32
- expect(@order.line_items.first.price.to_f).to be(10.00)
31
+ expect(order.user.has_spree_role?(role.name.to_sym)).to be(false)
32
+ variant.volume_prices.first.update(role_id: role.id)
33
+ expect(line_item.price.to_f).to be(10.00)
34
+ order.contents.add(variant, 1)
35
+ expect(order.line_items.first.price.to_f).to be(10.00)
33
36
  end
34
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Spree::Order, type: :model do
2
4
  before do
3
5
  @order = create(:order)
@@ -31,7 +33,7 @@ RSpec.describe Spree::Order, type: :model do
31
33
  end
32
34
 
33
35
  it 'uses the master variant volume price in case variant has no volume price if config is true' do
34
- Spree::Config.use_master_variant_volume_pricing = true
36
+ stub_spree_preferences(use_master_variant_volume_pricing: true)
35
37
  @master = @variant.product.master
36
38
  @master.volume_prices << create(:volume_price, range: '(1..5)', amount: 9, position: 2)
37
39
  @order.contents.add(@variant, 5)
@@ -39,7 +41,7 @@ RSpec.describe Spree::Order, type: :model do
39
41
  end
40
42
 
41
43
  it 'doesnt use the master variant volume price in case variant has no volume price if config is false' do
42
- Spree::Config.use_master_variant_volume_pricing = false
44
+ stub_spree_preferences(use_master_variant_volume_pricing: false)
43
45
  @master = @variant.product.master
44
46
  @master.volume_prices << create(:volume_price, range: '(1..5)', amount: 9, position: 2)
45
47
  @order.contents.add(@variant, 5)
@@ -1,306 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Spree::Variant, type: :model do
2
4
  it { is_expected.to have_many(:volume_prices) }
3
-
4
- describe '#volume_price' do
5
-
6
- context 'discount_type = price' do
7
- before :each do
8
- @variant = create :variant, price: 10
9
- @variant.volume_prices.create! amount: 9, discount_type: 'price', range: '(10+)'
10
- @role = create(:role)
11
- @user = create(:user)
12
- end
13
-
14
- it 'uses the variants price when it does not match a range' do
15
- expect(@variant.volume_price(1).to_f).to be(10.00)
16
- end
17
-
18
- it 'uses the variants price when it does not match role with null role' do
19
- @variant.volume_prices.first.update(role_id: @role.id)
20
- expect(@variant.volume_price(10).to_f).to be(10.00)
21
- end
22
-
23
- it 'uses the variants price when it does not match roles' do
24
- other_role = create(:role)
25
- @user.spree_roles << other_role
26
- @variant.volume_prices.first.update(role_id: @role.id)
27
- expect(@variant.volume_price(10, @user).to_f).to be(10.00)
28
- end
29
-
30
- it 'uses the volume price when it does match a range' do
31
- expect(@variant.volume_price(10).to_f).to be(9.00)
32
- end
33
-
34
- it 'uses the volume price when it does match a range and role' do
35
- @user.spree_roles << @role
36
- Spree::Config.volume_pricing_role = @role.name
37
- @variant.volume_prices.first.update(role_id: @role.id)
38
- expect(@variant.volume_price(10, @user).to_f).to be(9.00)
39
- end
40
-
41
- it 'uses the volume price when it does match from a volume price model' do
42
- @variant.volume_price_models << create(:volume_price_model)
43
- @variant.volume_price_models.first.volume_prices.create!(amount: 5, discount_type: 'price', range: '(5+)')
44
- expect(@variant.volume_price(6).to_f).to be(5.00)
45
- end
46
-
47
- it 'gives percent of earning without role' do
48
- expect(@variant.volume_price_earning_percent(10)).to be(10)
49
- end
50
-
51
- it 'gives percent of earning if role matches' do
52
- @user.spree_roles << @role
53
- Spree::Config.volume_pricing_role = @role.name
54
- @variant.volume_prices.first.update(role_id: @role.id)
55
- expect(@variant.volume_price_earning_percent(10, @user)).to be(10)
56
- end
57
-
58
- it 'gives zero percent earning if doesnt match' do
59
- expect(@variant.volume_price_earning_percent(1)).to be(0)
60
- end
61
-
62
- it 'gives zero percent earning if role doesnt match with null' do
63
- @variant.volume_prices.first.update(role_id: @role.id)
64
- expect(@variant.volume_price_earning_percent(10)).to be(0)
65
- end
66
-
67
- it 'gives zero percent earning if role doesnt match' do
68
- other_role = create(:role)
69
- @user.spree_roles << other_role
70
- @variant.volume_prices.first.update(role_id: @role.id)
71
- expect(@variant.volume_price_earning_percent(10, @user)).to be(0)
72
- end
73
-
74
- it 'gives amount earning without role' do
75
- expect(@variant.volume_price_earning_amount(10)).to eq(1)
76
- end
77
-
78
- it 'gives amount earning if role matches' do
79
- @user.spree_roles << @role
80
- Spree::Config.volume_pricing_role = @role.name
81
- @variant.volume_prices.first.update(role_id: @role.id)
82
- expect(@variant.volume_price_earning_amount(10, @user)).to eq(1)
83
- end
84
-
85
- it 'gives zero earning amount if doesnt match' do
86
- expect(@variant.volume_price_earning_amount(1)).to eq(0)
87
- end
88
-
89
- it 'gives zero earning amount if role doesnt match with null' do
90
- @variant.volume_prices.first.update(role_id: @role.id)
91
- expect(@variant.volume_price_earning_amount(10)).to be(0)
92
- end
93
-
94
- it 'gives zero earning amount if role doesnt match' do
95
- other_role = create(:role)
96
- @user.spree_roles << other_role
97
- @variant.volume_prices.first.update(role_id: @role.id)
98
- expect(@variant.volume_price_earning_amount(10, @user)).to be(0)
99
- end
100
- end
101
-
102
- context 'discount_type = dollar' do
103
- before :each do
104
- @variant = create :variant, price: 10
105
- @variant.volume_prices.create! amount: 1, discount_type: 'dollar', range: '(10+)'
106
- @role = create(:role)
107
- @user = create(:user)
108
- end
109
-
110
- it 'uses the variants price when it does not match a range' do
111
- expect(@variant.volume_price(1).to_f).to be(10.00)
112
- end
113
-
114
- it 'uses the variants price when it does not match role with null role' do
115
- @variant.volume_prices.first.update(role_id: @role.id)
116
- expect(@variant.volume_price(10).to_f).to be(10.00)
117
- end
118
-
119
- it 'uses the variants price when it does not match roles' do
120
- other_role = create(:role)
121
- @user.spree_roles << other_role
122
- @variant.volume_prices.first.update(role_id: @role.id)
123
- expect(@variant.volume_price(10, @user).to_f).to be(10.00)
124
- end
125
-
126
- it 'uses the volume price when it does match a range' do
127
- expect(@variant.volume_price(10).to_f).to be(9.00)
128
- end
129
-
130
- it 'uses the volume price when it does match a range and role' do
131
- @user.spree_roles << @role
132
- Spree::Config.volume_pricing_role = @role.name
133
- @variant.volume_prices.first.update(role_id: @role.id)
134
- expect(@variant.volume_price(10, @user).to_f).to be(9.00)
135
- end
136
-
137
- it 'uses the volume price when it does match from a volume price model' do
138
- @variant.volume_price_models << create(:volume_price_model)
139
- @variant.volume_price_models.first.volume_prices.create!(amount: 5, discount_type: 'dollar', range: '(5+)')
140
- expect(@variant.volume_price(6).to_f).to be(5.00)
141
- end
142
-
143
- it 'gives percent of earning without role' do
144
- expect(@variant.volume_price_earning_percent(10)).to be(10)
145
- end
146
-
147
- it 'gives percent of earning if role matches' do
148
- @user.spree_roles << @role
149
- Spree::Config.volume_pricing_role = @role.name
150
- @variant.volume_prices.first.update(role_id: @role.id)
151
- expect(@variant.volume_price_earning_percent(10, @user)).to be(10)
152
- end
153
-
154
- it 'gives zero percent earning if doesnt match' do
155
- expect(@variant.volume_price_earning_percent(1)).to be(0)
156
- end
157
-
158
- it 'gives zero percent earning if role doesnt match with null' do
159
- @variant.volume_prices.first.update(role_id: @role.id)
160
- expect(@variant.volume_price_earning_percent(10)).to be(0)
161
- end
162
-
163
- it 'gives zero percent earning if role doesnt match' do
164
- other_role = create(:role)
165
- @user.spree_roles << other_role
166
- @variant.volume_prices.first.update(role_id: @role.id)
167
- expect(@variant.volume_price_earning_percent(10, @user)).to be(0)
168
- end
169
-
170
- it 'gives amount earning without role' do
171
- expect(@variant.volume_price_earning_amount(10)).to eq(1)
172
- end
173
-
174
- it 'gives amount earning if role matches' do
175
- @user.spree_roles << @role
176
- Spree::Config.volume_pricing_role = @role.name
177
- @variant.volume_prices.first.update(role_id: @role.id)
178
- expect(@variant.volume_price_earning_amount(10, @user)).to eq(1)
179
- end
180
-
181
- it 'gives zero earning amount if doesnt match' do
182
- expect(@variant.volume_price_earning_amount(1)).to eq(0)
183
- end
184
-
185
- it 'gives zero earning amount if role doesnt match with null' do
186
- @variant.volume_prices.first.update(role_id: @role.id)
187
- expect(@variant.volume_price_earning_amount(10)).to be(0)
188
- end
189
-
190
- it 'gives zero earning amount if role doesnt match' do
191
- other_role = create(:role)
192
- @user.spree_roles << other_role
193
- @variant.volume_prices.first.update(role_id: @role.id)
194
- expect(@variant.volume_price_earning_amount(10, @user)).to be(0)
195
- end
196
- end
197
-
198
- context 'discount_type = percent' do
199
- before :each do
200
- @variant = create :variant, price: 10
201
- @variant.volume_prices.create! amount: 0.1, discount_type: 'percent', range: '(10+)'
202
- @role = create(:role)
203
- @user = create(:user)
204
- end
205
-
206
- it 'uses the variants price when it does not match a range' do
207
- expect(@variant.volume_price(1).to_f).to be(10.00)
208
- end
209
-
210
- it 'uses the variants price when it does not match role with null role' do
211
- @variant.volume_prices.first.update(role_id: @role.id)
212
- expect(@variant.volume_price(10).to_f).to be(10.00)
213
- end
214
-
215
- it 'uses the variants price when it does not match roles' do
216
- other_role = create(:role)
217
- @user.spree_roles << other_role
218
- @variant.volume_prices.first.update(role_id: @role.id)
219
- expect(@variant.volume_price(10, @user).to_f).to be(10.00)
220
- end
221
-
222
- it 'uses the volume price when it does match a range' do
223
- expect(@variant.volume_price(10).to_f).to be(9.00)
224
- end
225
-
226
- it 'uses the volume price when it does match a range and role' do
227
- @user.spree_roles << @role
228
- Spree::Config.volume_pricing_role = @role.name
229
- @variant.volume_prices.first.update(role_id: @role.id)
230
- expect(@variant.volume_price(10, @user).to_f).to be(9.00)
231
- end
232
-
233
- it 'gives percent of earning without roles' do
234
- expect(@variant.volume_price_earning_percent(10)).to be(10)
235
- @variant_five = create :variant, price: 10
236
- @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
237
- expect(@variant_five.volume_price_earning_percent(1)).to be(50)
238
- end
239
-
240
- it 'gives amount earning if role matches' do
241
- @user.spree_roles << @role
242
- Spree::Config.volume_pricing_role = @role.name
243
- expect(@variant.volume_price_earning_percent(10)).to be(10)
244
- @variant_five = create :variant, price: 10
245
- @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
246
- @variant_five.volume_prices.first.update(role_id: @role.id)
247
- expect(@variant_five.volume_price_earning_percent(1, @user)).to be(50)
248
- end
249
-
250
- it 'gives zero percent earning if doesnt match' do
251
- expect(@variant.volume_price_earning_percent(1)).to be(0)
252
- end
253
-
254
- it 'gives zero percent earning if role doesnt match with null' do
255
- @variant.volume_prices.first.update(role_id: @role.id)
256
- expect(@variant.volume_price_earning_percent(10)).to be(0)
257
- end
258
-
259
- it 'gives zero percent earning if role doesnt match' do
260
- other_role = create(:role)
261
- @user.spree_roles << other_role
262
- @variant.volume_prices.first.update(role_id: @role.id)
263
- expect(@variant.volume_price_earning_percent(10, @user)).to be(0)
264
- end
265
-
266
- it 'gives amount earning without roles' do
267
- expect(@variant.volume_price_earning_amount(10)).to eq(1)
268
- @variant_five = create :variant, price: 10
269
- @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
270
- expect(@variant_five.volume_price_earning_amount(1)).to eq(5)
271
- end
272
-
273
- it 'gives amount earning if role matches' do
274
- @user.spree_roles << @role
275
- Spree::Config.volume_pricing_role = @role.name
276
- expect(@variant.volume_price_earning_amount(10)).to eq(1)
277
- @variant_five = create :variant, price: 10
278
- @variant_five.volume_prices.create! amount: 0.5, discount_type: 'percent', range: '(1+)'
279
- @variant_five.volume_prices.first.update(role_id: @role.id)
280
- expect(@variant_five.volume_price_earning_amount(1, @user)).to eq(5)
281
- end
282
-
283
- it 'uses the volume price when it does match from a volume price model' do
284
- @variant.volume_price_models << create(:volume_price_model)
285
- @variant.volume_price_models.first.volume_prices.create!(amount: 0.5, discount_type: 'percent', range: '(5+)')
286
- expect(@variant.volume_price(6).to_f).to be(5.00)
287
- end
288
-
289
- it 'gives zero earning amount if doesnt match' do
290
- expect(@variant.volume_price_earning_amount(1)).to eq(0)
291
- end
292
-
293
- it 'gives zero earning amount if role doesnt match with null' do
294
- @variant.volume_prices.first.update(role_id: @role.id)
295
- expect(@variant.volume_price_earning_amount(10)).to be(0)
296
- end
297
-
298
- it 'gives zero earning amount if role doesnt match' do
299
- other_role = create(:role)
300
- @user.spree_roles << other_role
301
- @variant.volume_prices.first.update(role_id: @role.id)
302
- expect(@variant.volume_price_earning_amount(10, @user)).to be(0)
303
- end
304
- end
305
- end
5
+ it { is_expected.to have_many(:model_volume_prices) }
306
6
  end
@@ -1,120 +1,224 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Spree::VolumePrice, type: :model do
2
- it { is_expected.to belong_to(:variant).touch(true) }
3
- it { is_expected.to belong_to(:volume_price_model).touch(true) }
4
- it { is_expected.to belong_to(:spree_role).class_name('Spree::Role').with_foreign_key('role_id') }
4
+ let(:volume_price) do
5
+ described_class.new(variant: Spree::Variant.new, amount: 10, discount_type: 'price')
6
+ end
7
+
8
+ it { is_expected.to belong_to(:variant).touch(true).optional }
9
+ it { is_expected.to belong_to(:volume_price_model).touch(true).optional }
10
+ it { is_expected.to belong_to(:spree_role).class_name('Spree::Role').with_foreign_key('role_id').optional }
5
11
  it { is_expected.to validate_presence_of(:discount_type) }
6
- it { is_expected.to validate_inclusion_of(:discount_type).in_array(%w(price dollar percent)) }
7
12
  it { is_expected.to validate_presence_of(:amount) }
8
13
 
9
- before do
10
- @volume_price = Spree::VolumePrice.new(variant: Spree::Variant.new, amount: 10, discount_type: 'price')
14
+ it do
15
+ expect(subject).to \
16
+ validate_inclusion_of(:discount_type).
17
+ in_array(%w(price dollar percent)).
18
+ with_message('shoulda-matchers test string is not a valid Volume Price Type')
11
19
  end
12
20
 
13
- ['1..2', '(1..2)'].each do |range|
14
- it "does not interepret a Ruby range of #{range} as being opend ended" do
15
- @volume_price.range = range
16
- expect(@volume_price).not_to be_open_ended
21
+ describe '.for_variant' do
22
+ subject { described_class.for_variant(variant, user: user) }
23
+
24
+ let(:user) { nil }
25
+ let(:variant) { create(:variant) }
26
+ let!(:volume_prices) { create_list(:volume_price, 2, variant: variant) }
27
+
28
+ context 'if no user is given' do
29
+ it 'returns all volume prices for given variant that are not related to a specific role' do
30
+ expect(subject).to eq(volume_prices)
31
+ end
17
32
  end
18
- end
19
33
 
20
- ['50+', '(50+)'].each do |range|
21
- it "properly interpret an open ended range of #{range}" do
22
- @volume_price.range = range
23
- expect(@volume_price).to be_open_ended
34
+ context 'if user is given' do
35
+ let(:role) do
36
+ create(:role, name: 'merchant')
37
+ end
38
+
39
+ let(:user) do
40
+ create(:user)
41
+ end
42
+
43
+ let!(:volume_prices_for_user_role) do
44
+ create_list(:volume_price, 2, variant: variant, role_id: role.id)
45
+ end
46
+
47
+ before do
48
+ stub_spree_preferences(volume_pricing_role: role.name)
49
+ end
50
+
51
+ context 'whose role matches' do
52
+ before do
53
+ user.spree_roles = [role]
54
+ end
55
+
56
+ it 'returns role specific volume prices' do
57
+ expect(subject).to include(*volume_prices_for_user_role)
58
+ end
59
+
60
+ it 'returns non-role specific volume prices' do
61
+ expect(subject).to include(*volume_prices)
62
+ end
63
+ end
64
+
65
+ context 'whose role does not match' do
66
+ before do
67
+ user.spree_roles = []
68
+ end
69
+
70
+ it 'does not include role specific volume prices' do
71
+ expect(subject).not_to include(*volume_prices_for_user_role)
72
+ end
73
+
74
+ it 'returns non-role specific volume prices' do
75
+ expect(subject).to include(*volume_prices)
76
+ end
77
+ end
78
+ end
79
+
80
+ context 'if volume prices are not related to the variant but to a volume price model' do
81
+ let(:volume_price_model) do
82
+ create(:volume_price_model)
83
+ end
84
+
85
+ let!(:volume_prices_from_model) do
86
+ create_list(:volume_price, 2, volume_price_model: volume_price_model, variant: nil)
87
+ end
88
+
89
+ context 'and these volume prices are also related to the given variant' do
90
+ let(:variant) do
91
+ create(:variant, volume_price_models: [volume_price_model])
92
+ end
93
+
94
+ it 'includes these volume prices' do
95
+ expect(subject).to include(*volume_prices_from_model)
96
+ end
97
+ end
98
+
99
+ context 'and these volume prices are not related to the given variant' do
100
+ it 'does not include these volume prices' do
101
+ expect(subject).not_to include(*volume_prices_from_model)
102
+ end
103
+ end
24
104
  end
25
105
  end
26
106
 
27
107
  describe 'valid range format' do
28
108
  it 'requires the presence of a variant' do
29
- @volume_price.variant = nil
30
- expect(@volume_price).not_to be_valid
109
+ volume_price.variant = nil
110
+ expect(volume_price).not_to be_valid
31
111
  end
32
112
 
33
113
  it 'consider a range of (1..2) to be valid' do
34
- @volume_price.range = '(1..2)'
35
- expect(@volume_price).to be_valid
114
+ volume_price.range = '(1..2)'
115
+ expect(volume_price).to be_valid
36
116
  end
37
117
 
38
118
  it 'consider a range of (1...2) to be valid' do
39
- @volume_price.range = '(1...2)'
40
- expect(@volume_price).to be_valid
119
+ volume_price.range = '(1...2)'
120
+ expect(volume_price).to be_valid
41
121
  end
42
122
 
43
123
  it 'consider a range of 1..2 to be valid' do
44
- @volume_price.range = '1..2'
45
- expect(@volume_price).to be_valid
124
+ volume_price.range = '1..2'
125
+ expect(volume_price).to be_valid
46
126
  end
47
127
 
48
128
  it 'consider a range of 1...2 to be valid' do
49
- @volume_price.range = '1...2'
50
- expect(@volume_price).to be_valid
129
+ volume_price.range = '1...2'
130
+ expect(volume_price).to be_valid
51
131
  end
52
132
 
53
133
  it 'consider a range of (10+) to be valid' do
54
- @volume_price.range = '(10+)'
55
- expect(@volume_price).to be_valid
134
+ volume_price.range = '(10+)'
135
+ expect(volume_price).to be_valid
56
136
  end
57
137
 
58
138
  it 'consider a range of 10+ to be valid' do
59
- @volume_price.range = '10+'
60
- expect(@volume_price).to be_valid
139
+ volume_price.range = '10+'
140
+ expect(volume_price).to be_valid
61
141
  end
62
142
 
63
143
  it 'does not consider a range of 1-2 to valid' do
64
- @volume_price.range = '1-2'
65
- expect(@volume_price).not_to be_valid
144
+ volume_price.range = '1-2'
145
+ expect(volume_price).not_to be_valid
66
146
  end
67
147
 
68
148
  it 'does not consider a range of 1 to valid' do
69
- @volume_price.range = '1'
70
- expect(@volume_price).not_to be_valid
149
+ volume_price.range = '1'
150
+ expect(volume_price).not_to be_valid
71
151
  end
72
152
 
73
153
  it 'does not consider a range of foo to valid' do
74
- @volume_price.range = 'foo'
75
- expect(@volume_price).not_to be_valid
154
+ volume_price.range = 'foo'
155
+ expect(volume_price).not_to be_valid
156
+ end
157
+ end
158
+
159
+ describe 'display_range' do
160
+ subject(:display_range) { volume_price.display_range }
161
+
162
+ let(:volume_price) { described_class.new(range: range) }
163
+
164
+ context 'with parens' do
165
+ let(:range) { '(48+)' }
166
+
167
+ it { is_expected.to eq('48+') }
168
+ end
169
+
170
+ context 'with range dots' do
171
+ let(:range) { '1..3' }
172
+
173
+ it { is_expected.to eq('1-3') }
174
+ end
175
+
176
+ context 'with range dots and parens' do
177
+ let(:range) { '(1..3)' }
178
+
179
+ it { is_expected.to eq('1-3') }
76
180
  end
77
181
  end
78
182
 
79
183
  describe 'include?' do
80
184
  ['10..20', '(10..20)'].each do |range|
81
185
  it "does not match a quantity that fails to fall within the specified range of #{range}" do
82
- @volume_price.range = range
83
- expect(@volume_price).not_to include(21)
186
+ volume_price.range = range
187
+ expect(volume_price).not_to include(21)
84
188
  end
85
189
 
86
190
  it "matches a quantity that is within the specified range of #{range}" do
87
- @volume_price.range = range
88
- expect(@volume_price).to include(12)
191
+ volume_price.range = range
192
+ expect(volume_price).to include(12)
89
193
  end
90
194
 
91
195
  it 'matches the upper bound of ranges that include the upper bound' do
92
- @volume_price.range = range
93
- expect(@volume_price).to include(20)
196
+ volume_price.range = range
197
+ expect(volume_price).to include(20)
94
198
  end
95
199
  end
96
200
 
97
201
  ['10...20', '(10...20)'].each do |range|
98
202
  it 'does not match the upper bound for ranges that exclude the upper bound' do
99
- @volume_price.range = range
100
- expect(@volume_price).not_to include(20)
203
+ volume_price.range = range
204
+ expect(volume_price).not_to include(20)
101
205
  end
102
206
  end
103
207
 
104
208
  ['50+', '(50+)'].each do |range|
105
209
  it "matches a quantity that exceeds the value of an open ended range of #{range}" do
106
- @volume_price.range = range
107
- expect(@volume_price).to include(51)
210
+ volume_price.range = range
211
+ expect(volume_price).to include(51)
108
212
  end
109
213
 
110
214
  it "matches a quantity that equals the value of an open ended range of #{range}" do
111
- @volume_price.range = range
112
- expect(@volume_price).to include(50)
215
+ volume_price.range = range
216
+ expect(volume_price).to include(50)
113
217
  end
114
218
 
115
219
  it "does not match a quantity that is less then the value of an open ended range of #{range}" do
116
- @volume_price.range = range
117
- expect(@volume_price).not_to include(40)
220
+ volume_price.range = range
221
+ expect(volume_price).not_to include(40)
118
222
  end
119
223
  end
120
224
  end