diff --git a/core/app/models/spree/fulfilment_changer.rb b/core/app/models/spree/fulfilment_changer.rb index 747cb86f5a4..31c8a99b15e 100644 --- a/core/app/models/spree/fulfilment_changer.rb +++ b/core/app/models/spree/fulfilment_changer.rb @@ -43,17 +43,21 @@ def run! return false if invalid? desired_shipment.save! if desired_shipment.new_record? - new_on_hand_quantity = [desired_shipment.stock_location.count_on_hand(variant), quantity].min + # Retrieve how many on hand items we can take from desired stock location + available_quantity = [desired_shipment.stock_location.count_on_hand(variant), 0].max + + new_on_hand_quantity = [available_quantity, quantity].min + unstock_quantity = desired_shipment.stock_location.backorderable?(variant) ? quantity : new_on_hand_quantity ActiveRecord::Base.transaction do if handle_stock_counts? # We only run this query if we need it. - current_on_hand_quantity = [current_shipment.inventory_units.on_hand.size, quantity].min + current_on_hand_quantity = [current_shipment.inventory_units.pre_shipment.size, quantity].min # Restock things we will not fulfil from the current shipment anymore current_stock_location.restock(variant, current_on_hand_quantity, current_shipment) # Unstock what we will fulfil with the new shipment - desired_stock_location.unstock(variant, new_on_hand_quantity, desired_shipment) + desired_stock_location.unstock(variant, unstock_quantity, desired_shipment) end # These two statements are the heart of this class. We change the number diff --git a/core/spec/models/spree/fulfilment_changer_spec.rb b/core/spec/models/spree/fulfilment_changer_spec.rb index eca50082e19..eaec960b7ec 100644 --- a/core/spec/models/spree/fulfilment_changer_spec.rb +++ b/core/spec/models/spree/fulfilment_changer_spec.rb @@ -110,12 +110,12 @@ stock_item.update(backorderable: true) end - it "restocks five at the original stock location" do + it "restocks seven at the original stock location" do expect { subject }.to change { current_shipment.stock_location.count_on_hand(variant) }.by(7) end - it "unstocks five at the desired stock location" do - expect { subject }.to change { desired_shipment.stock_location.count_on_hand(variant) }.by(-5) + it "unstocks seven at the desired stock location" do + expect { subject }.to change { desired_shipment.stock_location.count_on_hand(variant) }.by(-7) end it "creates a shipment with the correct number of on hand and backordered units" do @@ -124,6 +124,24 @@ expect(desired_shipment.inventory_units.backordered.count).to eq(2) end + context "when the desired stock location already has a backordered units" do + let(:desired_count_on_hand) { -1 } + + it "restocks seven at the original stock location" do + expect { subject }.to change { current_shipment.stock_location.count_on_hand(variant) }.by(7) + end + + it "unstocks seven at the desired stock location" do + expect { subject }.to change { desired_shipment.stock_location.count_on_hand(variant) }.by(-7) + end + + it "creates a shipment with the correct number of on hand and backordered units" do + subject + expect(desired_shipment.inventory_units.on_hand.count).to eq(0) + expect(desired_shipment.inventory_units.backordered.count).to eq(7) + end + end + context "when the original shipment has on hand and backordered units" do before do current_shipment.inventory_units.limit(6).update_all(state: :backordered) @@ -137,16 +155,21 @@ end context "when the original shipment had some backordered units" do + let(:current_stock_item) { current_shipment.stock_location.stock_items.find_by(variant: variant) } + let(:desired_stock_item) { desired_shipment.stock_location.stock_items.find_by(variant: variant) } + let(:backordered_units) { 6 } + before do - current_shipment.inventory_units.limit(6).update_all(state: :backordered) + current_shipment.inventory_units.limit(backordered_units).update_all(state: :backordered) + current_stock_item.set_count_on_hand(-backordered_units) end it "restocks four at the original stock location" do - expect { subject }.to change { current_shipment.stock_location.count_on_hand(variant) }.by(4) + expect { subject }.to change { current_stock_item.reload.count_on_hand }.from(-backordered_units).to(1) end it "unstocks five at the desired stock location" do - expect { subject }.to change { desired_shipment.stock_location.count_on_hand(variant) }.by(-5) + expect { subject }.to change { desired_stock_item.reload.count_on_hand }.from(5).to(-2) end it "creates a shipment with the correct number of on hand and backordered units" do