spree_multi_vendor 2.1.0 → 2.2.0

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