Add to cart page does not allow the user to add a product from an order cycle that cannot supply the cart's products

This commit is contained in:
Rohan Mitchell
2013-06-04 10:26:13 +10:00
parent cb703c2a66
commit 661ce4e597
6 changed files with 101 additions and 51 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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.

View File

@@ -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) || [])

View File

@@ -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

View File

@@ -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