solidus_volume_pricing 1.2.0 → 2.0.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.git-blame-ignore-revs +3 -0
  3. data/.github/workflows/lint.yml +25 -0
  4. data/.github/workflows/test.yml +59 -0
  5. data/.rubocop.yml +0 -5
  6. data/Gemfile +21 -23
  7. data/Guardfile +8 -8
  8. data/README.md +1 -1
  9. data/Rakefile +3 -3
  10. data/app/models/solidus_volume_pricing/pricer.rb +9 -9
  11. data/app/models/solidus_volume_pricing/pricing_options.rb +2 -2
  12. data/app/models/spree/volume_price.rb +8 -8
  13. data/app/patches/helpers/solidus_volume_pricing/spree_base_helper_patch.rb +29 -0
  14. data/app/patches/models/solidus_volume_pricing/spree_line_item_patch.rb +18 -0
  15. data/app/patches/models/solidus_volume_pricing/spree_variant_patch.rb +21 -0
  16. data/bin/rails-engine +6 -6
  17. data/bin/rails-sandbox +4 -4
  18. data/config/routes.rb +1 -1
  19. data/db/migrate/20150603143015_create_spree_volume_price_models.rb +2 -2
  20. data/lib/generators/solidus_volume_pricing/install/install_generator.rb +4 -4
  21. data/lib/patches/backend/controllers/solidus_volume_pricing/spree_admin_variants_controller_patch.rb +38 -0
  22. data/lib/solidus_volume_pricing/engine.rb +22 -11
  23. data/lib/solidus_volume_pricing/range_from_string.rb +4 -4
  24. data/lib/solidus_volume_pricing/testing_support/factories.rb +5 -5
  25. data/lib/solidus_volume_pricing/version.rb +1 -1
  26. data/lib/solidus_volume_pricing.rb +9 -9
  27. data/solidus_volume_pricing.gemspec +20 -21
  28. metadata +41 -63
  29. data/.circleci/config.yml +0 -73
  30. data/.rubocop_todo.yml +0 -68
  31. data/app/decorators/controllers/solidus_volume_pricing/spree/admin/variants_controller_decorator.rb +0 -42
  32. data/app/decorators/helpers/solidus_volume_pricing/spree/base_helper_decorator.rb +0 -31
  33. data/app/decorators/models/solidus_volume_pricing/spree/line_item_decorator.rb +0 -18
  34. data/app/decorators/models/solidus_volume_pricing/spree/variant_decorator.rb +0 -23
  35. data/spec/controllers/spree/admin/variants_controller_spec.rb +0 -30
  36. data/spec/features/manage_volume_price_models_feature_spec.rb +0 -24
  37. data/spec/features/manage_volume_prices_feature_spec.rb +0 -33
  38. data/spec/helpers/base_helper_spec.rb +0 -24
  39. data/spec/lib/solidus_volume_pricing/range_from_string_spec.rb +0 -61
  40. data/spec/models/solidus_volume_pricing/pricer_spec.rb +0 -669
  41. data/spec/models/solidus_volume_pricing/pricing_options_spec.rb +0 -57
  42. data/spec/models/spree/line_item_spec.rb +0 -36
  43. data/spec/models/spree/order_spec.rb +0 -51
  44. data/spec/models/spree/variant_spec.rb +0 -6
  45. data/spec/models/spree/volume_price_spec.rb +0 -216
  46. data/spec/spec_helper.rb +0 -32
  47. data/spec/support/shoulda.rb +0 -11
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
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
-
9
- before do
10
- variant.volume_prices.create! amount: 9, discount_type: 'price', range: '(2+)'
11
- order.contents.add(variant, 1)
12
- end
13
-
14
- it 'updates the line item price when the quantity changes to match a range and has no role' do
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)
18
- end
19
-
20
- it 'updates the line item price when the quantity changes to match a range and role matches' do
21
- order.user.spree_roles << role
22
- expect(order.user.has_spree_role?(role.name.to_sym)).to be(true)
23
- variant.volume_prices.first.update(role_id: role.id)
24
- expect(line_item.price.to_f).to be(10.00)
25
- order.contents.add(variant, 1)
26
- expect(order.line_items.first.price.to_f).to be(9.00)
27
- end
28
-
29
- it 'does not update the line item price when the variant role and order role don`t match' do
30
- expect(order.user.has_spree_role?(role.name.to_sym)).to be(false)
31
- variant.volume_prices.first.update(role_id: role.id)
32
- expect(line_item.price.to_f).to be(10.00)
33
- order.contents.add(variant, 1)
34
- expect(order.line_items.first.price.to_f).to be(10.00)
35
- end
36
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Spree::Order, type: :model do
4
- before do
5
- @order = create(:order)
6
- @variant = create(:variant, price: 10)
7
-
8
- @variant_with_prices = create(:variant, price: 10)
9
- @variant_with_prices.volume_prices << create(:volume_price, range: '1..5', amount: 9, position: 2)
10
- @variant_with_prices.volume_prices << create(:volume_price, range: '(5..9)', amount: 8, position: 1)
11
- end
12
-
13
- context 'add_variant' do
14
- it 'uses the variant price if there are no volume prices' do
15
- @order.contents.add(@variant)
16
- expect(@order.line_items.first.price).to eq(10)
17
- end
18
-
19
- it 'uses the volume price if quantity falls within a quantity range of a volume price' do
20
- @variant.volume_prices << create(:volume_price, range: '(5..10)', amount: 9)
21
- @order.contents.add(@variant_with_prices, 7)
22
- expect(@order.line_items.first.price).to eq(8)
23
- end
24
-
25
- it 'uses the variant price if the quantity fails to satisfy any of the volume price ranges' do
26
- @order.contents.add(@variant, 10)
27
- expect(@order.line_items.first.price).to eq(10)
28
- end
29
-
30
- it 'uses the first matching volume price in the event of more then one matching volume prices' do
31
- @order.contents.add(@variant_with_prices, 5)
32
- expect(@order.line_items.first.price).to eq(8)
33
- end
34
-
35
- it 'uses the master variant volume price in case variant has no volume price if config is true' do
36
- stub_spree_preferences(use_master_variant_volume_pricing: true)
37
- @master = @variant.product.master
38
- @master.volume_prices << create(:volume_price, range: '(1..5)', amount: 9, position: 2)
39
- @order.contents.add(@variant, 5)
40
- expect(@order.line_items.first.price).to eq(9)
41
- end
42
-
43
- it 'doesnt use the master variant volume price in case variant has no volume price if config is false' do
44
- stub_spree_preferences(use_master_variant_volume_pricing: false)
45
- @master = @variant.product.master
46
- @master.volume_prices << create(:volume_price, range: '(1..5)', amount: 9, position: 2)
47
- @order.contents.add(@variant, 5)
48
- expect(@order.line_items.first.price).to eq(10)
49
- end
50
- end
51
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Spree::Variant, type: :model do
4
- it { is_expected.to have_many(:volume_prices) }
5
- it { is_expected.to have_many(:model_volume_prices) }
6
- end
@@ -1,216 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Spree::VolumePrice, type: :model do
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 }
11
- it { is_expected.to validate_presence_of(:discount_type) }
12
- it { is_expected.to validate_presence_of(:amount) }
13
-
14
- it { is_expected.to validate_inclusion_of(:discount_type).in_array(%w[price dollar percent]) }
15
-
16
- describe '.for_variant' do
17
- subject { described_class.for_variant(variant, user: user) }
18
-
19
- let(:user) { nil }
20
- let(:variant) { create(:variant) }
21
- let!(:volume_prices) { create_list(:volume_price, 2, variant: variant) }
22
-
23
- context 'if no user is given' do
24
- it 'returns all volume prices for given variant that are not related to a specific role' do
25
- expect(subject).to eq(volume_prices)
26
- end
27
- end
28
-
29
- context 'if user is given' do
30
- let(:role) do
31
- create(:role, name: 'merchant')
32
- end
33
-
34
- let(:user) do
35
- create(:user)
36
- end
37
-
38
- let!(:volume_prices_for_user_role) do
39
- create_list(:volume_price, 2, variant: variant, role_id: role.id)
40
- end
41
-
42
- context 'whose role matches' do
43
- before do
44
- user.spree_roles = [role]
45
- end
46
-
47
- it 'returns role specific volume prices' do
48
- expect(subject).to include(*volume_prices_for_user_role)
49
- end
50
-
51
- it 'returns non-role specific volume prices' do
52
- expect(subject).to include(*volume_prices)
53
- end
54
- end
55
-
56
- context 'whose role does not match' do
57
- before do
58
- user.spree_roles = []
59
- end
60
-
61
- it 'does not include role specific volume prices' do
62
- expect(subject).not_to include(*volume_prices_for_user_role)
63
- end
64
-
65
- it 'returns non-role specific volume prices' do
66
- expect(subject).to include(*volume_prices)
67
- end
68
- end
69
- end
70
-
71
- context 'if volume prices are not related to the variant but to a volume price model' do
72
- let(:volume_price_model) do
73
- create(:volume_price_model)
74
- end
75
-
76
- let!(:volume_prices_from_model) do
77
- create_list(:volume_price, 2, volume_price_model: volume_price_model, variant: nil)
78
- end
79
-
80
- context 'and these volume prices are also related to the given variant' do
81
- let(:variant) do
82
- create(:variant, volume_price_models: [volume_price_model])
83
- end
84
-
85
- it 'includes these volume prices' do
86
- expect(subject).to include(*volume_prices_from_model)
87
- end
88
- end
89
-
90
- context 'and these volume prices are not related to the given variant' do
91
- it 'does not include these volume prices' do
92
- expect(subject).not_to include(*volume_prices_from_model)
93
- end
94
- end
95
- end
96
- end
97
-
98
- describe 'valid range format' do
99
- it 'requires the presence of a variant' do
100
- volume_price.variant = nil
101
- expect(volume_price).not_to be_valid
102
- end
103
-
104
- it 'consider a range of (1..2) to be valid' do
105
- volume_price.range = '(1..2)'
106
- expect(volume_price).to be_valid
107
- end
108
-
109
- it 'consider a range of (1...2) to be valid' do
110
- volume_price.range = '(1...2)'
111
- expect(volume_price).to be_valid
112
- end
113
-
114
- it 'consider a range of 1..2 to be valid' do
115
- volume_price.range = '1..2'
116
- expect(volume_price).to be_valid
117
- end
118
-
119
- it 'consider a range of 1...2 to be valid' do
120
- volume_price.range = '1...2'
121
- expect(volume_price).to be_valid
122
- end
123
-
124
- it 'consider a range of (10+) to be valid' do
125
- volume_price.range = '(10+)'
126
- expect(volume_price).to be_valid
127
- end
128
-
129
- it 'consider a range of 10+ to be valid' do
130
- volume_price.range = '10+'
131
- expect(volume_price).to be_valid
132
- end
133
-
134
- it 'does not consider a range of 1-2 to valid' do
135
- volume_price.range = '1-2'
136
- expect(volume_price).not_to be_valid
137
- end
138
-
139
- it 'does not consider a range of 1 to valid' do
140
- volume_price.range = '1'
141
- expect(volume_price).not_to be_valid
142
- end
143
-
144
- it 'does not consider a range of foo to valid' do
145
- volume_price.range = 'foo'
146
- expect(volume_price).not_to be_valid
147
- end
148
- end
149
-
150
- describe 'display_range' do
151
- subject(:display_range) { volume_price.display_range }
152
-
153
- let(:volume_price) { described_class.new(range: range) }
154
-
155
- context 'with parens' do
156
- let(:range) { '(48+)' }
157
-
158
- it { is_expected.to eq('48+') }
159
- end
160
-
161
- context 'with range dots' do
162
- let(:range) { '1..3' }
163
-
164
- it { is_expected.to eq('1-3') }
165
- end
166
-
167
- context 'with range dots and parens' do
168
- let(:range) { '(1..3)' }
169
-
170
- it { is_expected.to eq('1-3') }
171
- end
172
- end
173
-
174
- describe 'include?' do
175
- ['10..20', '(10..20)'].each do |range|
176
- it "does not match a quantity that fails to fall within the specified range of #{range}" do
177
- volume_price.range = range
178
- expect(volume_price).not_to include(21)
179
- end
180
-
181
- it "matches a quantity that is within the specified range of #{range}" do
182
- volume_price.range = range
183
- expect(volume_price).to include(12)
184
- end
185
-
186
- it 'matches the upper bound of ranges that include the upper bound' do
187
- volume_price.range = range
188
- expect(volume_price).to include(20)
189
- end
190
- end
191
-
192
- ['10...20', '(10...20)'].each do |range|
193
- it 'does not match the upper bound for ranges that exclude the upper bound' do
194
- volume_price.range = range
195
- expect(volume_price).not_to include(20)
196
- end
197
- end
198
-
199
- ['50+', '(50+)'].each do |range|
200
- it "matches a quantity that exceeds the value of an open ended range of #{range}" do
201
- volume_price.range = range
202
- expect(volume_price).to include(51)
203
- end
204
-
205
- it "matches a quantity that equals the value of an open ended range of #{range}" do
206
- volume_price.range = range
207
- expect(volume_price).to include(50)
208
- end
209
-
210
- it "does not match a quantity that is less then the value of an open ended range of #{range}" do
211
- volume_price.range = range
212
- expect(volume_price).not_to include(40)
213
- end
214
- end
215
- end
216
- end
data/spec/spec_helper.rb DELETED
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Configure Rails Environment
4
- ENV['RAILS_ENV'] = 'test'
5
-
6
- # Run Coverage report
7
- require 'solidus_dev_support/rspec/coverage'
8
-
9
- # Create the dummy app if it's still missing.
10
- dummy_env = "#{__dir__}/dummy/config/environment.rb"
11
- system 'bin/rake extension:test_app' unless File.exist? dummy_env
12
- require dummy_env
13
-
14
- # Requires factories and other useful helpers defined in spree_core.
15
- require 'solidus_dev_support/rspec/feature_helper'
16
-
17
- # Requires supporting ruby files with custom matchers and macros, etc,
18
- # in spec/support/ and its subdirectories.
19
- Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
20
-
21
- # Requires factories defined in Solidus core and this extension.
22
- # See: lib/solidus_volume_pricing/testing_support/factories.rb
23
- SolidusDevSupport::TestingSupport::Factories.load_for(SolidusVolumePricing::Engine)
24
-
25
- RSpec.configure do |config|
26
- config.infer_spec_type_from_file_location!
27
- config.use_transactional_fixtures = false
28
-
29
- if Spree.solidus_gem_version < Gem::Version.new('2.11')
30
- config.extend Spree::TestingSupport::AuthorizationHelpers::Request, type: :system
31
- end
32
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'shoulda-matchers'
4
-
5
- # From: https://github.com/thoughtbot/shoulda-matchers/issues/384
6
- Shoulda::Matchers.configure do |config|
7
- config.integrate do |with|
8
- with.test_framework :rspec
9
- with.library :rails
10
- end
11
- end