Skip to content

Commit 64f159c

Browse files
committed
Properly calculate inventory item quantities to be moved
The backordered quantity count should differ depending on whether moving to the same or a different stock location. For this reason, the way we calculate `available_quantity` changes as follows: * when the stock location differs: the stock on hand at the new shipment stock location; * when the stock location is the same: the sum of the stock on hand at the shipment stock location plus the number of on_hand inventory items from the shipment The explicit `backordered_quantity` variable is introduced to track the number of backordered items for the target shipment. The value is calculated as follows: * when the stock location differs: the quantity to be moved minus the positive available quantity at the stock location; * when the stock location is the same: the shipment total quantity for the variant minus the positive available quantity at the stock location. Also, we start the process by moving backordered items first to to make sure no pending backordered item remains. If the backordered count decreased, we're going to leave a few to be later moved and transformed to on hand, while if the backordered count increased, we are going to move also some previously on hand items.
1 parent 2bc7831 commit 64f159c

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

core/app/models/spree/fulfilment_changer.rb

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ def run!
8686
# we can take from the desired location, we could end up with some items being backordered.
8787
def run_tracking_inventory
8888
# Retrieve how many on hand items we can take from desired stock location
89-
available_quantity = [desired_shipment.stock_location.count_on_hand(variant), default_on_hand_quantity].max
90-
89+
available_quantity = get_available_quantity
9190
new_on_hand_quantity = [available_quantity, quantity].min
91+
backordered_quantity = get_backordered_quantity(available_quantity, new_on_hand_quantity)
9292
unstock_quantity = desired_shipment.stock_location.backorderable?(variant) ? quantity : new_on_hand_quantity
9393

9494
ActiveRecord::Base.transaction do
@@ -105,19 +105,21 @@ def run_tracking_inventory
105105
# These two statements are the heart of this class. We change the number
106106
# of inventory units requested from one shipment to the other.
107107
# We order by state, because `'backordered' < 'on_hand'`.
108+
# We start to move the new actual backordered quantity, so the remaining
109+
# quantity can be set to on_hand state.
108110
current_shipment.
109111
inventory_units.
110112
where(variant: variant).
111113
order(state: :asc).
112-
limit(new_on_hand_quantity).
113-
update_all(shipment_id: desired_shipment.id, state: :on_hand)
114+
limit(backordered_quantity).
115+
update_all(shipment_id: desired_shipment.id, state: :backordered)
114116

115117
current_shipment.
116118
inventory_units.
117119
where(variant: variant).
118120
order(state: :asc).
119-
limit(quantity - new_on_hand_quantity).
120-
update_all(shipment_id: desired_shipment.id, state: :backordered)
121+
limit(quantity - backordered_quantity).
122+
update_all(shipment_id: desired_shipment.id, state: :on_hand)
121123
end
122124
end
123125

@@ -141,11 +143,22 @@ def handle_stock_counts?
141143
current_shipment.order.completed? && current_stock_location != desired_stock_location
142144
end
143145

144-
def default_on_hand_quantity
146+
def get_available_quantity
147+
if current_stock_location != desired_stock_location
148+
desired_location_quantifier.positive_stock
149+
else
150+
sl_availability = current_location_quantifier.positive_stock
151+
shipment_availability = current_shipment.inventory_units.where(variant: variant).on_hand.count
152+
sl_availability + shipment_availability
153+
end
154+
end
155+
156+
def get_backordered_quantity(available_quantity, new_on_hand_quantity)
145157
if current_stock_location != desired_stock_location
146-
0
158+
quantity - new_on_hand_quantity
147159
else
148-
current_shipment.inventory_units.where(variant: variant).on_hand.count
160+
shipment_quantity = current_shipment.inventory_units.where(variant: variant).size
161+
shipment_quantity - available_quantity
149162
end
150163
end
151164

@@ -156,11 +169,19 @@ def current_shipment_not_already_shipped
156169
end
157170

158171
def enough_stock_at_desired_location
159-
unless Spree::Stock::Quantifier.new(variant, desired_stock_location).can_supply?(quantity)
172+
unless desired_location_quantifier.can_supply?(quantity)
160173
errors.add(:desired_shipment, :not_enough_stock_at_desired_location)
161174
end
162175
end
163176

177+
def desired_location_quantifier
178+
@desired_location_quantifier ||= Spree::Stock::Quantifier.new(variant, desired_stock_location)
179+
end
180+
181+
def current_location_quantifier
182+
@current_location_quantifier ||= Spree::Stock::Quantifier.new(variant, current_stock_location)
183+
end
184+
164185
def desired_shipment_different_from_current
165186
if desired_shipment.id == current_shipment.id
166187
errors.add(:desired_shipment, :can_not_transfer_within_same_shipment)

0 commit comments

Comments
 (0)