From 661ce4e5976609b8929ac2a2d7b00f2541b18fb5 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Tue, 4 Jun 2013 10:26:13 +1000 Subject: [PATCH] Add to cart page does not allow the user to add a product from an order cycle that cannot supply the cart's products --- app/helpers/add_to_cart_helper.rb | 8 +- .../spree/products/_add_to_cart.html.haml | 5 +- ..._to_cart_order_cycle_unavailable.html.haml | 4 + .../distribution_change_validator.rb | 9 +- spec/features/consumer/add_to_cart_spec.rb | 82 +++++++++---------- .../distribution_change_validator_spec.rb | 44 +++++++++- 6 files changed, 101 insertions(+), 51 deletions(-) create mode 100644 app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml diff --git a/app/helpers/add_to_cart_helper.rb b/app/helpers/add_to_cart_helper.rb index 1f336033a4..c8e657470d 100644 --- a/app/helpers/add_to_cart_helper.rb +++ b/app/helpers/add_to_cart_helper.rb @@ -3,8 +3,12 @@ module AddToCartHelper !@product.has_stock? && !Spree::Config[:allow_backorders] end - def product_incompatible_with_current_order(order, product) - !DistributionChangeValidator.new(order).product_compatible_with_current_order(product) + def distributor_available_for?(order, product) + DistributionChangeValidator.new(order).distributor_available_for?(product) + end + + def order_cycle_available_for?(order, product) + DistributionChangeValidator.new(order).order_cycle_available_for?(product) end def available_distributors_for(order, product) diff --git a/app/views/spree/products/_add_to_cart.html.haml b/app/views/spree/products/_add_to_cart.html.haml index 309e688f54..abfe34383e 100644 --- a/app/views/spree/products/_add_to_cart.html.haml +++ b/app/views/spree/products/_add_to_cart.html.haml @@ -4,9 +4,12 @@ - if product_out_of_stock = content_tag('strong', t(:out_of_stock)) - - elsif product_incompatible_with_current_order(order, @product) + - elsif !distributor_available_for?(order, @product) = render 'add_to_cart_distributor_unavailable' + - elsif !order_cycle_available_for?(order, @product) + = render 'add_to_cart_order_cycle_unavailable' + - else = render 'add_to_cart_quantity_fields', product: @product diff --git a/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml b/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml new file mode 100644 index 0000000000..ba3a99dbbb --- /dev/null +++ b/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml @@ -0,0 +1,4 @@ +.error-distributor + Please complete your order from + = link_to current_order_cycle.name, root_path + before shopping in a different order cycle. diff --git a/lib/open_food_web/distribution_change_validator.rb b/lib/open_food_web/distribution_change_validator.rb index 3c8193c20e..2362877d1c 100644 --- a/lib/open_food_web/distribution_change_validator.rb +++ b/lib/open_food_web/distribution_change_validator.rb @@ -14,10 +14,14 @@ class DistributionChangeValidator @order.line_items.empty? || all_available_distributors.include?(distributor) end - def product_compatible_with_current_order(product) + def distributor_available_for?(product) @order.nil? || available_distributors_for(product).present? end + def order_cycle_available_for?(product) + @order.nil? || !product_requires_order_cycle(product) || available_order_cycles_for(product).present? + end + def available_distributors_for(product) distributors = Enterprise.distributing_product(product) @@ -38,6 +42,9 @@ class DistributionChangeValidator order_cycles end + def product_requires_order_cycle(product) + product.product_distributions.blank? + end def all_available_distributors @all_available_distributors ||= (available_distributors(Enterprise.all) || []) diff --git a/spec/features/consumer/add_to_cart_spec.rb b/spec/features/consumer/add_to_cart_spec.rb index 108c7b3b67..9540d10225 100644 --- a/spec/features/consumer/add_to_cart_spec.rb +++ b/spec/features/consumer/add_to_cart_spec.rb @@ -276,58 +276,54 @@ feature %q{ page.should have_selector 'h4 a', :text => p2.name end - end + it "when the only valid distributor differs from the chosen one, alerts the user and changes distributor on add to cart" do + # Given two products, one available at only one distributor + d1 = create(:distributor_enterprise) + d2 = create(:distributor_enterprise) + p1 = create(:product) + p2 = create(:product) + create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master]) + create(:simple_order_cycle, :distributors => [d2], :variants => [p1.master, p2.master]) - it "allows us to add two products from the same distributor" do - # Given two products, each at the same distributor - d = create(:distributor_enterprise) - p1 = create(:product) - p2 = create(:product) - create(:simple_order_cycle, :distributors => [d], :variants => [p1.master, p2.master]) + # When I add the first to my cart + visit spree.product_path p1 + select d1.name, from: 'distributor_id' + click_button 'Add To Cart' - # When I add the first to my cart - visit spree.product_path p1 - select d.name, :from => 'distributor_id' - click_button 'Add To Cart' + # And I go to add the second + visit spree.product_path p2 - # And I add the second - visit spree.product_path p2 - click_button 'Add To Cart' + # Then I should see a message offering to change distributor for my order + page.should have_content "Your distributor for this order will be changed to #{d2.name} if you add this product to your cart." - # Then both should be in my cart - visit spree.cart_path - page.should have_selector 'h4 a', :text => p1.name - page.should have_selector 'h4 a', :text => p2.name - end + # When I add the second to my cart + click_button 'Add To Cart' - it "offers to automatically change distributors when there is only one choice" do - # Given two products, one available at only one distributor - d1 = create(:distributor_enterprise) - d2 = create(:distributor_enterprise) - p1 = create(:product) - p2 = create(:product) - create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master]) - create(:simple_order_cycle, :distributors => [d2], :variants => [p1.master, p2.master]) + # Then my distributor should have changed + page.should have_selector "#current-distribution a", :text => d2.name + end - # p1 - available at both, select d1 - # p2 - available at the one not selected + it "does not allow the user to add a product from an order cycle that cannot supply the cart's products" do + # Given two products, each at a different order cycle + d = create(:distributor_enterprise) + p1 = create(:product) + p2 = create(:product) + 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 - visit spree.product_path p1 - select d1.name, from: 'distributor_id' - click_button 'Add To Cart' + # When I add one of them to my cart + visit spree.product_path p1 + select d.name, :from => 'distributor_id' + select oc1.name, :from => 'order_cycle_id' + click_button 'Add To Cart' - # And I go to add the second - visit spree.product_path p2 + # And I attempt to add the other + visit spree.product_path p2 - # Then I should see a message offering to change distributor for my order - page.should have_content "Your distributor for this order will be changed to #{d2.name} if you add this product to your cart." - - # When I add the second to my cart - click_button 'Add To Cart' - - # Then my distributor should have changed - page.should have_selector "#current-distribution a", :text => d2.name + # Then I should not be allowed to add the product + page.should_not have_selector "button#add-to-cart-button" + page.should have_content "Please complete your order from #{oc1.name} before shopping in a different order cycle." + end end end diff --git a/spec/lib/open_food_web/distribution_change_validator_spec.rb b/spec/lib/open_food_web/distribution_change_validator_spec.rb index 7bb2a95677..45517d2e89 100644 --- a/spec/lib/open_food_web/distribution_change_validator_spec.rb +++ b/spec/lib/open_food_web/distribution_change_validator_spec.rb @@ -126,20 +126,44 @@ describe DistributionChangeValidator do end end - describe "checking product compatibility with current order" do + describe "checking if a distributor is available for a product" do it "returns true when order is nil" do subject = DistributionChangeValidator.new(nil) - subject.product_compatible_with_current_order(product).should be_true + subject.distributor_available_for?(product).should be_true end it "returns true when there's an distributor that can cover the new product" do subject.stub(:available_distributors_for).and_return([1]) - subject.product_compatible_with_current_order(product).should be_true + subject.distributor_available_for?(product).should be_true end it "returns false when there's no distributor that can cover the new product" do subject.stub(:available_distributors_for).and_return([]) - subject.product_compatible_with_current_order(product).should be_false + subject.distributor_available_for?(product).should be_false + end + end + + describe "checking if an order cycle is available for a product" do + it "returns true when the order is nil" do + subject = DistributionChangeValidator.new(nil) + subject.order_cycle_available_for?(product).should be_true + end + + it "returns true when the product doesn't require an order cycle" do + subject.stub(:product_requires_order_cycle).and_return(false) + subject.order_cycle_available_for?(product).should be_true + end + + it "returns true when there's an order cycle that can cover the product" do + subject.stub(:product_requires_order_cycle).and_return(true) + subject.stub(:available_order_cycles_for).and_return([1]) + subject.order_cycle_available_for?(product).should be_true + end + + it "returns false otherwise" do + subject.stub(:product_requires_order_cycle).and_return(true) + subject.stub(:available_order_cycles_for).and_return([]) + subject.order_cycle_available_for?(product).should be_false end end @@ -194,4 +218,16 @@ describe DistributionChangeValidator do subject.available_order_cycles_for(product).should == [2] end end + + describe "determining if a product requires an order cycle" do + it "returns true when the product does not have any product distributions" do + product.stub(:product_distributions).and_return([]) + subject.product_requires_order_cycle(product).should be_true + end + + it "returns false otherwise" do + product.stub(:product_distributions).and_return([1]) + subject.product_requires_order_cycle(product).should be_false + end + end end