solidus_multi_domain 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.rspec +4 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +9 -0
  6. data/README.md +72 -0
  7. data/Rakefile +21 -0
  8. data/app/controllers/concerns/spree_multi_domain/create_line_item_support.rb +16 -0
  9. data/app/controllers/concerns/spree_multi_domain/show_product_support.rb +17 -0
  10. data/app/controllers/spree/admin/products_controller_decorator.rb +12 -0
  11. data/app/controllers/spree/admin/stores_controller.rb +24 -0
  12. data/app/controllers/spree/api/line_items_controller_decorator.rb +1 -0
  13. data/app/controllers/spree/api/orders_controller_decorator.rb +21 -0
  14. data/app/controllers/spree/api/products_controller_decorator.rb +1 -0
  15. data/app/controllers/spree/api/shipments_controller_decorator.rb +17 -0
  16. data/app/controllers/spree/home_controller_decorator.rb +7 -0
  17. data/app/controllers/spree/products_controller_decorator.rb +1 -0
  18. data/app/controllers/spree/taxons_controller_decorator.rb +10 -0
  19. data/app/helpers/spree/products_helper_decorator.rb +11 -0
  20. data/app/mailers/spree/carton_mailer_decorator.rb +13 -0
  21. data/app/mailers/spree/order_mailer.rb +35 -0
  22. data/app/models/spree/order_decorator.rb +8 -0
  23. data/app/models/spree/payment_method_decorator.rb +13 -0
  24. data/app/models/spree/product_decorator.rb +4 -0
  25. data/app/models/spree/promotion/rules/store.rb +30 -0
  26. data/app/models/spree/shipping_method_decorator.rb +18 -0
  27. data/app/models/spree/store_decorator.rb +25 -0
  28. data/app/models/spree/store_payment_method.rb +6 -0
  29. data/app/models/spree/store_shipping_method.rb +6 -0
  30. data/app/models/spree/taxon_decorator.rb +5 -0
  31. data/app/models/spree/taxonomy_decorator.rb +3 -0
  32. data/app/models/spree/tracker_decorator.rb +7 -0
  33. data/app/models/spree_multi_domain/line_item_decorator.rb +20 -0
  34. data/app/overrides/decorate_admin_configurations_index.rb +5 -0
  35. data/app/overrides/decorate_admin_products_form.rb +6 -0
  36. data/app/overrides/decorate_admin_products_index.rb +20 -0
  37. data/app/overrides/decorate_admin_trackers_form.rb +6 -0
  38. data/app/overrides/decorate_admin_trackers_index.rb +13 -0
  39. data/app/views/spree/admin/products/_index_headers.html.erb +1 -0
  40. data/app/views/spree/admin/products/_index_rows.html.erb +1 -0
  41. data/app/views/spree/admin/products/_index_search_fields.html.erb +4 -0
  42. data/app/views/spree/admin/products/_stores.html.erb +8 -0
  43. data/app/views/spree/admin/promotions/rules/_store.html.erb +8 -0
  44. data/app/views/spree/admin/stores/_form.html.erb +90 -0
  45. data/app/views/spree/admin/stores/edit.html.erb +29 -0
  46. data/app/views/spree/admin/stores/index.html.erb +43 -0
  47. data/app/views/spree/admin/stores/new.html.erb +29 -0
  48. data/app/views/spree/admin/taxonomies/_form.html.erb +12 -0
  49. data/app/views/spree/admin/trackers/_index_rows.html.erb +1 -0
  50. data/app/views/spree/admin/trackers/_store.html.erb +6 -0
  51. data/app/views/spree/shared/_google_analytics.html.erb +39 -0
  52. data/bin/rails +7 -0
  53. data/circle.yml +6 -0
  54. data/config/locales/en.yml +26 -0
  55. data/config/locales/fr.yml +9 -0
  56. data/config/locales/pl.yml +10 -0
  57. data/config/locales/ru.yml +9 -0
  58. data/config/routes.rb +5 -0
  59. data/db/migrate/20091202123245_add_order_store.rb +17 -0
  60. data/db/migrate/20100114020535_add_store_to_tracker.rb +25 -0
  61. data/db/migrate/20100227180338_create_products_stores.rb +13 -0
  62. data/db/migrate/20100616204303_store_id_for_taxonomies.rb +19 -0
  63. data/db/migrate/20110601125650_remove_datetime_columns_from_products_stores.rb +13 -0
  64. data/db/migrate/20110601145424_add_indexes_to_products_stores.rb +11 -0
  65. data/db/migrate/20120223183401_namespace.rb +9 -0
  66. data/db/migrate/20121210224018_add_store_payment_methods.rb +10 -0
  67. data/db/migrate/20130308084714_add_logo_to_stores.rb +13 -0
  68. data/db/migrate/20130325231147_add_store_shipping_methods.rb +14 -0
  69. data/db/migrate/20130412212659_add_spree_promotion_rules_stores.rb +8 -0
  70. data/db/migrate/20150304200122_add_indexes.rb +6 -0
  71. data/lib/assets/javascripts/spree/backend/solidus_multi_domain.js +1 -0
  72. data/lib/assets/javascripts/spree/backend/store_picker.js +34 -0
  73. data/lib/assets/javascripts/spree/frontend/solidus_multi_domain.js +0 -0
  74. data/lib/assets/stylesheets/spree/frontend/solidus_multi_domain.css +5 -0
  75. data/lib/generators/spree_multi_domain/install/install_generator.rb +24 -0
  76. data/lib/solidus_multi_domain.rb +3 -0
  77. data/lib/spree/controller_helpers/order_decorator.rb +11 -0
  78. data/lib/spree/search/multi_domain.rb +19 -0
  79. data/lib/spree_multi_domain/engine.rb +65 -0
  80. data/lib/spree_multi_domain/multi_domain_helpers.rb +31 -0
  81. data/solidus_multi_domain.gemspec +31 -0
  82. data/spec/controllers/spree/admin/products_controller_spec.rb +39 -0
  83. data/spec/controllers/spree/admin/stores_controller_spec.rb +12 -0
  84. data/spec/controllers/spree/api/line_items_controller_spec.rb +35 -0
  85. data/spec/controllers/spree/api/orders_controller_spec.rb +44 -0
  86. data/spec/controllers/spree/api/products_controller_spec.rb +52 -0
  87. data/spec/controllers/spree/api/shipments_controller_spec.rb +63 -0
  88. data/spec/controllers/spree/products_controller_spec.rb +49 -0
  89. data/spec/helpers/products_helper_decorator_spec.rb +22 -0
  90. data/spec/mailers/carton_mailer_spec.rb +41 -0
  91. data/spec/models/spree/line_item_spec.rb +39 -0
  92. data/spec/models/spree/order_spec.rb +18 -0
  93. data/spec/models/spree/payment_method_spec.rb +33 -0
  94. data/spec/models/spree/product_spec.rb +18 -0
  95. data/spec/models/spree/shipping_method_decorator_spec.rb +27 -0
  96. data/spec/models/spree/store_spec.rb +42 -0
  97. data/spec/models/spree/taxon_decorator_spec.rb +30 -0
  98. data/spec/models/spree/tracker_spec.rb +19 -0
  99. data/spec/requests/global_controller_helpers_spec.rb +65 -0
  100. data/spec/requests/template_renderer_spec.rb +25 -0
  101. data/spec/spec_helper.rb +33 -0
  102. data/spec/support/factory_overrides.rb +10 -0
  103. metadata +278 -0
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.platform = Gem::Platform::RUBY
5
+ s.name = "solidus_multi_domain"
6
+ s.version = "1.0.0"
7
+ s.summary = "Adds multiple site support to Solidus"
8
+ s.description = "Multiple Solidus stores on different domains - single unified backed for processing orders."
9
+ s.required_ruby_version = ">= 2.1"
10
+
11
+ s.author = "Solidus Team"
12
+ s.email = "contact@solidus.io"
13
+ s.homepage = "https://solidus.io"
14
+ s.license = %q{BSD-3}
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.require_path = "lib"
19
+ s.requirements << "none"
20
+
21
+ s.add_dependency "solidus", [">= 1.0.0.pre", "< 2"]
22
+
23
+ s.add_development_dependency "rspec-rails", "~> 3.2"
24
+ s.add_development_dependency "simplecov"
25
+ s.add_development_dependency "sqlite3"
26
+ s.add_development_dependency "sass-rails", "~> 4.0.2"
27
+ s.add_development_dependency "coffee-rails", "~> 4.0.0"
28
+ s.add_development_dependency "factory_girl", "~> 4.5.0"
29
+ s.add_development_dependency "capybara", "~> 2.4"
30
+ s.add_development_dependency "ffaker"
31
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Admin::ProductsController do
4
+ stub_authorization!
5
+
6
+ describe "on :index" do
7
+ it "renders index" do
8
+ spree_get :index
9
+ expect(response).to be_success
10
+ end
11
+ end
12
+
13
+ describe "on a PUT to :update" do
14
+ before(:each) do
15
+ @product = FactoryGirl.create(:product)
16
+ @store = FactoryGirl.create(:store)
17
+ end
18
+
19
+ describe "when no stores are selected" do
20
+ it "clears stores if they previously existed" do
21
+ @product.stores << @store
22
+
23
+ spree_put :update, :id => @product.to_param,
24
+ :product => {:name => @product.name}, update_store_ids: 'true'
25
+
26
+ expect(@product.reload.store_ids).to be_empty
27
+ end
28
+ end
29
+
30
+ describe "when a store is selected" do
31
+ it "clears stores" do
32
+ spree_put :update, :id => @product.to_param,
33
+ :product => {:name => @product.name, :store_ids => [@store.id]}, update_store_ids: 'true'
34
+
35
+ expect(@product.reload.store_ids).to eq [@store.id]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Admin::StoresController do
4
+ stub_authorization!
5
+
6
+ describe "on :index" do
7
+ it "renders index" do
8
+ spree_get :index
9
+ expect(response).to be_success
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Api::LineItemsController do
4
+
5
+ before(:each) do
6
+ stub_authentication!
7
+ end
8
+
9
+ describe "POST create" do
10
+ let(:user) { create(:user) }
11
+ let(:current_api_user) { user }
12
+ let(:order) { create(:order, user: user) }
13
+ let(:line_item) { build(:line_item, order: order) }
14
+
15
+ subject { spree_post :create, line_item: line_item, order_id: line_item.order.number }
16
+
17
+ context "A SpreeMultiDomain::LineItemDecorator::ProductDoesNotBelongToStoreError is raised" do
18
+ before(:each) do
19
+ def controller.create
20
+ raise SpreeMultiDomain::LineItemDecorator::ProductDoesNotBelongToStoreError
21
+ end
22
+ end
23
+
24
+ it "sets the correct status" do
25
+ subject
26
+ expect(response.status).to eq 422
27
+ end
28
+
29
+ it "contains the correct error message" do
30
+ subject
31
+ expect(JSON.parse(response.body)["message"]).to eq "Products from different stores may not be added to this order."
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Api::OrdersController do
4
+ let!(:user) { FactoryGirl.create(:user) }
5
+ let!(:store1) { FactoryGirl.create(:store) }
6
+ let!(:store2) { FactoryGirl.create(:store) }
7
+
8
+ before(:each) do
9
+ controller.stub(current_api_user: user)
10
+ end
11
+
12
+ describe '#mine' do
13
+ it 'should return only orders from the correct store' do
14
+ FactoryGirl.create(:order, store: store1, user: user)
15
+ FactoryGirl.create(:order, store: store2, user: user)
16
+
17
+ controller.stub(current_store: store1)
18
+ controller.mine
19
+
20
+ expect(assigns(:orders).length).to eq(1)
21
+ expect(assigns(:orders).first.store_id).to eq(store1.id)
22
+
23
+ controller.stub(current_store: store2)
24
+ controller.mine
25
+
26
+ expect(assigns(:orders).length).to eq(1)
27
+ expect(assigns(:orders).first.store_id).to eq(store2.id)
28
+ end
29
+ end
30
+
31
+ describe '#find_current_order' do
32
+
33
+ it 'should return the latest incomplete order from the correct store' do
34
+ order1 = FactoryGirl.create(:order, store: store1, state: :cart, user: user)
35
+ order2 = FactoryGirl.create(:order, store: store2, state: :cart, user: user)
36
+
37
+ controller.stub(current_store: store1)
38
+ expect(controller.send(:find_current_order)).to eql(order1)
39
+
40
+ controller.stub(current_store: store2)
41
+ expect(controller.send(:find_current_order)).to eql(order2)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Api::ProductsController do
4
+
5
+ let!(:product) { FactoryGirl.create(:product) }
6
+
7
+ let(:user) { create(:user) }
8
+ before { allow(controller).to receive(:current_spree_user) { user } }
9
+
10
+ describe 'on :show to a product without any stores' do
11
+ let!(:store) { FactoryGirl.create(:store) }
12
+
13
+ it 'should return 404' do
14
+ spree_get :show, :id => product.to_param, format: :json
15
+
16
+ expect(response.response_code) == 404
17
+ end
18
+ end
19
+
20
+ # Regression test for #75
21
+ describe 'on :show to a product in the wrong store' do
22
+ let!(:store_1) { FactoryGirl.create(:store) }
23
+ let!(:store_2) { FactoryGirl.create(:store) }
24
+
25
+ before(:each) do
26
+ product.stores << store_1
27
+ end
28
+
29
+ it 'should return 404' do
30
+ controller.stub(:current_store => store_2)
31
+ spree_get :show, :id => product.to_param, format: :json
32
+
33
+ expect(response.response_code) == 404
34
+ end
35
+ end
36
+
37
+ describe 'on :show to a product w/ store' do
38
+ let!(:store) { FactoryGirl.create(:store) }
39
+
40
+ before(:each) do
41
+ product.stores << store
42
+ end
43
+
44
+ it 'should return 200' do
45
+ controller.stub(:current_store => store)
46
+ spree_get :show, :id => product.to_param, format: :json
47
+
48
+ expect(response.response_code) == 200
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Api::ShipmentsController do
4
+ describe '#mine' do
5
+ let!(:user) { FactoryGirl.create(:user) }
6
+ let!(:store1) { FactoryGirl.create(:store) }
7
+ let!(:store2) { FactoryGirl.create(:store) }
8
+ let!(:order_from_store1) { FactoryGirl.create(:order, store: store1, user: user) }
9
+ let!(:order_from_store2) { FactoryGirl.create(:order, store: store2, user: user) }
10
+
11
+ before(:each) do
12
+ controller.stub(current_api_user: user)
13
+ end
14
+
15
+ it 'should return only shipments from the correct store' do
16
+ FactoryGirl.create(:shipment, order: order_from_store1)
17
+ FactoryGirl.create(:shipment, order: order_from_store2)
18
+
19
+ controller.stub(current_store: store1)
20
+ controller.mine
21
+
22
+ expect(assigns(:shipments).length).to eq(1)
23
+ expect(assigns(:shipments).first.order.store_id).to eq(store1.id)
24
+
25
+ controller.stub(current_store: store2)
26
+ controller.mine
27
+
28
+ expect(assigns(:shipments).length).to eq(1)
29
+ expect(assigns(:shipments).first.order.store_id).to eq(store2.id)
30
+ end
31
+ end
32
+
33
+ describe "PUT add" do
34
+
35
+ let(:current_api_user) { create(:admin_user) }
36
+ let(:shipment) { create(:shipment) }
37
+ let(:variant) { create(:variant) }
38
+
39
+ subject { spree_put :add, variant_id: variant.id, id: shipment.number, quantity: 1 }
40
+
41
+ before(:each) do
42
+ stub_authentication!
43
+ end
44
+
45
+ context "A SpreeMultiDomain::LineItemDecorator::ProductDoesNotBelongToStoreError is raised" do
46
+ before(:each) do
47
+ def controller.add
48
+ raise SpreeMultiDomain::LineItemDecorator::ProductDoesNotBelongToStoreError
49
+ end
50
+ end
51
+
52
+ it "sets the correct status" do
53
+ subject
54
+ expect(response.status).to eq 422
55
+ end
56
+
57
+ it "contains the correct error message" do
58
+ subject
59
+ expect(JSON.parse(response.body)["message"]).to eq "Products from different stores may not be added to this order."
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::ProductsController do
4
+
5
+ let!(:product) { FactoryGirl.create(:product) }
6
+
7
+ describe 'on :show to a product without any stores' do
8
+ let!(:store) { FactoryGirl.create(:store) }
9
+
10
+ it 'returns 404' do
11
+ spree_get :show, :id => product.to_param
12
+
13
+ expect(response.response_code).to eq 404
14
+ end
15
+ end
16
+
17
+ # Regression test for #75
18
+ describe 'on :show to a product in the wrong store' do
19
+ let!(:store_1) { FactoryGirl.create(:store) }
20
+ let!(:store_2) { FactoryGirl.create(:store) }
21
+
22
+ before(:each) do
23
+ product.stores << store_1
24
+ end
25
+
26
+ it 'returns 404' do
27
+ allow(controller).to receive_messages(:current_store => store_2)
28
+ spree_get :show, :id => product.to_param
29
+
30
+ expect(response.response_code).to eq 404
31
+ end
32
+ end
33
+
34
+ describe 'on :show to a product w/ store' do
35
+ let!(:store) { FactoryGirl.create(:store) }
36
+
37
+ before(:each) do
38
+ product.stores << store
39
+ end
40
+
41
+ it 'returns 200' do
42
+ allow(controller).to receive_messages(:current_store => store)
43
+ spree_get :show, :id => product.to_param
44
+
45
+ expect(response.response_code).to eq 200
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe ProductsHelper do
5
+ before(:each) do
6
+ @store = FactoryGirl.create(:store)
7
+ @taxonomy = FactoryGirl.create(:taxonomy, :store => @store)
8
+ @taxonomy2 = FactoryGirl.create(:taxonomy)
9
+
10
+ allow(helper).to receive(:current_store) { @store }
11
+ end
12
+
13
+ describe "#get_taxonomies" do
14
+ it "only show taxonomies on current_store" do
15
+ taxonomies = helper.get_taxonomies
16
+
17
+ expect(taxonomies).to include(@taxonomy)
18
+ expect(taxonomies).to_not include(@taxonomy2)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::CartonMailer do
4
+ let(:mail) { Spree::CartonMailer.shipped_email(carton.id) }
5
+
6
+ let(:carton) do
7
+ FactoryGirl.create(:carton, inventory_units: order.inventory_units)
8
+ end
9
+
10
+ let(:order) do
11
+ FactoryGirl.create(:order_ready_to_ship, line_items_count: 1)
12
+ end
13
+
14
+ describe 'from address' do
15
+ subject do
16
+ mail.from
17
+ end
18
+
19
+ context 'the order does not have a store' do
20
+ let(:order) do
21
+ FactoryGirl.create(:order_ready_to_ship, line_items_count: 1, store: nil)
22
+ end
23
+
24
+ it { is_expected.to eq [Spree::Config[:mails_from]] }
25
+ end
26
+
27
+ context 'the order has a store' do
28
+ let(:order) do
29
+ FactoryGirl.create(
30
+ :order_ready_to_ship,
31
+ line_items_count: 1,
32
+ store: store,
33
+ )
34
+ end
35
+
36
+ let(:store) { FactoryGirl.create(:store, mail_from_address: 'store@example.com') }
37
+ it { is_expected.to eq ['store@example.com'] }
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::LineItem do
4
+ describe "before create" do
5
+
6
+ let(:order_store) { create(:store) }
7
+ let(:other_store) { create(:store) }
8
+ let(:order) { create(:order, store: order_store) }
9
+ let(:variant) { create(:variant, product: product) }
10
+ let(:line_item) { build(:line_item, order: order, product: product) }
11
+
12
+ subject { line_item.save! }
13
+
14
+ context "the order does not have a store" do
15
+ before(:each) { order.update_attributes(store_id: nil) }
16
+ let(:product) { create(:product, stores: [order_store])}
17
+
18
+ it 'does not raise an error' do
19
+ expect{ subject }.to_not raise_error
20
+ end
21
+ end
22
+
23
+ context "the line item's product does not belong to the order's store" do
24
+ let(:product) { create(:product, stores: [other_store]) }
25
+
26
+ it 'raises the correct error' do
27
+ expect{ subject }.to raise_error(SpreeMultiDomain::LineItemDecorator::ProductDoesNotBelongToStoreError)
28
+ end
29
+ end
30
+
31
+ context "the line item's product belongs to the order's store" do
32
+ let(:product) { create(:product, stores: [order_store])}
33
+
34
+ it "does not raise an error" do
35
+ expect{ subject }.to_not raise_error
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::Order do
4
+
5
+ before(:each) do
6
+ @store = FactoryGirl.create(:store)
7
+ @order = FactoryGirl.create(:order, :store => @store)
8
+
9
+ @order2 = FactoryGirl.create(:order)
10
+ end
11
+
12
+ it 'should correctly find products by store' do
13
+ by_store = Spree::Order.by_store(@store)
14
+
15
+ expect(by_store).to include(@order)
16
+ expect(by_store).to_not include(@order2)
17
+ end
18
+ end