diff --git a/app/models/cart.rb b/app/models/cart.rb index 61d1b32e7c..29b48c5545 100644 --- a/app/models/cart.rb +++ b/app/models/cart.rb @@ -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 diff --git a/app/views/open_food_web/cart/_show.html.haml b/app/views/open_food_web/cart/_show.html.haml index b9c6da6e72..5a633cf05b 100644 --- a/app/views/open_food_web/cart/_show.html.haml +++ b/app/views/open_food_web/cart/_show.html.haml @@ -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 diff --git a/spec/models/cart_spec.rb b/spec/models/cart_spec.rb index 7e40a2efba..e9d56dca10 100644 --- a/spec/models/cart_spec.rb +++ b/spec/models/cart_spec.rb @@ -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