atkhayar-dev-spree-multi-vendor 0.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 (134) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +10 -0
  3. data/LICENSE +26 -0
  4. data/README.md +181 -0
  5. data/Rakefile +21 -0
  6. data/app/controllers/spree/admin/vendor_settings_controller.rb +34 -0
  7. data/app/controllers/spree/admin/vendors_controller.rb +68 -0
  8. data/app/controllers/spree/api/v1/vendors_controller.rb +62 -0
  9. data/app/controllers/spree/api/v2/platform/vendors_controller.rb +32 -0
  10. data/app/controllers/spree/api/v2/storefront/vendors_controller.rb +33 -0
  11. data/app/controllers/spree_multi_vendor/spree/admin/base_controller_decorator.rb +10 -0
  12. data/app/controllers/spree_multi_vendor/spree/admin/products_controller_decorator.rb +79 -0
  13. data/app/controllers/spree_multi_vendor/spree/admin/resource_controller_decorator.rb +8 -0
  14. data/app/controllers/spree_multi_vendor/spree/admin/shipping_methods_controller_decorator.rb +7 -0
  15. data/app/controllers/spree_multi_vendor/spree/admin/stock_locations_controller_decorator.rb +7 -0
  16. data/app/controllers/spree_multi_vendor/spree/admin/users_controller_decorator.rb +13 -0
  17. data/app/controllers/spree_multi_vendor/spree/admin/variants_controller_decorator.rb +7 -0
  18. data/app/controllers/spree_multi_vendor/spree/api/base_controller_decorator.rb +17 -0
  19. data/app/controllers/spree_multi_vendor/spree/api/v1/products_controller_decorator.rb +9 -0
  20. data/app/controllers/spree_multi_vendor/spree/api/v1/users_controller_decorator.rb +13 -0
  21. data/app/controllers/spree_multi_vendor/spree/api/v2/platform/products_controller_decorator.rb +65 -0
  22. data/app/finders/spree_multi_vendor/products_finder_decorator.rb +31 -0
  23. data/app/helpers/spree/admin/vendor_helper.rb +15 -0
  24. data/app/helpers/spree/api/vendor_helper.rb +13 -0
  25. data/app/helpers/spree_multi_vendor/spree/api/api_helpers_decorator.rb +19 -0
  26. data/app/mailers/spree/vendor_mailer.rb +15 -0
  27. data/app/models/concerns/spree/vendor_concern.rb +11 -0
  28. data/app/models/spree/order_commission.rb +11 -0
  29. data/app/models/spree/vendor.rb +77 -0
  30. data/app/models/spree/vendor_ability.rb +155 -0
  31. data/app/models/spree/vendor_image.rb +18 -0
  32. data/app/models/spree/vendor_order_totals.rb +28 -0
  33. data/app/models/spree/vendor_user.rb +16 -0
  34. data/app/models/spree_multi_vendor/configuration.rb +10 -0
  35. data/app/models/spree_multi_vendor/spree/ability_decorator.rb +9 -0
  36. data/app/models/spree_multi_vendor/spree/base_decorator.rb +13 -0
  37. data/app/models/spree_multi_vendor/spree/line_item_decorator.rb +48 -0
  38. data/app/models/spree_multi_vendor/spree/order_decorator.rb +107 -0
  39. data/app/models/spree_multi_vendor/spree/shipment_decorator.rb +8 -0
  40. data/app/models/spree_multi_vendor/spree/stock/package_decorator.rb +14 -0
  41. data/app/models/spree_multi_vendor/spree/user_decorator.rb +8 -0
  42. data/app/models/spree_multi_vendor/spree/variant_decorator.rb +40 -0
  43. data/app/overrides/spree/admin/orders/_form.rb +13 -0
  44. data/app/overrides/spree/admin/orders/_line_items.rb +6 -0
  45. data/app/overrides/spree/admin/orders/_line_items_edit_form.rb +6 -0
  46. data/app/overrides/spree/admin/orders/index.rb +6 -0
  47. data/app/overrides/spree/admin/products/form.rb +29 -0
  48. data/app/overrides/spree/admin/products/new.rb +16 -0
  49. data/app/overrides/spree/admin/shared/_main_menu.rb +23 -0
  50. data/app/overrides/spree/admin/shared/_order_summary.rb +35 -0
  51. data/app/overrides/spree/admin/users/_form.rb +13 -0
  52. data/app/serializers/spree/api/v2/platform/vendor_serializer.rb +12 -0
  53. data/app/serializers/spree/v2/storefront/vendor_image_serializer.rb +11 -0
  54. data/app/serializers/spree/v2/storefront/vendor_order_totals_serializer.rb +20 -0
  55. data/app/serializers/spree/v2/storefront/vendor_serializer.rb +15 -0
  56. data/app/serializers/spree_multi_vendor/cart_serializer_decorator.rb +19 -0
  57. data/app/serializers/spree_multi_vendor/serializer_decorator.rb +23 -0
  58. data/app/services/spree/orders/generate_commissions.rb +34 -0
  59. data/app/views/spree/admin/translations/vendor.html.erb +21 -0
  60. data/app/views/spree/admin/vendor_settings/edit.html.erb +47 -0
  61. data/app/views/spree/admin/vendors/_form.html.erb +36 -0
  62. data/app/views/spree/admin/vendors/edit.html.erb +11 -0
  63. data/app/views/spree/admin/vendors/index.html.erb +83 -0
  64. data/app/views/spree/admin/vendors/new.html.erb +11 -0
  65. data/app/views/spree/api/v1/vendors/index.rabl +3 -0
  66. data/app/views/spree/api/v1/vendors/show.rabl +2 -0
  67. data/app/views/spree/vendor_mailer/vendor_notification_email.html.erb +81 -0
  68. data/app/views/spree/vendor_mailer/vendor_notification_email.text.erb +36 -0
  69. data/bin/rails +7 -0
  70. data/config/initializers/spree.rb +31 -0
  71. data/config/initializers/spree_permitted_attributes.rb +12 -0
  72. data/config/locales/en.yml +34 -0
  73. data/config/locales/es.yml +36 -0
  74. data/config/locales/fr.yml +33 -0
  75. data/config/routes.rb +29 -0
  76. data/db/default/vendors.rb +13 -0
  77. data/db/migrate/20170406102250_create_spree_vendors.rb +9 -0
  78. data/db/migrate/20170406102944_add_vendor_id_to_spree_models.rb +10 -0
  79. data/db/migrate/20170410111150_add_state_to_vendors.rb +6 -0
  80. data/db/migrate/20170412124925_add_deleted_at_to_spree_vendors.rb +6 -0
  81. data/db/migrate/20170413094447_create_spree_vendor_users.rb +11 -0
  82. data/db/migrate/20190212161426_add_slug_to_spree_vendors.rb +6 -0
  83. data/db/migrate/20190214120226_add_about_us_to_spree_vendors.rb +5 -0
  84. data/db/migrate/20190214142526_add_contact_us_to_spree_vendors.rb +5 -0
  85. data/db/migrate/20190305120337_add_commission_to_spree_vendors.rb +5 -0
  86. data/db/migrate/20190308091546_add_priority_to_vendor.rb +8 -0
  87. data/db/migrate/20190312130754_create_spree_order_commissions.rb +14 -0
  88. data/db/migrate/20190322133128_add_notification_email_to_vendors.rb +5 -0
  89. data/db/migrate/20200416030721_add_translations_to_vendor.rb +19 -0
  90. data/db/migrate/20210728120649_change_vendorized_models_vendor_id_type.rb +10 -0
  91. data/db/migrate/20210728120910_change_vendor_id_and_user_id_type_for_spree_vendor_users.rb +14 -0
  92. data/db/migrate/20210728121024_change_vendor_id_and_order_id_type_for_spree_order_commissions.rb +14 -0
  93. data/db/migrate/20221123095256_add_code_to_vendors.rb +6 -0
  94. data/lib/generators/spree_multi_vendor/install/install_generator.rb +21 -0
  95. data/lib/generators/spree_multi_vendor/mailers_preview/mailers_preview_generator.rb +22 -0
  96. data/lib/generators/spree_multi_vendor/mailers_preview/templates/mailers/previews/vendor_notification_preview.rb +5 -0
  97. data/lib/spree_multi_vendor/engine.rb +24 -0
  98. data/lib/spree_multi_vendor/factories.rb +7 -0
  99. data/lib/spree_multi_vendor/version.rb +11 -0
  100. data/lib/spree_multi_vendor.rb +16 -0
  101. data/lib/tasks/vendors.rake +8 -0
  102. data/spec/factories/spree/vendor_factory.rb +28 -0
  103. data/spec/factories/spree/vendor_image_factory.rb +5 -0
  104. data/spec/factories/spree/vendor_user_factory.rb +6 -0
  105. data/spec/features/spree/admin/orders_spec.rb +86 -0
  106. data/spec/features/spree/admin/product_spec.rb +177 -0
  107. data/spec/features/spree/admin/shipping_method_spec.rb +72 -0
  108. data/spec/features/spree/admin/stock_location_spec.rb +90 -0
  109. data/spec/features/spree/admin/vendor_settings_spec.rb +74 -0
  110. data/spec/features/spree/admin/vendor_spec.rb +125 -0
  111. data/spec/fixtures/thinking-cat.jpg +0 -0
  112. data/spec/mailers/vendor_mailer_spec.rb +45 -0
  113. data/spec/models/spree/line_item_spec.rb +32 -0
  114. data/spec/models/spree/order_commission_spec.rb +8 -0
  115. data/spec/models/spree/order_spec.rb +193 -0
  116. data/spec/models/spree/product_spec.rb +19 -0
  117. data/spec/models/spree/variant_spec.rb +104 -0
  118. data/spec/models/spree/vendor_order_totals_spec.rb +33 -0
  119. data/spec/models/spree/vendor_spec.rb +57 -0
  120. data/spec/models/spree/vendor_user_spec.rb +12 -0
  121. data/spec/requests/spree/api/v1/products_spec.rb +221 -0
  122. data/spec/requests/spree/api/v1/users_spec.rb +31 -0
  123. data/spec/requests/spree/api/v1/vendors_spec.rb +210 -0
  124. data/spec/requests/spree/api/v2/storefront/cart_spec.rb +85 -0
  125. data/spec/requests/spree/api/v2/storefront/products_spec.rb +96 -0
  126. data/spec/requests/spree/api/v2/storefront/vendors_spec.rb +118 -0
  127. data/spec/serializers/spree/v2/storefront/stock_location_serializer_spec.rb +32 -0
  128. data/spec/serializers/spree/v2/storefront/vendor_image_serializer_spec.rb +18 -0
  129. data/spec/serializers/spree/v2/storefront/vendor_order_totals_serializer_spec.rb +54 -0
  130. data/spec/serializers/spree/v2/storefront/vendor_serializer_spec.rb +34 -0
  131. data/spec/spec_helper.rb +13 -0
  132. data/spec/support/shoulda_matchers.rb +6 -0
  133. data/spree_multi_vendor.gemspec +42 -0
  134. metadata +308 -0
@@ -0,0 +1,5 @@
1
+ FactoryBot.define do
2
+ factory :vendor_image, class: Spree::VendorImage do
3
+ attachment { Rack::Test::UploadedFile.new(SpreeMultiVendor::Engine.root.join('spec', 'fixtures', 'thinking-cat.jpg'), 'image/jpeg') }
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :vendor_user, class: Spree::Vendor do
3
+ user
4
+ vendor
5
+ end
6
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Orders', :js do
4
+ let(:store) { Spree::Store.default }
5
+ let(:vendor) { create(:active_vendor, name: 'Vendor') }
6
+ let(:vendor_2) { create(:active_vendor, name: 'Other vendor') }
7
+ let(:order) { create(:order, ship_address: create(:address), bill_address: create(:address), store: store) }
8
+ let(:order_2) { create(:order, store: store) }
9
+ let!(:user) { create(:user, vendors: [vendor]) }
10
+ let(:product) { create(:product_in_stock, vendor: vendor, stores:[store]) }
11
+ let(:product_2) { create(:product_in_stock, vendor: vendor_2,stores:[store]) }
12
+
13
+ before do
14
+ create(:line_item, order: order, product: product)
15
+ create(:line_item, order: order, product: product_2)
16
+ order.create_proposed_shipments
17
+ order.update(state: :complete, completed_at: Time.current)
18
+ login_as(user, scope: :spree_user)
19
+ end
20
+
21
+ shared_examples 'shows order data' do
22
+ it { expect(page).to have_text(order.number) }
23
+ it { expect(page).to have_content(order.display_vendor_total(vendor).to_html) }
24
+ end
25
+
26
+ context 'index' do
27
+ background do
28
+ visit spree.admin_orders_path
29
+ end
30
+
31
+ it_behaves_like 'shows order data'
32
+
33
+ it 'does not show non-vendor orders' do
34
+ expect(page).not_to have_text(order_2.number)
35
+ end
36
+ end
37
+
38
+ context 'cart' do
39
+ background do
40
+ visit spree.cart_admin_order_path(id: order.number)
41
+ end
42
+
43
+ it_behaves_like 'shows order data'
44
+ end
45
+
46
+ context 'customer info' do
47
+ background do
48
+ visit spree.admin_order_customer_path(order_id: order.number)
49
+ end
50
+
51
+ it_behaves_like 'shows order data'
52
+
53
+ it 'shows customer information' do
54
+ expect(page).to have_text(order.ship_address.full_name)
55
+ expect(page).to have_text(order.ship_address.address1)
56
+ expect(page).to have_text(order.ship_address.city)
57
+
58
+ expect(page).to have_text(order.bill_address.full_name)
59
+ expect(page).to have_text(order.bill_address.address1)
60
+ expect(page).to have_text(order.bill_address.city)
61
+
62
+ expect(page).not_to have_selector('input[type=text]')
63
+ end
64
+ end
65
+
66
+ context 'edit' do
67
+ background do
68
+ visit spree.edit_admin_order_path(id: order.number)
69
+ end
70
+
71
+ it_behaves_like 'shows order data'
72
+
73
+ scenario 'vendor can add his product' do
74
+ select2_open label: 'Name or SKU'
75
+ select2_search product.name, from: 'Name or SKU'
76
+ select2_select product.name, from: 'Name or SKU', match: :first
77
+ expect(page).to have_text(product.name)
78
+ end
79
+
80
+ scenario 'vendor cannot add other vendors product' do
81
+ select2_open label: 'Name or SKU'
82
+ select2_search product_2.name, from: 'Name or SKU'
83
+ expect(page).not_to have_text(product_2.name)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,177 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Products', :js do
4
+ let(:vendor) { create(:active_vendor) }
5
+ let!(:user) { create(:user, vendors: [vendor]) }
6
+ let!(:admin) { create(:admin_user) }
7
+ let!(:option_type) { create(:option_type, name: 'Testing option') }
8
+ let!(:option_value) { create(:option_value, option_type: option_type) }
9
+ let!(:product) { create(:product, sku: 'Test1') }
10
+ let!(:vendor_product) { create(:product, vendor: vendor, sku: 'Test2', option_types: [option_type]) }
11
+
12
+ context 'for user with admin role' do
13
+ before { login_as(admin, scope: :spree_user) }
14
+
15
+ context 'index' do
16
+ scenario 'displays all products' do
17
+ visit spree.admin_products_path
18
+ expect(page).to have_selector('tr', count: 3)
19
+ end
20
+ end
21
+
22
+ context 'create product' do
23
+ scenario 'creates new product with vendor id unassigned' do
24
+ visit spree.admin_products_path
25
+ click_link 'New Product'
26
+ expect(current_path).to eq spree.new_admin_product_path
27
+
28
+ fill_in 'product_name', with: 'Vendor product'
29
+ fill_in 'product_price', with: 15
30
+ select2 Spree::ShippingCategory.last.name, from: 'Shipping Categories'
31
+
32
+ click_button 'Create'
33
+
34
+ expect(page).to have_text 'successfully created!'
35
+ expect(current_path).to eq spree.edit_admin_product_path(Spree::Product.last)
36
+ expect(Spree::Product.last.vendor_id).to eq nil
37
+ end
38
+ scenario 'creates new product with assigned vendor' do
39
+ visit spree.admin_products_path
40
+ click_link 'New Product'
41
+ expect(current_path).to eq spree.new_admin_product_path
42
+
43
+ fill_in 'product_name', with: 'Vendor product'
44
+ fill_in 'product_price', with: 15
45
+ select2 Spree::ShippingCategory.last.name, from: 'Shipping Categories'
46
+ select2 'Active vendor', from: 'Vendor'
47
+
48
+ click_button 'Create'
49
+
50
+ expect(page).to have_text 'successfully created!'
51
+ expect(current_path).to eq spree.edit_admin_product_path(Spree::Product.last)
52
+ expect(Spree::Product.last.vendor_id).to eq Spree::Vendor.last.id
53
+ end
54
+ end
55
+
56
+ context 'edit product' do
57
+ before(:each) do
58
+ visit spree.edit_admin_product_path(product)
59
+ expect(current_path).to eq spree.edit_admin_product_path(product)
60
+ end
61
+
62
+ scenario 'can update an existing product' do
63
+ fill_in 'product_name', with: 'Testing edit'
64
+ click_button 'Update'
65
+ expect(page).to have_text 'successfully updated!'
66
+ expect(page).to have_text 'Testing edit'
67
+ end
68
+
69
+ scenario 'can update product master price' do
70
+ fill_in 'product_price', with: 123
71
+ click_button 'Update'
72
+ expect(page).to have_text 'successfully updated!'
73
+ product.reload
74
+ expect(product.price).to eq 123
75
+ end
76
+
77
+ scenario 'can update product vendor' do
78
+ expect(product.vendor).to eq nil
79
+ select2 vendor.name, from: 'Vendor'
80
+ click_button 'Update'
81
+ expect(page).to have_text 'successfully updated!'
82
+ product.reload
83
+ expect(product.vendor).to eq vendor
84
+ end
85
+ end
86
+
87
+ context 'create variant' do
88
+ scenario 'creates new variant with vendor id assigned' do
89
+ visit spree.admin_product_variants_path(vendor_product)
90
+ click_link 'New Variant'
91
+ select2 'S', from: 'Size'
92
+ click_button 'Create'
93
+ expect(page).to have_text 'successfully created!'
94
+ expect(Spree::Variant.last.vendor_id).to eq vendor.id
95
+ end
96
+ end
97
+ end
98
+
99
+ context 'for user with vendor' do
100
+ before(:each) do
101
+ login_as(user, scope: :spree_user)
102
+ visit spree.admin_products_path
103
+ end
104
+
105
+ context 'index' do
106
+ scenario 'displays only vendor product' do
107
+ expect(page).to have_selector('tr', count: 2)
108
+ end
109
+ end
110
+
111
+ context 'create product' do
112
+ scenario 'can create a new product' do
113
+ click_link 'New Product'
114
+ expect(current_path).to eq spree.new_admin_product_path
115
+
116
+ fill_in 'product_name', with: 'Vendor product'
117
+ fill_in 'product_price', with: 15
118
+ select2 Spree::ShippingCategory.last.name, from: 'Shipping Categories'
119
+
120
+ click_button 'Create'
121
+
122
+ expect(page).to have_text 'successfully created!'
123
+ expect(current_path).to eq spree.edit_admin_product_path(Spree::Product.last)
124
+ expect(Spree::Product.last.vendor_id).to eq vendor.id
125
+ end
126
+ end
127
+
128
+ context 'edit product' do
129
+ before(:each) do
130
+ within_row(1) { click_icon :edit }
131
+ expect(current_path).to eq spree.edit_admin_product_path(vendor_product)
132
+ end
133
+
134
+ scenario 'can update an existing product' do
135
+ fill_in 'product_name', with: 'Testing edit'
136
+ click_button 'Update'
137
+ expect(page).to have_text 'successfully updated!'
138
+ expect(page).to have_text 'Testing edit'
139
+ end
140
+
141
+ scenario 'can update product master price' do
142
+ fill_in 'product_price', with: 123
143
+ click_button 'Update'
144
+ expect(page).to have_text 'successfully updated!'
145
+ vendor_product.reload
146
+ expect(vendor_product.price).to eq 123
147
+ end
148
+
149
+ scenario 'shows validation error with blank name' do
150
+ fill_in 'product_name', with: ''
151
+ click_button 'Update'
152
+ expect(page).to have_text 'Name can\'t be blank'
153
+ end
154
+ end
155
+
156
+ context 'create product property' do
157
+ scenario 'can create new product property' do
158
+ visit spree.admin_product_product_properties_path(vendor_product)
159
+ fill_in 'product[product_properties_attributes][0][property_name]', with: 'Testing edit'
160
+ click_button 'Update'
161
+ expect(page).to have_text 'successfully updated!'
162
+ # expect(Spree::ProductProperty.last.property.vendor_id).to eq vendor.id
163
+ end
164
+ end
165
+
166
+ context 'create variant' do
167
+ scenario 'can create new variant' do
168
+ visit spree.admin_product_variants_path(vendor_product)
169
+ click_link 'New Variant'
170
+ select2 'S', from: 'Size'
171
+ click_button 'Create'
172
+ expect(page).to have_text 'successfully created!'
173
+ expect(Spree::Variant.last.option_values).to include option_value
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Shipping Methods', :js do
4
+ let(:active_vendor) { create(:active_vendor) }
5
+ let!(:user) { create(:user, vendors: [active_vendor]) }
6
+ let!(:admin) { create(:admin_user) }
7
+ let!(:shipping_method) { create(:shipping_method, name: 'Test') }
8
+ let!(:vendor_shipping_method) { create(:shipping_method, name: 'Test', vendor: active_vendor) }
9
+
10
+ context 'for user with admin role' do
11
+ context 'index' do
12
+ scenario 'displays all shipping methods' do
13
+ login_as(admin, scope: :spree_user)
14
+ visit spree.admin_shipping_methods_path
15
+ expect(page).to have_selector('tr', count: 3)
16
+ end
17
+ end
18
+ end
19
+
20
+ context 'for user with vendor' do
21
+ before(:each) do
22
+ login_as(user, scope: :spree_user)
23
+ visit spree.admin_shipping_methods_path
24
+ end
25
+
26
+ context 'index' do
27
+ scenario 'displays only vendor shipping method' do
28
+ expect(page).to have_selector('tr', count: 2)
29
+ end
30
+ end
31
+
32
+ context 'create' do
33
+ scenario 'can create a new shipping method' do
34
+ click_link 'New Shipping Method'
35
+ expect(current_path).to eq spree.new_admin_shipping_method_path
36
+
37
+ fill_in 'shipping_method_name', with: 'Vendor shipping method'
38
+ check Spree::ShippingCategory.last.name
39
+
40
+ if Spree.version.to_f >= 4.0
41
+ select2 'Both', from: 'Display'
42
+ end
43
+
44
+ click_button 'Create'
45
+
46
+ expect(page).to have_text 'successfully created!'
47
+ expect(current_path).to eq spree.edit_admin_shipping_method_path(Spree::ShippingMethod.last)
48
+ expect(Spree::ShippingMethod.last.vendor_id).to eq active_vendor.id
49
+ end
50
+ end
51
+
52
+ context 'edit' do
53
+ before(:each) do
54
+ within_row(1) { click_icon :edit }
55
+ expect(current_path).to eq spree.edit_admin_shipping_method_path(active_vendor.shipping_methods.first)
56
+ end
57
+
58
+ scenario 'can update an existing shipping method' do
59
+ fill_in 'shipping_method_name', with: 'Testing edit'
60
+ click_button 'Update'
61
+ expect(page).to have_text 'successfully updated!'
62
+ expect(page).to have_text 'Testing edit'
63
+ end
64
+
65
+ scenario 'shows validation error with blank name' do
66
+ fill_in 'shipping_method_name', with: ''
67
+ click_button 'Update'
68
+ expect(page).to_not have_text 'successfully created!'
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Stock Locations', :js do
4
+ let(:active_vendor) { create(:active_vendor) }
5
+ let!(:product) { create(:product, vendor_id: active_vendor.id, name: 'Test') }
6
+ let!(:user) { create(:user, vendors: [active_vendor]) }
7
+ let!(:admin) { create(:admin_user) }
8
+ let!(:stock_location) { create(:stock_location, name: 'Test') }
9
+
10
+ context 'for user with admin role' do
11
+ context 'index' do
12
+ scenario 'displays all stock locations' do
13
+ login_as(admin, scope: :spree_user)
14
+ visit spree.admin_stock_locations_path
15
+ expect(page).to have_selector('tr', count: 3)
16
+ end
17
+ end
18
+ end
19
+
20
+ context 'for user with vendor' do
21
+ before(:each) do
22
+ login_as(user, scope: :spree_user)
23
+ visit spree.admin_stock_locations_path
24
+ end
25
+
26
+ context 'index' do
27
+ scenario 'displays only vendor stock location' do
28
+ expect(page).to have_selector('tr', count: 2)
29
+ end
30
+ end
31
+
32
+ context 'stock movements' do
33
+ scenario 'displays stock movements for vendor stock location' do
34
+ click_on 'Stock Movements'
35
+ expect(page).to have_text 'Stock Movements for Active vendor'
36
+ end
37
+
38
+ scenario 'can create a new stock movement for vendor stock location' do
39
+ click_on 'Stock Movements'
40
+ click_on 'New Stock Movement'
41
+ expect(current_path).to eq spree.new_admin_stock_location_stock_movement_path(active_vendor.stock_locations.first)
42
+
43
+ fill_in 'stock_movement_quantity', with: 5
44
+ select2_open label: 'Stock Item'
45
+ select2_search product.name, from: 'Stock Item'
46
+ select2_select product.name, from: 'Stock Item', match: :first
47
+
48
+ click_button 'Create'
49
+
50
+ expect(page).to have_text 'successfully created!'
51
+ expect(Spree::StockMovement.count).to eq 1
52
+ end
53
+ end
54
+
55
+ context 'create' do
56
+ scenario 'can create a new stock location' do
57
+ click_link 'New Stock Location'
58
+ expect(current_path).to eq spree.new_admin_stock_location_path
59
+
60
+ fill_in 'stock_location_name', with: 'Vendor stock location'
61
+
62
+ click_button 'Create'
63
+
64
+ expect(page).to have_text 'successfully created!'
65
+ expect(current_path).to eq spree.admin_stock_locations_path
66
+ expect(Spree::StockLocation.last.vendor_id).to eq active_vendor.id
67
+ end
68
+ end
69
+
70
+ context 'edit' do
71
+ before(:each) do
72
+ within_row(1) { click_icon :edit }
73
+ expect(current_path).to eq spree.edit_admin_stock_location_path(active_vendor.stock_locations.first)
74
+ end
75
+
76
+ scenario 'can update an existing stock location' do
77
+ fill_in 'stock_location_name', with: 'Testing edit'
78
+ click_button 'Update'
79
+ expect(page).to have_text 'successfully updated!'
80
+ expect(page).to have_text 'Testing edit'
81
+ end
82
+
83
+ scenario 'shows validation error with blank name' do
84
+ fill_in 'stock_location_name', with: ''
85
+ click_button 'Update'
86
+ expect(page).to_not have_text 'successfully created!'
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Vendor Settings', :js do
4
+ let(:vendor) { create(:active_vendor) }
5
+ let(:blocked_vendor) { create(:blocked_vendor)}
6
+ let!(:user) { create(:user, vendors: [vendor]) }
7
+ let!(:user_with_blocked_vendor) { create(:user, vendors: [blocked_vendor]) }
8
+
9
+ context 'edit' do
10
+ background do
11
+ login_as(user, scope: :spree_user)
12
+ visit spree.admin_vendor_settings_path
13
+ end
14
+
15
+ scenario 'can update current vendor' do
16
+ fill_in 'vendor_name', with: 'Testing edit'
17
+ fill_in 'vendor_about_us', with: 'Testing about us edit'
18
+ fill_in 'vendor_contact_us', with: 'Testing contact us edit'
19
+ expect {
20
+ click_button 'Update'
21
+ }.to change { vendor.reload.slug }.from('active-vendor').to('testing-edit')
22
+ expect(page).to have_text 'Testing edit'
23
+ expect(page).to have_text 'Testing about us edit'
24
+ expect(page).to have_text 'Testing contact us edit'
25
+ end
26
+
27
+ scenario 'shows validation error with blank name' do
28
+ fill_in 'vendor_name', with: ''
29
+ click_button 'Update'
30
+ expect(page).to have_text 'name can\'t be blank'
31
+ end
32
+
33
+ scenario 'does not show validation error with blank about_us' do
34
+ fill_in 'vendor_about_us', with: ''
35
+ click_button 'Update'
36
+ expect(page).not_to have_text 'about_us can\'t be blank'
37
+ end
38
+
39
+ scenario 'does not show validation error with blank contact_us' do
40
+ fill_in 'vendor_contact_us', with: ''
41
+ click_button 'Update'
42
+ expect(page).not_to have_text 'contact_us can\'t be blank'
43
+ end
44
+
45
+ scenario 'can update an existing vendor image' do
46
+ create(:vendor, name: 'New vendor')
47
+ page.attach_file("vendor_image", Spree::Core::Engine.root + 'spec/fixtures' + 'thinking-cat.jpg')
48
+ click_button 'Update'
49
+ expect(page).to have_css("img[src*='thinking-cat.jpg']")
50
+ end
51
+ end
52
+
53
+ context 'no vendor present' do
54
+ before do
55
+ vendor.destroy!
56
+ end
57
+
58
+ it 'renders page without errors' do
59
+ visit spree.admin_vendor_settings_path
60
+ expect(page).to have_current_path('/admin/login')
61
+ end
62
+ end
63
+
64
+ context 'blocked vendor present' do
65
+ background do
66
+ login_as(user_with_blocked_vendor, scope: :spree_user)
67
+ end
68
+
69
+ it 'renders forbidden page' do
70
+ visit spree.admin_vendor_settings_path
71
+ expect(current_path).to eq spree.admin_forbidden_path
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.feature 'Admin Vendors', :js do
4
+ let!(:admin) { create(:admin_user) }
5
+ let!(:vendor_user) { create(:user) }
6
+
7
+ background do
8
+ login_as(admin, scope: :spree_user)
9
+ create(:active_vendor, users: [vendor_user]) if Spree::Vendor.find_by(name: 'Active vendor').nil?
10
+ create(:pending_vendor)
11
+ create(:blocked_vendor)
12
+ visit spree.admin_vendors_path
13
+ end
14
+
15
+ context 'index' do
16
+ scenario 'displays existing vendors' do
17
+ within_row(1) do
18
+ expect(column_text(1)).to eq vendor_user.email
19
+ expect(column_text(2)).to eq 'Active vendor'
20
+ expect(column_text(3)).to eq 'active'
21
+ end
22
+ end
23
+
24
+ scenario 'filter by multiple states' do
25
+ click_button 'Filter'
26
+ select2 'Active', from: 'State'
27
+ select2 'Pending', from: 'State'
28
+
29
+ click_button 'Filter Results'
30
+
31
+ expect(page).to have_content('active')
32
+ expect(page).to have_content('pending')
33
+ expect(page).not_to have_content('blocked')
34
+ end
35
+ end
36
+
37
+ context 'create' do
38
+ scenario 'can create a new vendor' do
39
+ click_link 'New Vendor'
40
+ expect(current_path).to eq spree.new_admin_vendor_path
41
+
42
+ fill_in 'vendor_name', with: 'Test'
43
+ fill_in 'vendor_about_us', with: 'About...'
44
+ fill_in 'vendor_contact_us', with: 'Contact...'
45
+ expect(find_field('vendor_commission_rate').value).to eq '5.0'
46
+ select 'Blocked'
47
+
48
+ click_button 'Create'
49
+
50
+ expect(page).to have_text 'successfully created!'
51
+ expect(current_path).to eq spree.admin_vendors_path
52
+ end
53
+
54
+ scenario 'shows validation error with blank name' do
55
+ click_link 'New Vendor'
56
+ expect(current_path).to eq spree.new_admin_vendor_path
57
+
58
+ fill_in 'vendor_name', with: ''
59
+ click_button 'Create'
60
+
61
+ expect(page).to have_text 'name can\'t be blank'
62
+ end
63
+
64
+ scenario 'shows validation error with repeated name' do
65
+ click_link 'New Vendor'
66
+ expect(current_path).to eq spree.new_admin_vendor_path
67
+
68
+ fill_in 'vendor_name', with: 'Active vendor'
69
+ click_button 'Create'
70
+
71
+ expect(page).to have_text 'name has already been taken'
72
+ end
73
+ end
74
+
75
+ context 'edit' do
76
+ background do
77
+ within_row(1) { click_icon :edit }
78
+ expect(current_path).to eq spree.edit_admin_vendor_path('active-vendor')
79
+ end
80
+
81
+ scenario 'can update an existing vendor' do
82
+ fill_in 'vendor_name', with: 'Testing edit'
83
+ fill_in 'vendor_about_us', with: 'Testing about us'
84
+ fill_in 'vendor_contact_us', with: 'Testing contact us'
85
+ fill_in 'vendor_commission_rate', with: '5.5'
86
+ click_button 'Update'
87
+ expect(page).to have_text 'successfully updated!'
88
+ expect(page).to have_text 'Testing edit'
89
+ end
90
+
91
+ if Spree.version.to_f >= 3.6
92
+ scenario 'can update an existing vendor image' do
93
+ page.attach_file("vendor_image", Spree::Core::Engine.root + 'spec/fixtures' + 'thinking-cat.jpg')
94
+ expect { click_button 'Update' }.to change(Spree::VendorImage, :count).by(1)
95
+ expect(page).to have_text 'successfully updated!'
96
+ end
97
+ end
98
+
99
+ scenario 'shows validation error with blank name' do
100
+ fill_in 'vendor_name', with: ''
101
+ click_button 'Update'
102
+ expect(page).to have_text 'name can\'t be blank'
103
+ end
104
+
105
+ scenario 'does not show validation error with blank about_us' do
106
+ fill_in 'vendor_about_us', with: ''
107
+ click_button 'Update'
108
+ expect(page).not_to have_text 'about_us can\'t be blank'
109
+ end
110
+
111
+ scenario 'does not show validation error with blank contact_us' do
112
+ fill_in 'vendor_contact_us', with: ''
113
+ click_button 'Update'
114
+ expect(page).not_to have_text 'contact_us can\'t be blank'
115
+ end
116
+
117
+ scenario 'shows validation error with repeated name' do
118
+ create(:vendor, name: 'New vendor')
119
+
120
+ fill_in 'vendor_name', with: 'New vendor'
121
+ click_button 'Update'
122
+ expect(page).to have_text 'name has already been taken'
123
+ end
124
+ end
125
+ end
Binary file
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::VendorMailer, type: :mailer do
4
+ let(:store) { create(:store)}
5
+ let(:vendor) { Spree::Vendor.new(id: 1, name: 'Test vendor', state: 'active', notification_email: 'test-vendor@example.com') }
6
+ let(:other_vendor) { Spree::Vendor.new(id: 2, name: 'Other vendor', state: 'active', notification_email: 'other-vendor@example.com') }
7
+ let(:order) { create(:completed_order_with_totals, line_items_count: 5) }
8
+
9
+ context 'vendor notification email' do
10
+ before do
11
+ order.line_items.first.product.update(vendor: vendor)
12
+ order.line_items.last.product.update(vendor: other_vendor)
13
+ end
14
+
15
+ it 'is sent from current store email address' do
16
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
17
+ expect(notification_email.from).to have_content(Spree::Store.current.mail_from_address)
18
+ end
19
+
20
+ it 'is sent to vendors email address' do
21
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
22
+ expect(notification_email.to).to have_content(vendor.contact_us)
23
+ end
24
+
25
+ it 'subject contains order number' do
26
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
27
+ expect(notification_email.subject).to have_content(order.number)
28
+ end
29
+
30
+ it 'body contains vendors items' do
31
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
32
+ vendors_item = order.line_items.select { |line_item| line_item.product.vendor == vendor }.first
33
+ expect(notification_email.body.parts.first).to have_text(vendors_item.product.name)
34
+ expect(notification_email.body.parts.last).to have_text(vendors_item.product.name)
35
+ end
36
+
37
+ it 'body does not contain other vendors items' do
38
+ notification_email = Spree::VendorMailer.vendor_notification_email(order.id, vendor.id)
39
+ other_vendors_item = order.line_items.select { |line_item| line_item.product.vendor != vendor }.first
40
+ expect(notification_email.body.parts.first).not_to have_text(other_vendors_item.product.name)
41
+ expect(notification_email.body.parts.last).not_to have_text(other_vendors_item.product.name)
42
+ end
43
+ end
44
+
45
+ end