From 0921e0086b15b2c05e8ea6a2142bda1ffe335df8 Mon Sep 17 00:00:00 2001 From: andrea longhi Date: Wed, 10 Oct 2018 12:53:05 +0200 Subject: [PATCH] Spree::FulfilmentChanger stock allocation fix When splitting a shipment item to the same stock location, if the stock location has currently zero availability for that product then the state of the target shipment inventory unit should be determined by the original shipment inventory unit state: * when originally backordered, as there is still no available stock, then it should remain backordered * when originally on hand, then it should remain on hand, as there is no actual stock movement in this case (the fact that the stock location now has no availability for that product is not actually relevant) A clarifying example for the second scenario: * stock location L has 1 unit for product A * customer purchases 1 unit of product A * the order is created with product A on hand * product A is automatically included in shipment S * stock location L is now empty (0 units) for product A * if the admin splits product A from shipment S to a new shipment from the very same stock location L, product A should remain on hand also in the new shipment --- core/app/models/spree/fulfilment_changer.rb | 10 +++++- .../models/spree/fulfilment_changer_spec.rb | 33 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/core/app/models/spree/fulfilment_changer.rb b/core/app/models/spree/fulfilment_changer.rb index df06c37244b..12c5efe131b 100644 --- a/core/app/models/spree/fulfilment_changer.rb +++ b/core/app/models/spree/fulfilment_changer.rb @@ -46,7 +46,7 @@ def run! desired_shipment.save! if desired_shipment.new_record? # 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 + available_quantity = [desired_shipment.stock_location.count_on_hand(variant), default_on_hand_quantity].max new_on_hand_quantity = [available_quantity, quantity].min unstock_quantity = desired_shipment.stock_location.backorderable?(variant) ? quantity : new_on_hand_quantity @@ -114,6 +114,14 @@ def handle_stock_counts? current_shipment.order.completed? && current_stock_location != desired_stock_location end + def default_on_hand_quantity + if current_stock_location != desired_stock_location + 0 + else + current_shipment.inventory_units.where(variant: variant).on_hand.count + end + end + def current_shipment_not_already_shipped if current_shipment.shipped? errors.add(:current_shipment, :has_already_been_shipped) diff --git a/core/spec/models/spree/fulfilment_changer_spec.rb b/core/spec/models/spree/fulfilment_changer_spec.rb index af284ba4cd0..897d82835cd 100644 --- a/core/spec/models/spree/fulfilment_changer_spec.rb +++ b/core/spec/models/spree/fulfilment_changer_spec.rb @@ -37,6 +37,39 @@ variant.stock_items.first.update_column(:count_on_hand, 100) end + context "when the current shipment stock location is the same of the target shipment" do + let(:current_shipment_inventory_unit_count) { 1 } + let(:quantity) { current_shipment_inventory_unit_count } + + context "when the stock location is empty" do + before do + variant.stock_items.first.update_column(:count_on_hand, 0) + end + + context "when the inventory unit is backordered" do + before do + current_shipment.inventory_units.first.update state: :backordered + end + + it "creates a new backordered inventory unit" do + subject + expect(desired_shipment.inventory_units.first).to be_backordered + end + end + + context "when the inventory unit is on hand" do + before do + current_shipment.inventory_units.first.update state: :on_hand + end + + it "creates a new on hand inventory unit" do + subject + expect(desired_shipment.inventory_units.first).to be_on_hand + end + end + end + end + context "when the current shipment has enough inventory units" do let(:current_shipment_inventory_unit_count) { 2 } let(:quantity) { 1 }