diff --git a/core/app/models/spree/shipment.rb b/core/app/models/spree/shipment.rb index d9326ff83d..2dbb167138 100644 --- a/core/app/models/spree/shipment.rb +++ b/core/app/models/spree/shipment.rb @@ -221,10 +221,10 @@ def determine_state(order) # ready all other cases def recalculate_state self.state = - if order.canceled? || inventory_units.all?(&:canceled?) - "canceled" - elsif shipped? + if shipped? "shipped" + elsif order.canceled? || inventory_units.all?(&:canceled?) + "canceled" elsif !order.can_ship? "pending" elsif can_transition_from_pending_to_ready? diff --git a/core/spec/models/spree/order_cancellations_spec.rb b/core/spec/models/spree/order_cancellations_spec.rb index 3834f61fa2..8de4253c4d 100644 --- a/core/spec/models/spree/order_cancellations_spec.rb +++ b/core/spec/models/spree/order_cancellations_spec.rb @@ -109,6 +109,32 @@ it "adjusts the order" do expect { subject }.to change { order.reload.total }.by(-40.0) end + + context "when cancelling all items in a completed order" do + let!(:order) { create(:completed_order_with_totals, line_items_attributes: [{ quantity: }]) } + + subject { described_class.new(order).short_ship(order.inventory_units) } + + it "updates all of the inventory units" do + expect { subject }.to change { order.inventory_units.canceled.count }.to(quantity) + end + + it "updates the shipment state" do + expect { subject }.to change { order.shipments.first.reload.state }.to("canceled") + end + + context "when the shipment is already shipped" do + let!(:order) { create(:shipped_order, line_items_attributes: [{ quantity: }]) } + + it "updates all of the inventory units" do + expect { subject }.to change { order.inventory_units.canceled.count }.to(quantity) + end + + it "does not update the shipment state" do + expect { subject }.not_to change { order.shipments.first.reload.state }.from("shipped") + end + end + end end it "sends a cancellation email" do