mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Add ability to change distributor based on whether products in the cart are available
This commit is contained in:
@@ -35,7 +35,7 @@ Spree::OrdersController.class_eval do
|
||||
|
||||
order = current_order(true)
|
||||
|
||||
if order.can_change_distributor?
|
||||
if order.can_change_to_distributor?(distributor)
|
||||
order.distributor = distributor
|
||||
order.save!
|
||||
end
|
||||
|
||||
@@ -2,17 +2,43 @@ Spree::Order.class_eval do
|
||||
belongs_to :distributor, :class_name => 'Enterprise'
|
||||
|
||||
before_validation :shipping_address_from_distributor
|
||||
validate :can_change_distributor?, :if => :distributor_id_changed?
|
||||
validate :change_distributor_validation, :if => :distributor_id_changed?
|
||||
attr_accessible :distributor_id
|
||||
|
||||
after_create :set_default_shipping_method
|
||||
|
||||
def change_distributor_validation
|
||||
# Check that the line_items in the current order are available from a newly selected distributor
|
||||
errors.add(:distributor_id, "The products in your cart are not available from '" + distributor.name + "'") unless can_change_to_distributor? distributor
|
||||
end
|
||||
|
||||
def can_change_to_distributor? distributor
|
||||
# Distributor may not be changed once an item has been added to the cart/order, unless all items are available from the specified distributor
|
||||
line_items.empty? || (available_distributors || []).include?(distributor)
|
||||
end
|
||||
|
||||
def can_change_distributor?
|
||||
# Distributor may not be changed once an item has been added to the cart/order
|
||||
line_items.empty?
|
||||
end
|
||||
|
||||
def available_distributors
|
||||
# Find all other enterprises which offer all product variants contained within the current order
|
||||
distributors_with_all_variants = get_distributors_with_all_variants(Enterprise.all)
|
||||
end
|
||||
|
||||
def get_distributors_with_all_variants(enterprises)
|
||||
variants_in_current_order = line_items.map{ |li| li.variant }
|
||||
distributors_with_all_variants = []
|
||||
enterprises.each do |e|
|
||||
variants_available_from_enterprise = ProductDistribution.find_all_by_distributor_id( e.id ).map{ |pd| pd.product.variants }.flatten
|
||||
distributors_with_all_variants << e if ( variants_in_current_order - variants_available_from_enterprise ).empty?
|
||||
end
|
||||
distributors_with_all_variants
|
||||
end
|
||||
|
||||
def distributor=(distributor)
|
||||
raise "You cannot change the distributor of an order with products" unless distributor == self.distributor || can_change_distributor?
|
||||
raise "You cannot change the distributor of an order with products" unless distributor == self.distributor || can_change_to_distributor?(distributor)
|
||||
super(distributor)
|
||||
end
|
||||
|
||||
@@ -21,9 +47,9 @@ Spree::Order.class_eval do
|
||||
save!
|
||||
end
|
||||
|
||||
|
||||
def can_add_product_to_cart?(product)
|
||||
can_change_distributor? || product.distributors.include?(distributor)
|
||||
# Products may be added if no line items are currently in the cart or if the product is available from the current distributor
|
||||
line_items.empty? || product.distributors.include?(distributor)
|
||||
end
|
||||
|
||||
def set_variant_attributes(variant, attributes)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
Deface::Override.new(:virtual_path => "spree/checkout/_address",
|
||||
:replace => "[data-hook='shipping_fieldset_wrapper']",
|
||||
:partial => "spree/checkout/distributor",
|
||||
:name => "delivery_address")
|
||||
:replace => "[data-hook='shipping_fieldset_wrapper']",
|
||||
:partial => "spree/checkout/distributor",
|
||||
:name => "replace_shipping_form")
|
||||
|
||||
Deface::Override.new(:virtual_path => "spree/checkout/edit",
|
||||
:insert_after => "[data-hook='checkout_summary_box']",
|
||||
:partial => "spree/checkout/other_available_distributors",
|
||||
:name => "other_available_distributors")
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="columns omega four" style="padding-top: 30px">
|
||||
<%
|
||||
other_available_distributors = @order.available_distributors
|
||||
other_available_distributors.delete(@order.distributor)
|
||||
unless other_available_distributors.empty?
|
||||
%>
|
||||
<%= form_for(@order) do |f| %>
|
||||
<%= f.label :distributor_label, "Alternative distributors for this order:" %>
|
||||
<% available_distributors_array = other_available_distributors.map { |distributor| [distributor.name + ": " + distributor.address.address1 + ", " + distributor.address.city, distributor.id.to_i] } %>
|
||||
<%= f.select :distributor_id, options_for_select( available_distributors_array ) %>
|
||||
<%= f.submit "Change Distributor" %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
No alternative distributors available.
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -11,7 +11,7 @@
|
||||
- order = current_order(false)
|
||||
- @distributors.each do |distributor|
|
||||
%li.nowrap
|
||||
- if order.nil? || order.can_change_distributor?
|
||||
- if order.nil? || order.can_change_to_distributor?(distributor)
|
||||
= link_to distributor.name, select_distributor_order_path(distributor)
|
||||
- elsif order.distributor == distributor
|
||||
= link_to distributor.name, [main_app, distributor]
|
||||
|
||||
@@ -26,7 +26,7 @@ describe Spree::Order do
|
||||
subject.can_change_distributor?.should be_false
|
||||
end
|
||||
|
||||
it "raises an exception if distributor is changed without permission" do
|
||||
it "checks that distributor is available when changing, and raises an exception if distributor is changed without permission" do
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product, :distributors => [d])
|
||||
subject.distributor = d
|
||||
@@ -34,6 +34,7 @@ describe Spree::Order do
|
||||
|
||||
subject.add_variant(p.master, 1)
|
||||
subject.can_change_distributor?.should be_false
|
||||
subject.should_receive(:available_distributors)
|
||||
|
||||
expect do
|
||||
subject.distributor = nil
|
||||
@@ -79,4 +80,63 @@ describe Spree::Order do
|
||||
li = Spree::LineItem.last
|
||||
li.max_quantity.should == 3
|
||||
end
|
||||
|
||||
context "finding alternative distributors" do
|
||||
it "checks that variants are available" do
|
||||
distributors_with_all_variants = double(:distributors_with_all_variants)
|
||||
subject.should_receive(:get_distributors_with_all_variants).with(Enterprise.all)
|
||||
subject.available_distributors
|
||||
end
|
||||
|
||||
context "finding distributors which have the same variants" do
|
||||
before(:each) do
|
||||
@enterprise1 = FactoryGirl.create(:enterprise, id: 1)
|
||||
subject.distributor = @enterprise1
|
||||
@product1 = FactoryGirl.create(:product)
|
||||
@product2 = FactoryGirl.create(:product)
|
||||
@product3 = FactoryGirl.create(:product)
|
||||
variant11 = FactoryGirl.create(:variant, product: @product1)
|
||||
variant12 = FactoryGirl.create(:variant, product: @product1)
|
||||
variant21 = FactoryGirl.create(:variant, product: @product2)
|
||||
variant31 = FactoryGirl.create(:variant, product: @product3)
|
||||
variant32 = FactoryGirl.create(:variant, product: @product3)
|
||||
|
||||
# Product Distributions
|
||||
# Enterprise 1 sells product 1 and product 3
|
||||
FactoryGirl.create(:product_distribution, product: @product1, distributor: @enterprise1)
|
||||
FactoryGirl.create(:product_distribution, product: @product3, distributor: @enterprise1)
|
||||
|
||||
# Build the current order
|
||||
line_item1 = FactoryGirl.create(:line_item, order: subject, variant: variant11)
|
||||
line_item2 = FactoryGirl.create(:line_item, order: subject, variant: variant12)
|
||||
line_item3 = FactoryGirl.create(:line_item, order: subject, variant: variant31)
|
||||
subject.line_items = [line_item1,line_item2,line_item3]
|
||||
end
|
||||
|
||||
it "matches the distributor enterprise of the current order" do
|
||||
subject.get_distributors_with_all_variants([@enterprise1]).should == [@enterprise1]
|
||||
end
|
||||
|
||||
it "does not match enterprises with no products available" do
|
||||
test_enterprise = FactoryGirl.create(:enterprise, id: 2)
|
||||
subject.get_distributors_with_all_variants([@enterprise1, test_enterprise]).should_not include test_enterprise
|
||||
end
|
||||
|
||||
it "does not match enterprises with only some of the same variants in the current order available" do
|
||||
test_enterprise = FactoryGirl.create(:enterprise, id: 2)
|
||||
# Test Enterprise sells only product 1
|
||||
FactoryGirl.create(:product_distribution, product: @product1, distributor: test_enterprise)
|
||||
subject.get_distributors_with_all_variants([@enterprise1, test_enterprise]).should_not include test_enterprise
|
||||
end
|
||||
|
||||
it "matches enteprises which offer all products in the current order" do
|
||||
test_enterprise = FactoryGirl.create(:enterprise, id: 2)
|
||||
# Enterprise 3 Sells Products 1, 2 and 3
|
||||
FactoryGirl.create(:product_distribution, product: @product1, distributor: test_enterprise)
|
||||
FactoryGirl.create(:product_distribution, product: @product2, distributor: test_enterprise)
|
||||
FactoryGirl.create(:product_distribution, product: @product3, distributor: test_enterprise)
|
||||
subject.get_distributors_with_all_variants([@enterprise1, test_enterprise]).should include test_enterprise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user