diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index 7f87d198e9..356691958e 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -8,6 +8,7 @@ Spree::OrdersController.class_eval do prepend_before_filter :require_order_cycle, only: :edit prepend_before_filter :require_distributor_chosen, only: :edit before_filter :check_hub_ready_for_checkout, only: :edit + before_filter :check_at_least_one_line_item, only: :update include OrderCyclesHelper layout 'darkswarm' @@ -223,4 +224,17 @@ Spree::OrdersController.class_eval do return order if order.andand.changes_allowed? && can?(:update, order) current_order end + + def check_at_least_one_line_item + order = order_to_update + return unless order.complete? + + items = params[:order][:line_items_attributes] + .andand.select{ |k,attrs| attrs["quantity"].to_i > 0 } + + if items.empty? + flash[:error] = I18n.t(:orders_cannot_remove_the_final_item) + redirect_to order_path(order) + end + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 5e5d067b31..9aa3a0de57 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1060,6 +1060,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using orders_show_confirmed: Confirmed orders_your_order_has_been_cancelled: "Your order has been cancelled" orders_could_not_cancel: "Sorry, the order could not be cancelled" + orders_cannot_remove_the_final_item: "Cannot remove the final item from an order, please cancel the order instead." orders_bought_items_notice: one: An additional item is already confirmed for this order cycle other: "%{count} additional items already confirmed for this order cycle" diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index 36e2182cd6..5008042c34 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -191,6 +191,40 @@ describe Spree::OrdersController do end end + describe "removing items from a completed order" do + let(:order) { create(:completed_order_with_totals) } + let!(:line_item) { order.reload.line_items.first } + let(:params) { { order: {} } } + + before { allow(subject).to receive(:order_to_update) { order } } + + context "when more than one item remains" do + before do + params[:order][:line_items_attributes] = { "0" => {quantity: "1", id: line_item.id} } + end + + it "does not remove the item, flash suggests cancellation" do + spree_post :update, params + expect(flash[:error]).to be nil + expect(response).to redirect_to spree.order_path(order) + expect(order.reload.line_items.count).to eq 1 + end + end + + context "when only one item remains" do + before do + params[:order][:line_items_attributes] = { "0" => {quantity: "0", id: line_item.id} } + end + + it "does not remove the item, flash suggests cancellation" do + spree_post :update, params + expect(flash[:error]).to eq I18n.t(:orders_cannot_remove_the_final_item) + expect(response).to redirect_to spree.order_path(order) + expect(order.reload.line_items.count).to eq 1 + end + end + end + describe "#order_to_update" do let!(:current_order) { double(:current_order) } let(:params) { { } }