solidus_marketplace 0.1.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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +8 -0
- data/LICENSE +26 -0
- data/README.md +123 -0
- data/Rakefile +15 -0
- data/Versionfile +6 -0
- data/app/assets/javascripts/spree/backend/solidus_marketplace.js +5 -0
- data/app/assets/javascripts/spree/backend/solidus_marketplace_routes.js +1 -0
- data/app/assets/javascripts/spree/backend/suppliers_autocomplete.js +55 -0
- data/app/assets/javascripts/spree/frontend/solidus_marketplace.js +1 -0
- data/app/assets/stylesheets/spree/backend/solidus_marketplace.scss +22 -0
- data/app/assets/stylesheets/spree/frontend/solidus_marketplace.css +3 -0
- data/app/controllers/ckeditor/attachment_files_controller_decorator.rb +20 -0
- data/app/controllers/ckeditor/pictures_controller_decorator.rb +17 -0
- data/app/controllers/spree/admin/marketplace_settings_controller.rb +19 -0
- data/app/controllers/spree/admin/products_controller_decorator.rb +79 -0
- data/app/controllers/spree/admin/reports_controller_decorator.rb +68 -0
- data/app/controllers/spree/admin/shipments_controller.rb +47 -0
- data/app/controllers/spree/admin/stock_items_controller_decorator.rb +10 -0
- data/app/controllers/spree/admin/stock_locations_controller_decorator.rb +23 -0
- data/app/controllers/spree/admin/suppliers_controller.rb +54 -0
- data/app/controllers/spree/admin/users_controller_decorator.rb +34 -0
- data/app/controllers/spree/api/suppliers_controller.rb +16 -0
- data/app/controllers/spree/api/v1/stock_locations_controller_decorator.rb +18 -0
- data/app/controllers/spree/base_controller_decorator.rb +13 -0
- data/app/helpers/spree/api/api_helpers_decorator.rb +22 -0
- data/app/mailers/spree/marketplace_order_mailer.rb +13 -0
- data/app/mailers/spree/supplier_mailer.rb +12 -0
- data/app/models/ckeditor/asset_decorator.rb +5 -0
- data/app/models/spree.rb +5 -0
- data/app/models/spree/marketplace_configuration.rb +14 -0
- data/app/models/spree/order_decorator.rb +44 -0
- data/app/models/spree/payment_decorator.rb +7 -0
- data/app/models/spree/product_decorator.rb +52 -0
- data/app/models/spree/shipment_decorator.rb +40 -0
- data/app/models/spree/stock/splitter/marketplace.rb +47 -0
- data/app/models/spree/stock_location_decorator.rb +23 -0
- data/app/models/spree/supplier.rb +120 -0
- data/app/models/spree/supplier_ability.rb +35 -0
- data/app/models/spree/supplier_variant.rb +6 -0
- data/app/models/spree/user_decorator.rb +23 -0
- data/app/models/spree/variant_decorator.rb +24 -0
- data/app/overrides/spree/admin/menus.rb +15 -0
- data/app/overrides/spree/admin/products/_form/converted_admin_product_form_right.html.erb.deface +5 -0
- data/app/overrides/spree/admin/products/edit/override_rows.html.erb.deface +22 -0
- data/app/overrides/spree/admin/stock_locations/_form/add_supplier.html.erb.deface +12 -0
- data/app/views/spree/admin/marketplace_settings/edit.html.erb +21 -0
- data/app/views/spree/admin/orders/index.html.erb +187 -0
- data/app/views/spree/admin/products/_form.html.erb +198 -0
- data/app/views/spree/admin/reports/earnings.html.erb +34 -0
- data/app/views/spree/admin/shared/_marketplace_settings.html.erb +1 -0
- data/app/views/spree/admin/shared/_marketplace_tabs.html.erb +4 -0
- data/app/views/spree/admin/shipments/edit.html.erb +24 -0
- data/app/views/spree/admin/shipments/index.html.erb +93 -0
- data/app/views/spree/admin/suppliers/_form.html.erb +75 -0
- data/app/views/spree/admin/suppliers/edit.html.erb +22 -0
- data/app/views/spree/admin/suppliers/index.html.erb +68 -0
- data/app/views/spree/admin/suppliers/new.html.erb +17 -0
- data/app/views/spree/api/shared/_pagination.json.jbuilder +5 -0
- data/app/views/spree/api/suppliers/_supplier.json.jbuilder +1 -0
- data/app/views/spree/api/suppliers/index.json.jbuilder +4 -0
- data/app/views/spree/marketplace_order_mailer/supplier_order.html.erb +119 -0
- data/app/views/spree/shared/unauthorized.erb +1 -0
- data/app/views/spree/supplier_mailer/welcome.html.erb +53 -0
- data/config/locales/en.yml +107 -0
- data/config/locales/es.yml +133 -0
- data/config/routes.rb +24 -0
- data/db/default/spree/marketplace_roles.rb +14 -0
- data/db/migrate/20121006073854_create_suppliers.rb +20 -0
- data/db/migrate/20130216070944_product_belongs_to_supplier.rb +6 -0
- data/db/migrate/20130405005502_stock_locations_belongs_to_supplier.rb +6 -0
- data/db/migrate/20130405011127_user_belongs_to_supplier.rb +6 -0
- data/db/migrate/20130428063053_add_balanced_token_to_suppliers.rb +7 -0
- data/db/migrate/20130510181443_add_supplier_id_to_ckeditor_assets.rb +8 -0
- data/db/migrate/20130606220913_add_permalink_to_suppliers.rb +6 -0
- data/db/migrate/20140323170638_add_supplier_commission_to_shipments.rb +5 -0
- data/db/migrate/20140416184616_migrate_payment_and_commission.rb +7 -0
- data/db/migrate/20140529041325_create_spree_supplier_variants.rb +15 -0
- data/db/migrate/20171027180043_add_paypal_email_to_suppliers.rb +5 -0
- data/db/seeds.rb +8 -0
- data/lib/generators/solidus_marketplace/install/install_generator.rb +36 -0
- data/lib/solidus_marketplace.rb +6 -0
- data/lib/solidus_marketplace/engine.rb +53 -0
- data/lib/solidus_marketplace/factories.rb +107 -0
- data/lib/solidus_marketplace/version.rb +3 -0
- data/lib/spree/permitted_attributes_decorator.rb +18 -0
- data/lib/tasks/spree_sample.rake +72 -0
- data/log/awesome.log +1 -0
- data/script/rails +7 -0
- data/solidus_marketplace.gemspec +46 -0
- data/spec/features/admin/orders_spec.rb +11 -0
- data/spec/features/admin/products_spec.rb +25 -0
- data/spec/features/admin/return_authorizations_spec.rb +7 -0
- data/spec/features/admin/settings_spec.rb +33 -0
- data/spec/features/admin/shipments_spec.rb +80 -0
- data/spec/features/admin/stock_management_spec.rb +156 -0
- data/spec/features/admin/stock_spec.rb +98 -0
- data/spec/features/admin/suppliers_spec.rb +130 -0
- data/spec/models/spree/order_decorator_spec.rb +80 -0
- data/spec/models/spree/payment_decorator_spec.rb +7 -0
- data/spec/models/spree/product_decorator_spec.rb +56 -0
- data/spec/models/spree/shipment_decorator_spec.rb +48 -0
- data/spec/models/spree/stock/splitter/marketplace_spec.rb +62 -0
- data/spec/models/spree/stock_location_decorator_spec.rb +33 -0
- data/spec/models/spree/supplier_ability_spec.rb +182 -0
- data/spec/models/spree/supplier_spec.rb +123 -0
- data/spec/models/spree/supplier_variant_spec.rb +5 -0
- data/spec/models/spree/user_decorator_spec.rb +57 -0
- data/spec/models/spree/variant_decorator_spec.rb +7 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/support/ability_helpers.rb +11 -0
- data/spec/support/integration_helpers.rb +15 -0
- metadata +473 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
feature 'Admin - Suppliers', js: true do
|
|
4
|
+
|
|
5
|
+
before do
|
|
6
|
+
country = create(:country, name: "United States")
|
|
7
|
+
create(:state, name: "Vermont", country: country)
|
|
8
|
+
@supplier = create :supplier
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context 'as an MarketMaker (aka admin)' do
|
|
12
|
+
|
|
13
|
+
before do
|
|
14
|
+
login_user create(:admin_user)
|
|
15
|
+
visit spree.admin_path
|
|
16
|
+
within '[data-hook=admin_tabs]' do
|
|
17
|
+
click_link 'Suppliers'
|
|
18
|
+
end
|
|
19
|
+
expect(page).to have_content('Suppliers')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
xscenario 'should be able to create new supplier' do
|
|
23
|
+
click_link 'New Supplier'
|
|
24
|
+
check 'supplier_active'
|
|
25
|
+
fill_in 'supplier[name]', with: 'Test Supplier'
|
|
26
|
+
fill_in 'supplier[email]', with: 'spree@example.com'
|
|
27
|
+
fill_in 'supplier[url]', with: 'http://www.test.com'
|
|
28
|
+
fill_in 'supplier[commission_flat_rate]', with: '0'
|
|
29
|
+
fill_in 'supplier[commission_percentage]', with: '0'
|
|
30
|
+
fill_in 'supplier[address_attributes][firstname]', with: 'First'
|
|
31
|
+
fill_in 'supplier[address_attributes][lastname]', with: 'Last'
|
|
32
|
+
fill_in 'supplier[address_attributes][address1]', with: '1 Test Drive'
|
|
33
|
+
fill_in 'supplier[address_attributes][city]', with: 'Test City'
|
|
34
|
+
fill_in 'supplier[address_attributes][zipcode]', with: '55555'
|
|
35
|
+
select2 'United States of America', from: 'Country'
|
|
36
|
+
select2 'Vermont', from: 'State'
|
|
37
|
+
fill_in 'supplier[address_attributes][phone]', with: '555-555-5555'
|
|
38
|
+
click_button 'Create'
|
|
39
|
+
expect(page).to have_content('Supplier "Test Supplier" has been successfully created!')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
xscenario 'should be able to delete supplier' do
|
|
43
|
+
click_icon 'delete'
|
|
44
|
+
page.driver.browser.switch_to.alert.accept
|
|
45
|
+
within 'table' do
|
|
46
|
+
expect(page).to_not have_content(@supplier.name)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
xscenario 'should be able to edit supplier' do
|
|
51
|
+
click_icon 'edit'
|
|
52
|
+
check 'supplier_active'
|
|
53
|
+
fill_in 'supplier[name]', with: 'Test Supplier'
|
|
54
|
+
fill_in 'supplier[email]', with: 'spree@example.com'
|
|
55
|
+
fill_in 'supplier[url]', with: 'http://www.test.com'
|
|
56
|
+
fill_in 'supplier[commission_flat_rate]', with: '0'
|
|
57
|
+
fill_in 'supplier[commission_percentage]', with: '0'
|
|
58
|
+
fill_in 'supplier[address_attributes][firstname]', with: 'First'
|
|
59
|
+
fill_in 'supplier[address_attributes][lastname]', with: 'Last'
|
|
60
|
+
fill_in 'supplier[address_attributes][address1]', with: '1 Test Drive'
|
|
61
|
+
fill_in 'supplier[address_attributes][city]', with: 'Test City'
|
|
62
|
+
fill_in 'supplier[address_attributes][zipcode]', with: '55555'
|
|
63
|
+
select2 'United States', from: 'Country'
|
|
64
|
+
select2 'Vermont', from: 'State'
|
|
65
|
+
fill_in 'supplier[address_attributes][phone]', with: '555-555-5555'
|
|
66
|
+
click_button 'Update'
|
|
67
|
+
expect(page).to have_content('Supplier "Test Supplier" has been successfully updated!')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'as a Supplier' do
|
|
73
|
+
before do
|
|
74
|
+
@user = create(:supplier_admin)
|
|
75
|
+
login_user @user
|
|
76
|
+
visit spree.edit_admin_supplier_path(@user.supplier)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
scenario 'should only see tabs they have access to' do
|
|
80
|
+
within '[data-hook=admin_tabs]' do
|
|
81
|
+
expect(page).to have_link('Products')
|
|
82
|
+
expect(page).to have_link('Stock')
|
|
83
|
+
expect(page).to have_link('Stock Locations')
|
|
84
|
+
expect(page).to have_link('Profile')
|
|
85
|
+
expect(page).to have_link('Orders')
|
|
86
|
+
expect(page).to have_link('Suppliers')
|
|
87
|
+
|
|
88
|
+
expect(page).to_not have_link('Overview')
|
|
89
|
+
expect(page).to_not have_link('Reports')
|
|
90
|
+
expect(page).to_not have_link('Configuration')
|
|
91
|
+
expect(page).to_not have_link('Promotions')
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
xscenario 'should be able to update supplier' do
|
|
96
|
+
fill_in 'supplier[name]', with: 'Test Supplier'
|
|
97
|
+
fill_in 'supplier[email]', with: @user.email
|
|
98
|
+
fill_in 'supplier[url]', with: 'http://www.test.com'
|
|
99
|
+
fill_in 'supplier[address_attributes][firstname]', with: 'First'
|
|
100
|
+
fill_in 'supplier[address_attributes][lastname]', with: 'Last'
|
|
101
|
+
fill_in 'supplier[address_attributes][address1]', with: '1 Test Drive'
|
|
102
|
+
fill_in 'supplier[address_attributes][city]', with: 'Test City'
|
|
103
|
+
fill_in 'supplier[address_attributes][zipcode]', with: '55555'
|
|
104
|
+
select2 'United States', from: 'Country'
|
|
105
|
+
select2 'Vermont', from: 'State'
|
|
106
|
+
fill_in 'supplier[address_attributes][phone]', with: '555-555-5555'
|
|
107
|
+
expect(page).to_not have_css('#supplier_active') # cannot edit active
|
|
108
|
+
expect(page).to_not have_css('#supplier_featured') # cannot edit featured
|
|
109
|
+
expect(page).to_not have_css('#s2id_supplier_user_ids') # cannot edit assigned users
|
|
110
|
+
expect(page).to_not have_css('#supplier_commission_flat_rate') # cannot edit flat rate commission
|
|
111
|
+
expect(page).to_not have_css('#supplier_commission_percentage') # cannot edit comission percentage
|
|
112
|
+
click_button 'Update'
|
|
113
|
+
expect(page).to have_content('Supplier "Test Supplier" has been successfully updated!')
|
|
114
|
+
expect(page.current_path).to eql(spree.edit_admin_supplier_path(@user.reload.supplier))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context 'as a User other than the suppliers' do
|
|
120
|
+
|
|
121
|
+
scenario 'should be unauthorized' do
|
|
122
|
+
supplier = create(:supplier)
|
|
123
|
+
login_user create(:user)
|
|
124
|
+
visit spree.edit_admin_supplier_path(supplier)
|
|
125
|
+
expect(page).to have_content('Authorization Failure')
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Order do
|
|
4
|
+
|
|
5
|
+
context '#finalize_with_supplier!' do
|
|
6
|
+
|
|
7
|
+
after do
|
|
8
|
+
SolidusMarketplace::Config[:send_supplier_email] = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
xit 'should deliver marketplace orders when SolidusMarketplace::Config[:send_supplier_email] == true' do
|
|
12
|
+
order = create(:order_with_totals, ship_address: create(:address))
|
|
13
|
+
order.line_items = [create(:line_item, variant: create(:variant_with_supplier)), create(:line_item, variant: create(:variant_with_supplier))]
|
|
14
|
+
order.create_proposed_shipments
|
|
15
|
+
|
|
16
|
+
order.shipments.each do |shipment|
|
|
17
|
+
expect(Spree::MarketplaceOrderMailer).to receive(:supplier_order).with(shipment.id).and_return(double(Mail, :deliver! => true))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
order.finalize!
|
|
21
|
+
order.reload
|
|
22
|
+
|
|
23
|
+
# Check orders are properly split.
|
|
24
|
+
expect(order.shipments.size).to eql(2)
|
|
25
|
+
order.shipments.each do |shipment|
|
|
26
|
+
expect(shipment.line_items.size).to eql(1)
|
|
27
|
+
expect(shipment.line_items.first.variant.suppliers.first).to eql(shipment.supplier)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'should NOT deliver marketplace orders when SolidusMarketplace::Config[:send_supplier_email] == false' do
|
|
32
|
+
SolidusMarketplace::Config[:send_supplier_email] = false
|
|
33
|
+
order = create(:order_with_totals, ship_address: create(:address))
|
|
34
|
+
order.line_items = [create(:line_item, variant: create(:variant_with_supplier)), create(:line_item, variant: create(:variant_with_supplier))]
|
|
35
|
+
order.create_proposed_shipments
|
|
36
|
+
|
|
37
|
+
order.shipments.each do |shipment|
|
|
38
|
+
expect(Spree::MarketplaceOrderMailer).not_to receive(:supplier_order).with(shipment.id)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
order.finalize!
|
|
42
|
+
order.reload
|
|
43
|
+
|
|
44
|
+
# Check orders are properly split.
|
|
45
|
+
expect(order.shipments.size).to eql(2)
|
|
46
|
+
order.shipments.each do |shipment|
|
|
47
|
+
expect(shipment.line_items.size).to eql(1)
|
|
48
|
+
expect(shipment.line_items.first.variant.suppliers.first).to eql(shipment.supplier)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "#supplier_total" do
|
|
55
|
+
context "when passed a supplier" do
|
|
56
|
+
it "returns the total commission earned for the order for a given supplier" do
|
|
57
|
+
order = create(:completed_order_from_supplier_with_totals, ship_address: create(:address))
|
|
58
|
+
supplier = order.suppliers.first
|
|
59
|
+
expected_supplier_total = Spree::Money.new(15.00)
|
|
60
|
+
expect(order.total).to eq(150.0)
|
|
61
|
+
expect(order.suppliers.count).to eq(1)
|
|
62
|
+
expect(order.supplier_total(supplier)).to eq(expected_supplier_total)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context "when passed a user associated with a supplier" do
|
|
67
|
+
it "returns the total commission earned for the order for a given supplier" do
|
|
68
|
+
order = create(:completed_order_from_supplier_with_totals, ship_address: create(:address))
|
|
69
|
+
supplier = order.suppliers.first
|
|
70
|
+
supplier_user = create(:supplier_user, supplier: supplier)
|
|
71
|
+
|
|
72
|
+
expected_supplier_total = Spree::Money.new(15.00)
|
|
73
|
+
expect(order.total).to eq(150.0)
|
|
74
|
+
expect(order.suppliers.count).to eq(1)
|
|
75
|
+
expect(order.supplier_total(supplier_user)).to eq(expected_supplier_total)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Product do
|
|
4
|
+
|
|
5
|
+
let(:product) { create :product }
|
|
6
|
+
let(:supplier1) { create(:supplier) }
|
|
7
|
+
let(:supplier2) { create(:supplier) }
|
|
8
|
+
|
|
9
|
+
describe "#add_supplier!" do
|
|
10
|
+
context "when passed a supplier" do
|
|
11
|
+
it "adds the supplier to product's list of supppliers" do
|
|
12
|
+
expect(product.suppliers).to be_empty
|
|
13
|
+
product.add_supplier!(supplier1)
|
|
14
|
+
expect(product.reload.suppliers).to include(supplier1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "when passed a supplier_id" do
|
|
19
|
+
it "adds the supplier to product's list of supppliers" do
|
|
20
|
+
expect(product.suppliers).to be_empty
|
|
21
|
+
product.add_supplier!(supplier2.id)
|
|
22
|
+
expect(product.reload.suppliers).to include(supplier2)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#add_suppliers!" do
|
|
28
|
+
it "adds multiple suppliers to the product's list of suppliers" do
|
|
29
|
+
expect(product.suppliers).to be_empty
|
|
30
|
+
product.add_suppliers!([supplier1.id, supplier2.id])
|
|
31
|
+
expect(product.reload.suppliers).to include(supplier1)
|
|
32
|
+
expect(product.reload.suppliers).to include(supplier2)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#remove_suppliers!" do
|
|
37
|
+
it "removes multiple suppliers from the product's list of suppliers" do
|
|
38
|
+
product.add_suppliers!([supplier1.id, supplier2.id])
|
|
39
|
+
expect(product.reload.suppliers).to include(supplier1)
|
|
40
|
+
expect(product.reload.suppliers).to include(supplier2)
|
|
41
|
+
|
|
42
|
+
product.remove_suppliers!([supplier1.id, supplier2.id])
|
|
43
|
+
expect(product.suppliers).to be_empty
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe '#supplier?' do
|
|
48
|
+
it "returns true if one or more suppliers are present" do
|
|
49
|
+
expect(product.supplier?).to eq false
|
|
50
|
+
product.add_supplier! create(:supplier)
|
|
51
|
+
expect(product.reload.supplier?).to eq true
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::Shipment do
|
|
4
|
+
|
|
5
|
+
describe 'Scopes' do
|
|
6
|
+
|
|
7
|
+
it '#by_supplier' do
|
|
8
|
+
supplier = create(:supplier)
|
|
9
|
+
stock_location_1 = supplier.stock_locations.first
|
|
10
|
+
stock_location_2 = create(:stock_location, supplier: supplier)
|
|
11
|
+
shipment_1 = create(:shipment)
|
|
12
|
+
shipment_2 = create(:shipment, stock_location: stock_location_1)
|
|
13
|
+
shipment_3 = create(:shipment)
|
|
14
|
+
shipment_4 = create(:shipment, stock_location: stock_location_2)
|
|
15
|
+
shipment_5 = create(:shipment)
|
|
16
|
+
shipment_6 = create(:shipment, stock_location: stock_location_1)
|
|
17
|
+
|
|
18
|
+
expect(subject.class.by_supplier(supplier.id)).to match_array([shipment_2, shipment_4, shipment_6])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#after_ship' do
|
|
24
|
+
|
|
25
|
+
it 'should capture payment if balance due' do
|
|
26
|
+
skip 'TODO make it so!'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
xit 'should track commission for shipment' do
|
|
30
|
+
supplier = create(:supplier_with_commission)
|
|
31
|
+
shipment = create(:shipment, stock_location: supplier.stock_locations.first)
|
|
32
|
+
|
|
33
|
+
expect(shipment.supplier_commission.to_f).to eql(0.0)
|
|
34
|
+
allow(shipment).to receive(:final_price_with_items).and_return(10.0)
|
|
35
|
+
shipment.send(:after_ship)
|
|
36
|
+
expect(shipment.reload.supplier_commission.to_f).to eql(1.5)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it '#final_price_with_items' do
|
|
42
|
+
shipment = build :shipment
|
|
43
|
+
allow(shipment).to receive(:item_cost).and_return(50.0)
|
|
44
|
+
allow(shipment).to receive(:final_price).and_return(5.5)
|
|
45
|
+
expect(shipment.final_price_with_items.to_f).to eql(55.5)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
module Stock
|
|
5
|
+
module Splitter
|
|
6
|
+
describe Marketplace do
|
|
7
|
+
|
|
8
|
+
let(:supplier_1) { create(:supplier) }
|
|
9
|
+
let(:supplier_2) { create(:supplier) }
|
|
10
|
+
|
|
11
|
+
let(:variant_1) {
|
|
12
|
+
v = create(:variant)
|
|
13
|
+
v.product.add_supplier! supplier_1
|
|
14
|
+
v.reload.supplier_variants.find_by_supplier_id(supplier_1.id).update_column(:cost, 5)
|
|
15
|
+
v.product.add_supplier! supplier_2
|
|
16
|
+
v.reload.supplier_variants.find_by_supplier_id(supplier_2.id).update_column(:cost, 6)
|
|
17
|
+
v
|
|
18
|
+
}
|
|
19
|
+
let(:variant_2) {
|
|
20
|
+
v = create(:variant)
|
|
21
|
+
v.product.add_supplier! supplier_1
|
|
22
|
+
v.reload.supplier_variants.find_by_supplier_id(supplier_1.id).update_column(:cost, 5)
|
|
23
|
+
v.product.add_supplier! supplier_2
|
|
24
|
+
v.reload.supplier_variants.find_by_supplier_id(supplier_2.id).update_column(:cost, 4)
|
|
25
|
+
v
|
|
26
|
+
}
|
|
27
|
+
let(:variant_3) {
|
|
28
|
+
v = create(:variant)
|
|
29
|
+
v.product.add_supplier! supplier_1
|
|
30
|
+
v.product.add_supplier! supplier_2
|
|
31
|
+
v.reload
|
|
32
|
+
}
|
|
33
|
+
let(:variant_4) { create(:variant) }
|
|
34
|
+
|
|
35
|
+
let(:variants){
|
|
36
|
+
[variant_1, variant_2, variant_3, variant_4]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let(:packer) { build(:stock_packer) }
|
|
40
|
+
|
|
41
|
+
subject { Marketplace.new(packer.stock_location) }
|
|
42
|
+
|
|
43
|
+
it 'splits packages for suppliers to ship' do
|
|
44
|
+
package = Package.new(packer.stock_location)
|
|
45
|
+
package = Package.new(packer.stock_location)
|
|
46
|
+
4.times { |i| package.add build(:inventory_unit, variant: variants[i]) }
|
|
47
|
+
|
|
48
|
+
packages = subject.split([package])
|
|
49
|
+
expect(packages.count).to eq 3
|
|
50
|
+
|
|
51
|
+
expect(packages[0].stock_location).to eq(packer.stock_location)
|
|
52
|
+
expect(packages[0].contents.count).to eq(1)
|
|
53
|
+
expect(packages[1].stock_location).to eq(supplier_1.stock_locations.first)
|
|
54
|
+
expect(packages[1].contents.count).to eq(2)
|
|
55
|
+
expect(packages[2].stock_location).to eq(supplier_2.stock_locations.first)
|
|
56
|
+
expect(packages[2].contents.count).to eq(1)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Spree::StockLocation do
|
|
4
|
+
|
|
5
|
+
it { should belong_to(:supplier) }
|
|
6
|
+
|
|
7
|
+
subject { create(:stock_location, backorderable_default: true) }
|
|
8
|
+
|
|
9
|
+
context "propagate variants" do
|
|
10
|
+
|
|
11
|
+
let(:variant) { build(:variant) }
|
|
12
|
+
let(:stock_item) { subject.propagate_variant(variant) }
|
|
13
|
+
|
|
14
|
+
context "passes backorderable default config" do
|
|
15
|
+
context "true" do
|
|
16
|
+
before { subject.backorderable_default = true }
|
|
17
|
+
xit { expect(stock_item.backorderable).to eq true }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "false" do
|
|
21
|
+
before { subject.backorderable_default = false }
|
|
22
|
+
xit { expect(stock_item.backorderable).to eq false }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'does not propagate for non supplier variants' do
|
|
27
|
+
before { subject.supplier_id = create(:supplier).id }
|
|
28
|
+
it { expect(stock_item).to be_nil }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'cancan/matchers'
|
|
3
|
+
require 'spree/testing_support/ability_helpers'
|
|
4
|
+
|
|
5
|
+
describe Spree::SupplierAbility do
|
|
6
|
+
|
|
7
|
+
let(:supplier) { create(:supplier) }
|
|
8
|
+
let(:supplier_admin_role) { build :role, name: "supplier_admin" }
|
|
9
|
+
let(:user) { create(:user, supplier: supplier) }
|
|
10
|
+
let(:ability) { Spree::SupplierAbility.new(user) }
|
|
11
|
+
let(:token) { nil }
|
|
12
|
+
|
|
13
|
+
before(:each) do
|
|
14
|
+
user.spree_roles << supplier_admin_role
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context 'for Dash' do
|
|
18
|
+
let(:resource) { Spree::Admin::RootController }
|
|
19
|
+
|
|
20
|
+
context 'requested by supplier' do
|
|
21
|
+
it_should_behave_like 'access denied'
|
|
22
|
+
it_should_behave_like 'no index allowed'
|
|
23
|
+
it_should_behave_like 'admin denied'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'for Product' do
|
|
28
|
+
let(:resource) { create(:product) }
|
|
29
|
+
|
|
30
|
+
before(:each) do
|
|
31
|
+
resource.add_supplier!(user.supplier)
|
|
32
|
+
resource.reload
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it_should_behave_like 'index allowed'
|
|
36
|
+
it_should_behave_like 'read and update access granted'
|
|
37
|
+
it_should_behave_like 'admin granted'
|
|
38
|
+
|
|
39
|
+
context 'requested by another suppliers user' do
|
|
40
|
+
let(:other_resource) {
|
|
41
|
+
product = create(:product)
|
|
42
|
+
product.add_supplier!(create(:supplier))
|
|
43
|
+
product
|
|
44
|
+
}
|
|
45
|
+
it { expect(ability).to_not be_able_to :read, other_resource }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'requested by suppliers user' do
|
|
49
|
+
let(:resource) {
|
|
50
|
+
product = create(:product)
|
|
51
|
+
product.add_supplier!(user.supplier)
|
|
52
|
+
product.reload
|
|
53
|
+
}
|
|
54
|
+
# it_should_behave_like 'access granted'
|
|
55
|
+
it { expect(ability).to be_able_to :read, resource }
|
|
56
|
+
it { expect(ability).to be_able_to :stock, resource }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'for Shipment' do
|
|
61
|
+
context 'requested by another suppliers user' do
|
|
62
|
+
let(:resource) { Spree::Shipment.new({stock_location: create(:stock_location, supplier: create(:supplier))}) }
|
|
63
|
+
it_should_behave_like 'access denied'
|
|
64
|
+
it_should_behave_like 'no index allowed'
|
|
65
|
+
it_should_behave_like 'admin denied'
|
|
66
|
+
it { expect(ability).to_not be_able_to :ready, resource }
|
|
67
|
+
it { expect(ability).to_not be_able_to :ship, resource }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'requested by suppliers user' do
|
|
71
|
+
context 'when order is complete' do
|
|
72
|
+
let(:resource) {
|
|
73
|
+
order = create(:completed_order_from_supplier_with_totals)
|
|
74
|
+
order.stock_locations.first.update_attribute :supplier, user.supplier
|
|
75
|
+
Spree::Shipment.new({order: order, stock_location: order.stock_locations.first })
|
|
76
|
+
}
|
|
77
|
+
it_should_behave_like 'read only'
|
|
78
|
+
it_should_behave_like 'index allowed'
|
|
79
|
+
it_should_behave_like 'admin granted'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'when order is incomplete' do
|
|
83
|
+
let(:resource) { Spree::Shipment.new({stock_location: create(:stock_location, supplier: user.supplier)}) }
|
|
84
|
+
it_should_behave_like 'access denied'
|
|
85
|
+
it { expect(ability).to_not be_able_to :ready, resource }
|
|
86
|
+
it { expect(ability).to_not be_able_to :ship, resource }
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context 'for StockItem' do
|
|
92
|
+
let(:resource) { Spree::StockItem }
|
|
93
|
+
|
|
94
|
+
it_should_behave_like 'index allowed'
|
|
95
|
+
it_should_behave_like 'admin granted'
|
|
96
|
+
|
|
97
|
+
context 'requested by another suppliers user' do
|
|
98
|
+
let(:resource) {
|
|
99
|
+
supplier = create(:supplier)
|
|
100
|
+
variant = create(:product).master
|
|
101
|
+
variant.product.add_supplier! supplier
|
|
102
|
+
supplier.stock_locations.first.stock_items.first
|
|
103
|
+
}
|
|
104
|
+
it_should_behave_like 'access denied'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'requested by suppliers user' do
|
|
108
|
+
let(:resource) {
|
|
109
|
+
variant = create(:product).master
|
|
110
|
+
variant.product.add_supplier! user.supplier
|
|
111
|
+
user.supplier.stock_locations.first.stock_items.first
|
|
112
|
+
}
|
|
113
|
+
it_should_behave_like 'access granted'
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'for StockLocation' do
|
|
118
|
+
context 'requsted by another suppliers user' do
|
|
119
|
+
let(:resource) {
|
|
120
|
+
supplier = create(:supplier)
|
|
121
|
+
variant = create(:product).master
|
|
122
|
+
variant.product.add_supplier! supplier
|
|
123
|
+
supplier.stock_locations.first
|
|
124
|
+
}
|
|
125
|
+
it_should_behave_like 'access denied'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
context 'requested by suppliers user' do
|
|
129
|
+
let(:resource) {
|
|
130
|
+
variant = create(:product).master
|
|
131
|
+
variant.product.add_supplier! user.supplier
|
|
132
|
+
user.supplier.stock_locations.first
|
|
133
|
+
}
|
|
134
|
+
it_should_behave_like 'access granted'
|
|
135
|
+
it_should_behave_like 'admin granted'
|
|
136
|
+
it_should_behave_like 'index allowed'
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context 'for StockMovement' do
|
|
141
|
+
let(:resource) { Spree::StockMovement }
|
|
142
|
+
|
|
143
|
+
it_should_behave_like 'index allowed'
|
|
144
|
+
it_should_behave_like 'admin granted'
|
|
145
|
+
|
|
146
|
+
context 'requested by another suppliers user' do
|
|
147
|
+
let(:resource) {
|
|
148
|
+
supplier = create(:supplier)
|
|
149
|
+
variant = create(:product).master
|
|
150
|
+
variant.product.add_supplier! supplier
|
|
151
|
+
Spree::StockMovement.new({ stock_item: supplier.stock_locations.first.stock_items.first })
|
|
152
|
+
}
|
|
153
|
+
it_should_behave_like 'admin denied'
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
context 'requested by suppliers user' do
|
|
157
|
+
let(:resource) {
|
|
158
|
+
variant = create(:product).master
|
|
159
|
+
variant.product.add_supplier! user.supplier
|
|
160
|
+
Spree::StockMovement.new({ stock_item: user.supplier.stock_locations.first.stock_items.first })
|
|
161
|
+
}
|
|
162
|
+
it_should_behave_like 'access granted'
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context 'for Supplier' do
|
|
167
|
+
context 'requested by any user' do
|
|
168
|
+
let(:ability) { Spree::SupplierAbility.new(create(:user)) }
|
|
169
|
+
let(:resource) { Spree::Supplier }
|
|
170
|
+
|
|
171
|
+
it_should_behave_like 'admin denied'
|
|
172
|
+
it_should_behave_like 'access denied'
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context 'requested by suppliers user' do
|
|
176
|
+
let(:resource) { user.supplier }
|
|
177
|
+
it_should_behave_like 'admin granted'
|
|
178
|
+
it_should_behave_like 'read and update access granted'
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
end
|