diff --git a/app/models/spree/order_populator_decorator.rb b/app/models/spree/order_populator_decorator.rb index 5afd6e1551..315a989e64 100644 --- a/app/models/spree/order_populator_decorator.rb +++ b/app/models/spree/order_populator_decorator.rb @@ -33,7 +33,7 @@ Spree::OrderPopulator.class_eval do if quantity > 0 if check_stock_levels(variant, quantity) && check_distribution_provided_for(variant) && - check_variant_available_under_distributor(variant) + check_variant_available_under_distribution(variant) @order.add_variant(variant, quantity, currency) end @@ -84,11 +84,11 @@ Spree::OrderPopulator.class_eval do distribution_provided end - def check_variant_available_under_distributor(variant) - if Enterprise.distributing_product(variant.product).include? @distributor + def check_variant_available_under_distribution(variant) + if DistributionChangeValidator.new(@order).variants_available_for_distribution(@distributor, @order_cycle).include? variant return true else - errors.add(:base, "That product is not available from the chosen distributor.") + errors.add(:base, "That product is not available from the chosen distributor or order cycle.") return false end end diff --git a/spec/controllers/orders_controller_spec.rb b/spec/controllers/orders_controller_spec.rb index a3dc31cc9e..50afbbb102 100644 --- a/spec/controllers/orders_controller_spec.rb +++ b/spec/controllers/orders_controller_spec.rb @@ -32,6 +32,61 @@ describe Spree::OrdersController do end + describe "adding a product to the cart with a distribution combination that can't service the existing cart" do + before do + @request.env["HTTP_REFERER"] = 'http://test.host/' + end + + it "produces an error when the distributor does not distribute the product" do + # Given two products with different distributors + d1 = create(:distributor_enterprise) + d2 = create(:distributor_enterprise) + p1 = create(:product, :price => 12.34) + p2 = create(:product, :price => 23.45) + oc1 = create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master]) + oc2 = create(:simple_order_cycle, :distributors => [d2], :variants => [p2.master]) + + # When I add the first to my cart + expect do + spree_post :populate, variants: {p1.master.id => 1}, distributor_id: d1.id, order_cycle_id: oc1.id + response.should redirect_to spree.cart_path + end.to change(self, :num_items_in_cart).by(1) + + # And I attempt to add the second, then the product should not be added to my cart + expect do + spree_post :populate, variants: {p2.master.id => 1}, distributor_id: d1.id, order_cycle_id: oc1.id + response.should redirect_to :back + end.to change(self, :num_items_in_cart).by(0) + + # And I should see an error + flash[:error].should == "That product is not available from the chosen distributor or order cycle." + end + + it "produces an error when the order cycle does not distribute the product" do + # Given two products with the same distributor but different order cycles + d = create(:distributor_enterprise) + p1 = create(:product, :price => 12.34) + p2 = create(:product, :price => 23.45) + oc1 = create(:simple_order_cycle, :distributors => [d], :variants => [p1.master]) + oc2 = create(:simple_order_cycle, :distributors => [d], :variants => [p2.master]) + + # When I add the first to my cart + expect do + spree_post :populate, variants: {p1.master.id => 1}, distributor_id: d.id, order_cycle_id: oc1.id + response.should redirect_to spree.cart_path + end.to change(self, :num_items_in_cart).by(1) + + # And I attempt to add the second, then the product should not be added to my cart + expect do + spree_post :populate, variants: {p2.master.id => 1}, distributor_id: d.id, order_cycle_id: oc1.id + response.should redirect_to :back + end.to change(self, :num_items_in_cart).by(0) + + # And I should see an error + flash[:error].should == "That product is not available from the chosen distributor or order cycle." + end + end + context "adding a group buy product to the cart" do it "sets a variant attribute for the max quantity" do distributor_product = create(:distributor_enterprise) @@ -46,4 +101,12 @@ describe Spree::OrdersController do end.to change(Spree::LineItem, :count).by(1) end end + + + private + + def num_items_in_cart + Spree::Order.last.andand.line_items.andand.count || 0 + end + end diff --git a/spec/models/order_populator_spec.rb b/spec/models/order_populator_spec.rb index d78f46c496..de64db40ab 100644 --- a/spec/models/order_populator_spec.rb +++ b/spec/models/order_populator_spec.rb @@ -70,7 +70,7 @@ module Spree op.should_receive(:check_stock_levels).with(variant, quantity).and_return(true) op.should_receive(:check_distribution_provided_for).with(variant).and_return(true) - op.should_receive(:check_variant_available_under_distributor).with(variant). + op.should_receive(:check_variant_available_under_distribution).with(variant). and_return(true) order.should_receive(:add_variant).with(variant, quantity, currency) @@ -120,20 +120,22 @@ module Spree let(:product) { double(:product) } let(:variant) { double(:variant, product: product) } - it "is available if the distributor is distributing this product" do - op.instance_eval { @distributor = 123 } - Enterprise.should_receive(:distributing_product).with(variant.product).and_return [123] - - op.send(:check_variant_available_under_distributor, variant).should be_true + it "delegates to DistributionChangeValidator, returning true when available" do + dcv = double(:dcv) + dcv.should_receive(:variants_available_for_distribution).with(123, 234).and_return([variant]) + DistributionChangeValidator.should_receive(:new).with(order).and_return(dcv) + op.instance_eval { @distributor = 123; @order_cycle = 234 } + op.send(:check_variant_available_under_distribution, variant).should be_true op.errors.should be_empty end - it "returns false and errors otherwise" do - op.instance_eval { @distributor = 123 } - Enterprise.should_receive(:distributing_product).with(variant.product).and_return [456] - - op.send(:check_variant_available_under_distributor, variant).should be_false - op.errors.to_a.should == ["That product is not available from the chosen distributor."] + it "delegates to DistributionChangeValidator, returning false and erroring otherwise" do + dcv = double(:dcv) + dcv.should_receive(:variants_available_for_distribution).with(123, 234).and_return([]) + DistributionChangeValidator.should_receive(:new).with(order).and_return(dcv) + op.instance_eval { @distributor = 123; @order_cycle = 234 } + op.send(:check_variant_available_under_distribution, variant).should be_false + op.errors.to_a.should == ["That product is not available from the chosen distributor or order cycle."] end end end