Support multiple orders when adding a product to a cart.

This commit is contained in:
Andrew Spinks
2013-08-14 09:43:23 +10:00
parent dd3aaccf9f
commit d5791657f3
3 changed files with 108 additions and 63 deletions

View File

@@ -2,21 +2,21 @@ class Cart < ActiveRecord::Base
has_many :orders, :class_name => 'Spree::Order'
belongs_to :user, :class_name => Spree.user_class
def add_variant variant_id, quantity, currency
def add_variant variant_id, quantity, distributor, order_cycle, currency
variant = Spree::Variant.find(variant_id)
variant.product.distributors.each do |distributor|
order = create_or_find_order_for_distributor distributor, currency
populator = Spree::OrderPopulator.new(order, currency)
populator.populate({ :variants => { variant_id => quantity }, :distributor_id => distributor.id, :order_cycle_id => nil })
end
order = create_or_find_order_for_distributor distributor, order_cycle, currency
populator = Spree::OrderPopulator.new(order, currency)
populator.populate({ :variants => { variant_id => quantity }, :distributor_id => distributor.id, :order_cycle_id => order_cycle })
end
def create_or_find_order_for_distributor distributor, currency
order_for_distributor = orders.find { |order| order.distributor == distributor }
def create_or_find_order_for_distributor distributor, order_cycle, currency
order_for_distributor = orders.find { |order| order.distributor == distributor && order.order_cycle == order_cycle }
unless order_for_distributor
order_for_distributor = Spree::Order.create(:currency => currency, :distributor => distributor)
order_for_distributor.distributor = distributor
order_for_distributor.order_cycle = order_cycle
orders << order_for_distributor
end

View File

@@ -4,15 +4,24 @@ Current cart for:
= spree_current_user.andand.email
%div{ 'ng-app' => 'store', 'ng-controller' => 'CartCtrl', 'ng-init' => "loadCart(#{spree_current_user.andand.cart.andand.id});" }
{{cart}} {{state}}
%br
%br
%ul
%li(ng-repeat="order in cart.orders")
Distributor: {{order.distributor}}
%br
Order cycle: {{order.order_cycle.andand.name}}
%br
From: {{order.order_cycle.andand.orders_open_at}} To: {{order.order_cycle.andand.orders_close_at}}
%strong Distributor:
{{order.distributor}}
%strong Order cycle:
{{order.order_cycle.andand.name}}
%strong From:
{{order.order_cycle.andand.orders_open_at}}
%strong To:
{{order.order_cycle.andand.orders_close_at}}
%ul
%li(ng-repeat="line_item in order.line_items")
Product: {{line_item.name}} Quantity: {{line_item.quantity}}
%strong Product:
{{line_item.name}}
%strong Quantity:
{{line_item.quantity}}
%button Buy me
%br

View File

@@ -6,89 +6,125 @@ describe Cart do
it { should have_many(:orders) }
end
describe 'adding a product' do
describe 'when adding a product' do
let(:cart) { Cart.create(user: user) }
let(:distributor) { FactoryGirl.create(:distributor_enterprise) }
let(:other_distributor) { FactoryGirl.create(:distributor_enterprise) }
let(:currency) { "AUD" }
let(:product) { FactoryGirl.create(:product, :distributors => [distributor]) }
let(:product_from_other_distributor) { FactoryGirl.create(:product, :distributors => [other_distributor]) }
let(:product) { FactoryGirl.create(:product, :distributors => [distributor]) }
let(:product_with_order_cycle) { create(:product) }
let(:order_cycle) { create(:simple_order_cycle, distributors: [distributor, other_distributor], variants: [product_with_order_cycle.master]) }
describe 'to an empty cart' do
it 'when there are no orders in the cart, create one when a product is added' do
subject.add_variant product.master.id, 3, currency
it 'should create an order for the product being added, and associate the product to the selected distribution' do
subject.add_variant product.master.id, 3, distributor, nil, currency
subject.orders.size.should == 1
order = subject.orders.first.reload
order.currency.should == currency
order.distributor.should == product.distributors.first
order.order_cycle.should be_nil
order.line_items.first.product.should == product
end
it 'should create an order for the product being added, and associate the order with an order cycle and distributor' do
subject.add_variant product_with_order_cycle.master.id, 3, distributor, order_cycle, currency
subject.orders.size.should == 1
order = subject.orders.first.reload
order.currency.should == currency
order.distributor.should == distributor
order.order_cycle.should == order_cycle
order.line_items.first.product.should == product_with_order_cycle
end
end
describe 'to a cart with an established order' do
let(:order) { FactoryGirl.create(:order, :distributor => other_distributor) }
describe 'to a cart with an order for a distributor' do
let(:product_from_other_distributor) { FactoryGirl.create(:product, :distributors => [other_distributor]) }
let(:order) { FactoryGirl.create(:order, :distributor => distributor) }
before (:each) do
subject.orders << order
subject.save!
end
it 'should create an order when a product from a new distributor is added' do
subject.add_variant product.master.id, 3, currency
it 'should create a new order when product added for different distributor' do
subject.add_variant product_from_other_distributor.master.id, 3, other_distributor, nil, currency
subject.reload
subject.orders.size.should == 2
new_order_for_distributor = subject.orders.find { |order| order.distributor == distributor }
new_order_for_distributor.line_items.first.product.should == product
new_order_for_other_distributor = subject.orders.find { |order| order.distributor == other_distributor }
new_order_for_other_distributor.order_cycle.should be_nil
new_order_for_other_distributor.line_items.first.product.should == product_from_other_distributor
end
it 'should group line item in existing order, when product from the same distributor' do
subject.add_variant product_from_other_distributor.master.id, 3, currency
it 'should group line item in existing order, when product added for the same distributor' do
subject.add_variant product.master.id, 3, distributor, nil, currency
subject.orders.size.should == 1
order = subject.orders.first.reload
order.line_items.size.should == 1
order.line_items.first.product.should == product
end
it 'should create a line item in each order for a product that has multiple distributors' do
product.distributors << other_distributor
product.save!
subject.add_variant product.master.id, 3, currency
subject.orders.size.should == 2
first_order = subject.orders.first.reload
second_order = subject.orders[1].reload
first_order.line_items.first.product.should == product
second_order.line_items.first.product.should == product
end
it 'should create multiple line items for an order that has multiple order cycles'
end
describe 'products with order cycles' do
let(:order_cycle) { FactoryGirl.create :order_cycle }
before(:each) do
product.order_cycles << order_cycle
product.save!
end
it 'should create an order when a product from a new order cycle is added' do
subject.add_variant product.master.id, 3, currency
subject.orders.size.should == 1
subject.orders.first.order_cycle.should == order_cycle
end
it 'should create line items in an order for added product, when in the same distributor and order cycle'
it 'should not create line items in an order, if the product is in a different order cycle to the order'
it 'should not create line items in an order, if the product is in a different distributor to the order'
it 'if the cart has a distributor set, then should only populate orders for that distributors'
it 'should create a new order for product in an order cycle' do
subject.add_variant product_with_order_cycle.master.id, 3, distributor, order_cycle, currency
subject.orders.size.should == 2
new_order_for_distributor = subject.orders.find { |order| order.order_cycle == order_cycle }
new_order_for_distributor.reload
new_order_for_distributor.line_items.first.product.should == product_with_order_cycle
end
end
describe 'existing order for distributor and order cycle' do
let(:order) { FactoryGirl.create(:order, :distributor => distributor, :order_cycle => order_cycle) }
before (:each) do
subject.orders << order
subject.save!
end
it 'should group line items in existing order when added for the same distributor and order cycle' do
subject.add_variant product_with_order_cycle.master.id, 3, distributor, order_cycle, currency
subject.orders.size.should == 1
order = subject.orders.first.reload
order.line_items.size.should == 1
order.line_items.find{ |line_item| line_item.product == product_with_order_cycle }.should_not be_nil
end
it 'should create line item in new order when product added is for a different order cycle' do
order_cycle2 = create(:simple_order_cycle, distributors: [distributor], variants: [product_with_order_cycle.master])
subject.add_variant product_with_order_cycle.master.id, 3, distributor, order_cycle2, currency
subject.orders.size.should == 2
new_order_for_second_order_cycle = subject.orders.find { |order| order.order_cycle == order_cycle2 }
new_order_for_second_order_cycle.reload
new_order_for_second_order_cycle.line_items.size.should == 1
new_order_for_second_order_cycle.line_items.first.product.should == product_with_order_cycle
new_order_for_second_order_cycle.distributor.should == distributor
new_order_for_second_order_cycle.order_cycle.should == order_cycle2
end
it 'should create line_items in new order when added with different distributor, but same order_cycle' do
subject.add_variant product_with_order_cycle.master.id, 3, other_distributor, order_cycle, currency
subject.orders.size.should == 2
new_order_for_second_order_cycle = subject.orders.find { |order| order.distributor == other_distributor }
new_order_for_second_order_cycle.reload
new_order_for_second_order_cycle.line_items.size.should == 1
new_order_for_second_order_cycle.line_items.find{ |line_item| line_item.product == product_with_order_cycle }.should_not be_nil
new_order_for_second_order_cycle.order_cycle.should == order_cycle
end
end
end
end