diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index 0de7d0f8f0..64ae25df7e 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -12,6 +12,7 @@ Spree::OrdersController.class_eval do include OrderCyclesHelper layout 'darkswarm' + respond_to :json # Patching to redirect to shop if order is empty def edit @@ -164,6 +165,18 @@ Spree::OrdersController.class_eval do @order_cycle = OrderCycle.find session[:expired_order_cycle_id] end + def cancel + @order = Spree::Order.find_by_number!(params[:id]) + authorize! :cancel, @order + + if @order.cancel + flash[:success] = I18n.t(:orders_your_order_has_been_cancelled) + else + flash[:error] = I18n.t(:orders_could_not_cancel) + end + redirect_to request.referer || order_path(@order) + end + private diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index b2ceffd1b0..6c5cad6fb3 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -55,6 +55,9 @@ class AbilityDecorator can [:destroy], Spree::LineItem do |item| item.andand.order.andand.can_remove_items? user end + can [:cancel], Spree::Order do |order| + order.user == user + end end # New users can create an enterprise, and gain other permissions from doing this. diff --git a/config/locales/en.yml b/config/locales/en.yml index 4abb72d108..9484e0b291 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1048,6 +1048,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using orders_show_title: Order Confirmation orders_show_time: Order ready on orders_show_number: Order confirmation + orders_your_order_has_been_cancelled: "Your order has been cancelled" + orders_could_not_cancel: "Sorry, the order could not be cancelled" products_cart_distributor_choice: "Distributor for your order:" products_cart_distributor_change: "Your distributor for this order will be changed to %{name} if you add this product to your cart." diff --git a/config/routes.rb b/config/routes.rb index ad47a68149..17986e2081 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -264,6 +264,7 @@ Spree::Core::Engine.routes.prepend do resources :orders do get :clear, :on => :collection get :order_cycle_expired, :on => :collection + put :cancel, on: :member end end diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index e1396be3f6..3707bd194d 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -259,6 +259,41 @@ describe Spree::OrdersController do end end + describe "cancelling an order" do + let(:user) { create(:user) } + let(:order) { create(:order, user: user) } + let(:params) { { id: order.number } } + + context "when the user does not have permission to cancel the order" do + it "responds with unauthorized" do + spree_put :cancel, params + expect(response).to render_template 'shared/unauthorized' + end + end + + context "when the user has permission to cancel the order" do + before { allow(controller).to receive(:spree_current_user) { user } } + + context "when the order is not yet complete" do + it "responds with forbidden" do + spree_put :cancel, params + expect(response.status).to redirect_to spree.order_path(order) + expect(flash[:error]).to eq I18n.t(:orders_could_not_cancel) + end + end + + context "when the order is complete" do + let(:order) { create(:completed_order_with_totals, user: user) } + + it "responds with success" do + spree_put :cancel, params + expect(response.status).to redirect_to spree.order_path(order) + expect(flash[:success]).to eq I18n.t(:orders_your_order_has_been_cancelled) + end + end + end + end + private