spree_multi_vendor 2.1.0 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c44adfbeea75e7b5d36a5282b3f73e82a50914e2afdcb3e5d5100f0f1fb7e2f
4
- data.tar.gz: e0fc1a00cc1c075944a888257004841199da7a62f85065dc087b0546a9eadf16
3
+ metadata.gz: b4a9ea707b2e1f2dd0c5ac2b71c82c1334ca991cb0e80cd26f35cc6e95234d06
4
+ data.tar.gz: 777150a6db369707f55927a5e5066e93de22070b190539a07de79b616e028182
5
5
  SHA512:
6
- metadata.gz: 6862e52f1a430fcbe23b6fef685c2c12d30245ce0199d993caae87c7a71dd9278ed73c29d611d325266c9dab107922a5921783f57bf8789c752f81b1f58c78e9
7
- data.tar.gz: 310a440feb55b56bc73ec09656f6167a7cbdc2fce296e5793379611ebc066749dc7853721140dc0963498f6dc7eb3116e259f5ca64eeb4c33320158870f3cc02
6
+ metadata.gz: 7b084940266d45faf272d01d3ef2e4c638476b51d736f2232879427218d0c04345c1d0494f3c1eaabbd37c8e50c68712f1e87ee1fc837c12a318451f2554fc56
7
+ data.tar.gz: 3a52b9945c79a47af00d3e99965176cf89cce11adce7c5cd89573ec685b41cc0d08242d4f302d5c3f07ec1c4a50c7463e53cb9e3eb5a25eb7d62c8c36cb04af4
@@ -0,0 +1,17 @@
1
+ module SpreeMultiVendor::Spree::Api::BaseControllerDecorator
2
+ Spree::Api::BaseController.include(Spree::Api::VendorHelper)
3
+
4
+ def self.prepended(base)
5
+ base.helper_method :current_spree_vendor
6
+ end
7
+
8
+ private
9
+
10
+ def set_vendor_id(resource_name)
11
+ return unless current_spree_vendor
12
+
13
+ params[resource_name][:vendor_id] = current_spree_vendor.id
14
+ end
15
+ end
16
+
17
+ ::Spree::Api::BaseController.prepend SpreeMultiVendor::Spree::Api::BaseControllerDecorator
@@ -0,0 +1,9 @@
1
+ module SpreeMultiVendor::Spree::Api::V1::ProductsControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action only: [:create, :update] do
4
+ set_vendor_id(:product)
5
+ end
6
+ end
7
+ end
8
+
9
+ Spree::Api::V1::ProductsController.prepend SpreeMultiVendor::Spree::Api::V1::ProductsControllerDecorator
@@ -0,0 +1,13 @@
1
+ module SpreeMultiVendor::Spree::Api::V1::UsersControllerDecorator
2
+ private
3
+
4
+ def user_params
5
+ params.require(:user).permit(permitted_user_attributes |
6
+ [spree_role_ids: [],
7
+ vendor_ids: [],
8
+ ship_address_attributes: permitted_address_attributes,
9
+ bill_address_attributes: permitted_address_attributes])
10
+ end
11
+ end
12
+
13
+ Spree::Api::V1::UsersController.prepend SpreeMultiVendor::Spree::Api::V1::UsersControllerDecorator
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ module Api
3
+ module VendorHelper
4
+ def current_spree_vendor
5
+ if current_api_user.vendors.any? && (!current_api_user.respond_to?(:has_spree_role?) || !current_api_user.has_spree_role?(:admin))
6
+ current_api_user.vendors.first
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -6,6 +6,8 @@ module SpreeMultiVendor
6
6
  base::ATTRIBUTES.push(:vendor_attributes)
7
7
 
8
8
  base.mattr_reader *base::ATTRIBUTES
9
+
10
+ base.user_attributes << :vendor_ids
9
11
  end
10
12
 
11
13
  @@vendor_attributes = [:id, :name, :slug, :state, :about_us, :contact_us]
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class VendorUser < Spree::Base
3
3
  belongs_to :vendor, class_name: 'Spree::Vendor', required: Spree.version.to_f >= 3.5
4
- belongs_to :user, class_name: Spree.user_class.name, required: Spree.version.to_f >= 3.5
4
+ belongs_to :user, class_name: Spree.user_class.name, required: Spree.version.to_f >= 3.5, touch: true
5
5
 
6
6
  validates :vendor_id, uniqueness: { scope: :user_id }
7
7
 
@@ -22,7 +22,9 @@ module SpreeMultiVendor::Spree::OrderDecorator
22
22
  end
23
23
 
24
24
  def vendor_subtotal(vendor)
25
- vendor_line_items(vendor).sum(&:total)
25
+ vendor_pre_tax_item_amount(vendor) +
26
+ vendor_pre_tax_ship_amount(vendor) +
27
+ vendor_additional_tax_total(vendor)
26
28
  end
27
29
 
28
30
  def vendor_promo_total(vendor)
@@ -102,4 +104,4 @@ module SpreeMultiVendor::Spree::OrderDecorator
102
104
  end
103
105
  end
104
106
 
105
- Spree::Order.prepend SpreeMultiVendor::Spree::OrderDecorator
107
+ Spree::Order.prepend SpreeMultiVendor::Spree::OrderDecorator unless Spree::Order.included_modules.include?(SpreeMultiVendor::Spree::OrderDecorator)
@@ -2,7 +2,7 @@ Deface::Override.new(
2
2
  virtual_path: 'spree/admin/shared/_main_menu',
3
3
  name: 'Display configuration tab for vendors',
4
4
  replace: 'erb[silent]:contains("current_store")',
5
- text: '<% if can?(:admin, current_store) || current_spree_user.vendors.any? %>'
5
+ text: '<% if can?(:admin, current_store) || current_spree_user&.vendors&.any? %>'
6
6
  )
7
7
  Deface::Override.new(
8
8
  virtual_path: 'spree/admin/shared/_main_menu',
@@ -4,6 +4,8 @@ module Spree
4
4
  class VendorOrderTotalsSerializer < BaseSerializer
5
5
  set_type :vendor_totals
6
6
 
7
+ cache_options store: nil
8
+
7
9
  attributes :name, :subtotal, :ship_total, :total, :display_subtotal,
8
10
  :display_ship_total, :display_total, :promo_total,
9
11
  :display_promo_total, :included_tax_total,
@@ -6,5 +6,7 @@ module Spree
6
6
 
7
7
  @@vendor_attributes = [:name, :about_us, :contact_us, :notification_email]
8
8
  @@vendor_attributes << :image if Spree.version.to_f >= 3.6
9
+
10
+ @@product_attributes << :vendor_id if SpreeMultiVendor::Config[:vendorized_models].include?('product')
9
11
  end
10
12
  end
@@ -1,5 +1,5 @@
1
1
  module SpreeMultiVendor
2
- VERSION = '2.1.0'
2
+ VERSION = '2.2.0'
3
3
 
4
4
  module_function
5
5
 
@@ -34,6 +34,20 @@ describe Spree::Order do
34
34
  expect(v.commissions.sum(:amount)).to eq(commission_ammount)
35
35
  end
36
36
  end
37
+
38
+ it 'sends mails only once per vendor' do
39
+ mail_double_1 = double(:mail_double_1)
40
+ mail_double_2 = double(:mail_double_1)
41
+
42
+ expect(Spree::VendorMailer).to receive(:vendor_notification_email)
43
+ .with(be_an(Integer), vendor.id) { mail_double_1 }
44
+ expect(mail_double_1).to receive(:deliver_later)
45
+ expect(Spree::VendorMailer).to receive(:vendor_notification_email)
46
+ .with(be_an(Integer), vendor_2.id) { mail_double_2 }
47
+ expect(mail_double_2).to receive(:deliver_later)
48
+
49
+ order.next!
50
+ end
37
51
  end
38
52
 
39
53
  context 'vendor methods' do
@@ -57,11 +71,11 @@ describe Spree::Order do
57
71
  end
58
72
 
59
73
  describe '#vendor_subtotal' do
60
- it { expect(order.vendor_subtotal(vendor)).to eq(270) }
74
+ it { expect(order.vendor_subtotal(vendor)).to eq(320) }
61
75
  end
62
76
 
63
77
  describe '#display_subtotal' do
64
- it { expect(order.display_vendor_subtotal(vendor).to_s).to eq('$270.00') }
78
+ it { expect(order.display_vendor_subtotal(vendor).to_s).to eq('$320.00') }
65
79
  end
66
80
 
67
81
  describe '#vendor_pre_tax_item_amount' do
@@ -0,0 +1,221 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe 'API V1 Products Spec', type: :request do
5
+ let(:vendor) { create(:vendor, state: :active) }
6
+ let(:other_vendor) { create(:vendor) }
7
+ let(:shipping_category) { create(:shipping_category) }
8
+ let(:selected_product) { product_without_vendor }
9
+ let(:params) { {} }
10
+
11
+ let!(:product_without_vendor) { create(:product) }
12
+ let!(:product_with_vendor_vendor) { create(:product, vendor: vendor) }
13
+ let!(:product_with_other_vendor) { create(:product, vendor: other_vendor) }
14
+
15
+ before { stub_authentication! }
16
+
17
+ describe 'products#index' do
18
+ before { get '/api/v1/products', params: params }
19
+
20
+ context 'as a regular user' do
21
+ it 'gets a list of all products' do
22
+ expect(response.status).to eq(200)
23
+ expect(json_response[:products].size).to eq(3)
24
+ end
25
+ end
26
+
27
+ context 'as an admin' do
28
+ sign_in_as_admin!
29
+
30
+ it 'gets a list of all products' do
31
+ expect(response.status).to eq(200)
32
+ expect(json_response[:products].size).to eq(3)
33
+ end
34
+ end
35
+
36
+ context 'as a vendor' do
37
+ let!(:current_api_user) do
38
+ user = create(:user, vendors: [vendor])
39
+ user
40
+ end
41
+
42
+ it 'gets a list of products assigned to that vendor' do
43
+ expect(response.status).to eq(200)
44
+ expect(json_response[:products].size).to eq(1)
45
+ expect(json_response[:products][0][:id]).to eq(vendor.products.first.id)
46
+ end
47
+ end
48
+ end
49
+
50
+ describe 'products#show' do
51
+ before { get "/api/v1/products/#{selected_product.id}" }
52
+
53
+ it 'gets a product' do
54
+ expect(response.status).to eq(200)
55
+ end
56
+
57
+ context 'as a vendor' do
58
+ let!(:current_api_user) do
59
+ user = create(:user, vendors: [vendor])
60
+ user
61
+ end
62
+
63
+ describe 'cannot view product of another vendor' do
64
+ let(:selected_product) { product_with_other_vendor }
65
+
66
+ it do
67
+ expect(response.status).to eq(404)
68
+ end
69
+ end
70
+
71
+ describe 'can view product assigned to that vendor' do
72
+ let(:selected_product) { product_with_vendor_vendor }
73
+
74
+ it do
75
+ expect(response.status).to eq(200)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ describe 'products#create' do
82
+ let(:params) do
83
+ {
84
+ product: {
85
+ name: 'Product',
86
+ shipping_category_id: shipping_category.id,
87
+ price: 12.34
88
+ }
89
+ }
90
+ end
91
+
92
+ before { post '/api/v1/products', params: params }
93
+
94
+ context 'as regular user' do
95
+ it 'cannot create a new product' do
96
+ expect(response.status).to eq(401)
97
+ end
98
+ end
99
+
100
+ context 'as an admin' do
101
+ sign_in_as_admin!
102
+
103
+ it 'can create a new product' do
104
+ expect(response.status).to eq(201)
105
+ expect(json_response['name']).to eq(params[:product][:name])
106
+ expect(json_response['price']).to eq(params[:product][:price].to_s)
107
+ expect(json_response['shipping_category_id']).to eq(params[:product][:shipping_category_id])
108
+ end
109
+ end
110
+
111
+ context 'as a vendor' do
112
+ let!(:current_api_user) do
113
+ user = create(:user, vendors: [vendor])
114
+ user
115
+ end
116
+
117
+ it 'can create a new product assigned to vendor' do
118
+ expect(response.status).to eq(201)
119
+ product = Spree::Product.find(json_response[:id])
120
+ expect(product.vendor).to eq(vendor)
121
+ end
122
+ end
123
+ end
124
+
125
+ describe 'products#update' do
126
+ let(:params) do
127
+ {
128
+ product: {
129
+ name: 'Updated Prodouct',
130
+ shipping_category_id: shipping_category.id,
131
+ price: 12.34
132
+ }
133
+ }
134
+ end
135
+
136
+ before { put "/api/v1/products/#{selected_product.id}", params: params }
137
+
138
+ context 'as regular user' do
139
+ it 'cannot update product' do
140
+ expect(response.status).to eq(401)
141
+ end
142
+ end
143
+
144
+ context 'as an admin' do
145
+ sign_in_as_admin!
146
+
147
+ it 'can update product' do
148
+ expect(response.status).to eq(200)
149
+ expect(json_response['name']).to eq(params[:product][:name])
150
+ expect(json_response['price']).to eq(params[:product][:price].to_s)
151
+ expect(json_response['shipping_category_id']).to eq(params[:product][:shipping_category_id])
152
+ end
153
+ end
154
+
155
+ context 'as a vendor' do
156
+ let!(:current_api_user) do
157
+ user = create(:user, vendors: [vendor])
158
+ user
159
+ end
160
+
161
+ describe 'cannot update product of another vendor' do
162
+ let(:selected_product) { product_with_other_vendor }
163
+
164
+ it do
165
+ expect(response.status).to eq(404)
166
+ end
167
+ end
168
+
169
+ describe 'can update product assigned to that vendor' do
170
+ let(:selected_product) { product_with_vendor_vendor }
171
+
172
+ it do
173
+ expect(response.status).to eq(200)
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ describe 'products#destroy' do
180
+ before { delete "/api/v1/products/#{selected_product.id}" }
181
+
182
+ context 'as regular user' do
183
+ it 'cannot delete product' do
184
+ expect(response.status).to eq(401)
185
+ end
186
+ end
187
+
188
+ context 'as an admin' do
189
+ sign_in_as_admin!
190
+
191
+ it 'can delete product' do
192
+ expect(response.status).to eq(204)
193
+ expect(product_without_vendor.reload.deleted_at).to_not eq(nil)
194
+ end
195
+ end
196
+
197
+ context 'as a vendor' do
198
+ let!(:current_api_user) do
199
+ user = create(:user, vendors: [vendor])
200
+ user
201
+ end
202
+
203
+ describe 'cannot delete product of another vendor' do
204
+ let(:selected_product) { product_with_other_vendor }
205
+
206
+ it do
207
+ expect(response.status).to eq(404)
208
+ end
209
+ end
210
+
211
+ describe 'can delete product assigned to that vendor' do
212
+ let(:selected_product) { product_with_vendor_vendor }
213
+
214
+ it do
215
+ expect(response.status).to eq(204)
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe 'API V1 Users Spec', type: :request do
5
+ let(:user) { create(:user) }
6
+ let(:vendor) { create(:vendor, state: :active) }
7
+
8
+ before { stub_authentication! }
9
+
10
+ describe 'users#update' do
11
+ let(:params) do
12
+ {
13
+ user: {
14
+ vendor_ids: [vendor.id]
15
+ }
16
+ }
17
+ end
18
+
19
+ before { put "/api/v1/users/#{user.id}", params: params }
20
+
21
+ context 'as an admin' do
22
+ sign_in_as_admin!
23
+
24
+ it 'can update user' do
25
+ expect(response.status).to eq(200)
26
+ expect(json_response['vendor_ids']).to eq([vendor.id])
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -26,7 +26,7 @@ describe 'API V2 Storefront Cart Spec', type: :request do
26
26
  it_behaves_like 'returns valid cart JSON'
27
27
  end
28
28
 
29
- context 'includes vendor and totals data' do
29
+ context 'with one vendor' do
30
30
  let(:params) { { include: 'vendors,vendor_totals' } }
31
31
 
32
32
  it_behaves_like 'showing the cart'
@@ -42,6 +42,24 @@ describe 'API V2 Storefront Cart Spec', type: :request do
42
42
  end
43
43
  end
44
44
 
45
+ context 'with many vendors' do
46
+ let!(:line_item_2) { create(:line_item, order: order, product: product_2, variant: product_2.default_variant) }
47
+ let(:params) { { include: 'vendors,vendor_totals' } }
48
+
49
+ it_behaves_like 'showing the cart'
50
+
51
+ it 'includes many vendors and vendor totals' do
52
+ get '/api/v2/storefront/cart', headers: headers_bearer, params: params
53
+
54
+ [vendor, vendor_2].each do |vendor|
55
+ expect(json_response['included']).to include(have_type('vendor').and have_id(vendor.id.to_s))
56
+ expect(json_response['included']).to include(have_type('vendor_totals').and have_id(vendor.id.to_s))
57
+ expect(json_response['included']).to include(have_type('vendor').and have_attribute(:name).with_value(vendor.name))
58
+ expect(json_response['included']).to include(have_type('vendor_totals').and have_attribute(:name).with_value(vendor.name))
59
+ end
60
+ end
61
+ end
62
+
45
63
  context 'includes line item vendor data' do
46
64
  it_behaves_like 'showing the cart'
47
65
 
@@ -31,8 +31,8 @@ describe Spree::V2::Storefront::VendorOrderTotalsSerializer do
31
31
  display_included_tax_total: Spree::Money.new(30),
32
32
  ship_total: BigDecimal(25),
33
33
  display_ship_total: Spree::Money.new(25),
34
- subtotal: BigDecimal(600),
35
- display_subtotal: Spree::Money.new(600),
34
+ subtotal: BigDecimal(680),
35
+ display_subtotal: Spree::Money.new(680),
36
36
  promo_total: BigDecimal(60),
37
37
  display_promo_total: Spree::Money.new(60),
38
38
  total: BigDecimal(625),
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_multi_vendor
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Spark Solutions
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-11 00:00:00.000000000 Z
11
+ date: 2021-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree_core
@@ -151,8 +151,12 @@ files:
151
151
  - app/controllers/spree_multi_vendor/spree/admin/stock_locations_controller_decorator.rb
152
152
  - app/controllers/spree_multi_vendor/spree/admin/users_controller_decorator.rb
153
153
  - app/controllers/spree_multi_vendor/spree/admin/variants_controller_decorator.rb
154
+ - app/controllers/spree_multi_vendor/spree/api/base_controller_decorator.rb
155
+ - app/controllers/spree_multi_vendor/spree/api/v1/products_controller_decorator.rb
156
+ - app/controllers/spree_multi_vendor/spree/api/v1/users_controller_decorator.rb
154
157
  - app/finders/spree_multi_vendor/products_finder_decorator.rb
155
158
  - app/helpers/spree/admin/vendor_helper.rb
159
+ - app/helpers/spree/api/vendor_helper.rb
156
160
  - app/helpers/spree_multi_vendor/spree/api/api_helpers_decorator.rb
157
161
  - app/mailers/spree/vendor_mailer.rb
158
162
  - app/models/concerns/spree/vendor_concern.rb
@@ -245,6 +249,8 @@ files:
245
249
  - spec/models/spree/vendor_order_totals_spec.rb
246
250
  - spec/models/spree/vendor_spec.rb
247
251
  - spec/models/spree/vendor_user_spec.rb
252
+ - spec/requests/spree/api/v1/products_spec.rb
253
+ - spec/requests/spree/api/v1/users_spec.rb
248
254
  - spec/requests/spree/api/v1/vendors_spec.rb
249
255
  - spec/requests/spree/api/v2/storefront/cart_spec.rb
250
256
  - spec/requests/spree/api/v2/storefront/products_spec.rb
@@ -261,9 +267,9 @@ licenses:
261
267
  - BSD-3-Clause
262
268
  metadata:
263
269
  bug_tracker_uri: https://github.com/spree-contrib/spree_multi_vendor/issues
264
- changelog_uri: https://github.com/spree-contrib/spree_multi_vendor/releases/tag/v2.1.0
270
+ changelog_uri: https://github.com/spree-contrib/spree_multi_vendor/releases/tag/v2.2.0
265
271
  documentation_uri: https://guides.spreecommerce.org/
266
- source_code_uri: https://github.com/spree-contrib/spree_multi_vendor/tree/v2.1.0
272
+ source_code_uri: https://github.com/spree-contrib/spree_multi_vendor/tree/v2.2.0
267
273
  post_install_message:
268
274
  rdoc_options: []
269
275
  require_paths:
@@ -280,7 +286,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
280
286
  version: '0'
281
287
  requirements:
282
288
  - none
283
- rubygems_version: 3.0.3
289
+ rubygems_version: 3.2.3
284
290
  signing_key:
285
291
  specification_version: 4
286
292
  summary: Spree Commerce multi vendor marketplace extension
@@ -304,6 +310,8 @@ test_files:
304
310
  - spec/models/spree/vendor_order_totals_spec.rb
305
311
  - spec/models/spree/vendor_spec.rb
306
312
  - spec/models/spree/vendor_user_spec.rb
313
+ - spec/requests/spree/api/v1/products_spec.rb
314
+ - spec/requests/spree/api/v1/users_spec.rb
307
315
  - spec/requests/spree/api/v1/vendors_spec.rb
308
316
  - spec/requests/spree/api/v2/storefront/cart_spec.rb
309
317
  - spec/requests/spree/api/v2/storefront/products_spec.rb