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.
- checksums.yaml +4 -4
- data/.git-blame-ignore-revs +3 -0
- data/.github/workflows/lint.yml +25 -0
- data/.github/workflows/test.yml +59 -0
- data/.rubocop.yml +0 -5
- data/Gemfile +21 -23
- data/Guardfile +8 -8
- data/README.md +1 -1
- data/Rakefile +3 -3
- data/app/models/solidus_volume_pricing/pricer.rb +9 -9
- data/app/models/solidus_volume_pricing/pricing_options.rb +2 -2
- data/app/models/spree/volume_price.rb +8 -8
- data/app/patches/helpers/solidus_volume_pricing/spree_base_helper_patch.rb +29 -0
- data/app/patches/models/solidus_volume_pricing/spree_line_item_patch.rb +18 -0
- data/app/patches/models/solidus_volume_pricing/spree_variant_patch.rb +21 -0
- data/bin/rails-engine +6 -6
- data/bin/rails-sandbox +4 -4
- data/config/routes.rb +1 -1
- data/db/migrate/20150603143015_create_spree_volume_price_models.rb +2 -2
- data/lib/generators/solidus_volume_pricing/install/install_generator.rb +4 -4
- data/lib/patches/backend/controllers/solidus_volume_pricing/spree_admin_variants_controller_patch.rb +38 -0
- data/lib/solidus_volume_pricing/engine.rb +22 -11
- data/lib/solidus_volume_pricing/range_from_string.rb +4 -4
- data/lib/solidus_volume_pricing/testing_support/factories.rb +5 -5
- data/lib/solidus_volume_pricing/version.rb +1 -1
- data/lib/solidus_volume_pricing.rb +9 -9
- data/solidus_volume_pricing.gemspec +20 -21
- metadata +41 -63
- data/.circleci/config.yml +0 -73
- data/.rubocop_todo.yml +0 -68
- data/app/decorators/controllers/solidus_volume_pricing/spree/admin/variants_controller_decorator.rb +0 -42
- data/app/decorators/helpers/solidus_volume_pricing/spree/base_helper_decorator.rb +0 -31
- data/app/decorators/models/solidus_volume_pricing/spree/line_item_decorator.rb +0 -18
- data/app/decorators/models/solidus_volume_pricing/spree/variant_decorator.rb +0 -23
- data/spec/controllers/spree/admin/variants_controller_spec.rb +0 -30
- data/spec/features/manage_volume_price_models_feature_spec.rb +0 -24
- data/spec/features/manage_volume_prices_feature_spec.rb +0 -33
- data/spec/helpers/base_helper_spec.rb +0 -24
- data/spec/lib/solidus_volume_pricing/range_from_string_spec.rb +0 -61
- data/spec/models/solidus_volume_pricing/pricer_spec.rb +0 -669
- data/spec/models/solidus_volume_pricing/pricing_options_spec.rb +0 -57
- data/spec/models/spree/line_item_spec.rb +0 -36
- data/spec/models/spree/order_spec.rb +0 -51
- data/spec/models/spree/variant_spec.rb +0 -6
- data/spec/models/spree/volume_price_spec.rb +0 -216
- data/spec/spec_helper.rb +0 -32
- 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,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
|
data/spec/support/shoulda.rb
DELETED
|
@@ -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
|