From 15fb493d9aeb06d363fdef15bf7b5f5b4a53e8ce Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Thu, 15 Dec 2016 13:52:07 +1100 Subject: [PATCH] StandingOrderPlacementJob: cap quantity at 0 for items not available through OC --- app/jobs/standing_order_placement_job.rb | 17 ++++- .../jobs/standing_order_placement_job_spec.rb | 70 ++++++++++++++----- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/app/jobs/standing_order_placement_job.rb b/app/jobs/standing_order_placement_job.rb index 19fec629dc..9165971f5b 100644 --- a/app/jobs/standing_order_placement_job.rb +++ b/app/jobs/standing_order_placement_job.rb @@ -30,12 +30,17 @@ class StandingOrderPlacementJob end def cap_quantity_and_store_changes(order) + changes = {} insufficient_stock_lines = order.insufficient_stock_lines - return {} unless insufficient_stock_lines.present? - insufficient_stock_lines.each_with_object({}) do |line_item, changes| + insufficient_stock_lines.each_with_object(changes) do |line_item, changes| changes[line_item.id] = line_item.quantity line_item.cap_quantity_at_stock! end + unavailable_stock_lines = unavailable_stock_lines_for(order) + unavailable_stock_lines.each_with_object(changes) do |line_item, changes| + changes[line_item.id] = changes[line_item.id] || line_item.quantity + line_item.update_attributes(quantity: 0) + end end def move_to_completion(order) @@ -54,6 +59,14 @@ class StandingOrderPlacementJob end end + def unavailable_stock_lines_for(order) + order.line_items.where('variant_id NOT IN (?)', available_variants_for(order)) + end + + def available_variants_for(order) + DistributionChangeValidator.new(order).variants_available_for_distribution(order.distributor, order_cycle) + end + def send_placement_email(order, changes) return unless order.completed? Spree::OrderMailer.standing_order_email(order.id, 'placement', changes).deliver diff --git a/spec/jobs/standing_order_placement_job_spec.rb b/spec/jobs/standing_order_placement_job_spec.rb index ff1d1649d3..d5765a38ca 100644 --- a/spec/jobs/standing_order_placement_job_spec.rb +++ b/spec/jobs/standing_order_placement_job_spec.rb @@ -28,32 +28,64 @@ describe StandingOrderPlacementJob do end end - describe "processing an order containing items with insufficient stock" do + describe "checking that line items are available to purchase" do let(:order_cycle) { create(:simple_order_cycle) } - let(:order) { create(:order, order_cycle: order_cycle) } + let(:shop) { order_cycle.coordinator } + let(:order) { create(:order, order_cycle: order_cycle, distributor: shop) } + let(:ex) { create(:exchange, :order_cycle => order_cycle, :sender => shop, :receiver => shop, :incoming => false) } let(:variant1) { create(:variant, count_on_hand: 5) } - let(:variant2) { create(:variant, count_on_hand: 2) } - let(:variant3) { create(:variant, count_on_hand: 0) } - let(:line_item1) { create(:line_item, order: order, variant: variant1, quantity: 5) } - let(:line_item2) { create(:line_item, order: order, variant: variant2, quantity: 2) } - let(:line_item3) { create(:line_item, order: order, variant: variant3, quantity: 0) } + let(:variant2) { create(:variant, count_on_hand: 5) } + let(:variant3) { create(:variant, count_on_hand: 5) } + let!(:line_item1) { create(:line_item, order: order, variant: variant1, quantity: 3) } + let!(:line_item2) { create(:line_item, order: order, variant: variant2, quantity: 3) } + let!(:line_item3) { create(:line_item, order: order, variant: variant3, quantity: 3) } let!(:job) { StandingOrderPlacementJob.new(order_cycle) } - before do - Spree::Config.set(:allow_backorders, false) - line_item1.update_attribute(:quantity, 3) - line_item2.update_attribute(:quantity, 3) - line_item3.update_attribute(:quantity, 3) + before { Spree::Config.set(:allow_backorders, false) } + + context "when all items are available from the order cycle" do + before { [variant1, variant2, variant3].each { |v| ex.variants << v } } + + context "and insufficient stock exists to fulfil the order for some items" do + before do + variant1.update_attribute(:count_on_hand, 5) + variant2.update_attribute(:count_on_hand, 2) + variant3.update_attribute(:count_on_hand, 0) + end + + it "caps quantity at the stock level for stock-limited items, and reports the change" do + changes = job.send(:cap_quantity_and_store_changes, order.reload) + expect(line_item1.reload.quantity).to be 3 # not capped + expect(line_item2.reload.quantity).to be 2 # capped + expect(line_item3.reload.quantity).to be 0 # capped + expect(changes[line_item1.id]).to be nil + expect(changes[line_item2.id]).to be 3 + expect(changes[line_item3.id]).to be 3 + end + end end - it "caps quantity at the stock level, and reports the change" do - changes = job.send(:cap_quantity_and_store_changes, order.reload) - expect(line_item1.reload.quantity).to be 3 # not capped - expect(line_item2.reload.quantity).to be 2 # capped - expect(line_item3.reload.quantity).to be 0 # capped - expect(changes[line_item2.id]).to be 3 - expect(changes[line_item3.id]).to be 3 + context "and some items are not available from the order cycle" do + before { [variant2, variant3].each { |v| ex.variants << v } } + + context "and insufficient stock exists to fulfil the order for some items" do + before do + variant1.update_attribute(:count_on_hand, 5) + variant2.update_attribute(:count_on_hand, 2) + variant3.update_attribute(:count_on_hand, 0) + end + + it "sets quantity to 0 for unavailable items, and reports the change" do + changes = job.send(:cap_quantity_and_store_changes, order.reload) + expect(line_item1.reload.quantity).to be 0 # unavailable + expect(line_item2.reload.quantity).to be 2 # capped + expect(line_item3.reload.quantity).to be 0 # capped + expect(changes[line_item1.id]).to be 3 + expect(changes[line_item2.id]).to be 3 + expect(changes[line_item3.id]).to be 3 + end + end end end