diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 5a128f1824..011f30f66c 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -43,7 +43,6 @@ Layout/LineLength: - app/controllers/checkout_controller.rb - app/controllers/spree/admin/adjustments_controller_decorator.rb - app/controllers/spree/admin/orders_controller_decorator.rb - - app/controllers/spree/admin/payments_controller_decorator.rb - app/controllers/spree/credit_cards_controller.rb - app/controllers/spree/paypal_controller_decorator.rb - app/controllers/stripe/callbacks_controller.rb @@ -365,7 +364,8 @@ Metrics/AbcSize: - app/controllers/spree/admin/orders_controller_decorator.rb - app/controllers/spree/admin/overview_controller.rb - app/controllers/spree/admin/payment_methods_controller.rb - - app/controllers/spree/admin/payments_controller_decorator.rb + - app/controllers/spree/admin/payments_controller.rb + - app/controllers/spree/admin/products_controller_decorator.rb - app/controllers/spree/admin/reports_controller.rb - app/controllers/spree/admin/resource_controller.rb - app/controllers/spree/admin/products_controller.rb @@ -496,7 +496,6 @@ Metrics/CyclomaticComplexity: - app/controllers/admin/enterprise_fees_controller.rb - app/controllers/admin/enterprises_controller.rb - app/controllers/checkout_controller.rb - - app/controllers/spree/admin/payments_controller_decorator.rb - app/controllers/spree/admin/taxons_controller.rb - app/controllers/spree/orders_controller.rb - app/helpers/checkout_helper.rb @@ -527,7 +526,6 @@ Metrics/PerceivedComplexity: - app/controllers/admin/enterprises_controller.rb - app/controllers/api/variants_controller.rb - app/controllers/checkout_controller.rb - - app/controllers/spree/admin/payments_controller_decorator.rb - app/controllers/spree/admin/taxons_controller.rb - app/controllers/spree/orders_controller.rb - app/helpers/checkout_helper.rb @@ -569,7 +567,7 @@ Metrics/MethodLength: - app/controllers/spree/admin/image_settings_controller.rb - app/controllers/spree/admin/orders/customer_details_controller_decorator.rb - app/controllers/spree/admin/payment_methods_controller.rb - - app/controllers/spree/admin/payments_controller_decorator.rb + - app/controllers/spree/admin/payments_controller.rb - app/controllers/spree/admin/reports_controller.rb - app/controllers/spree/admin/resource_controller.rb - app/controllers/spree/admin/products_controller.rb diff --git a/app/controllers/spree/admin/payments_controller.rb b/app/controllers/spree/admin/payments_controller.rb new file mode 100644 index 0000000000..0c17f8154a --- /dev/null +++ b/app/controllers/spree/admin/payments_controller.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +module Spree + module Admin + class PaymentsController < Spree::Admin::BaseController + before_filter :load_order, except: [:show] + before_filter :load_payment, only: [:fire, :show] + before_filter :load_data + before_filter :can_transition_to_payment + + respond_to :html + + def index + @payments = @order.payments + redirect_to new_admin_order_payment_url(@order) if @payments.empty? + end + + def new + @payment = @order.payments.build + end + + def create + @payment = @order.payments.build(object_params) + load_payment_source + + begin + unless @payment.save + redirect_to admin_order_payments_path(@order) + return + end + + if @order.completed? + @payment.process! + flash[:success] = flash_message_for(@payment, :successfully_created) + + redirect_to admin_order_payments_path(@order) + else + AdvanceOrderService.new(@order).call! + + flash[:success] = Spree.t(:new_order_completed) + redirect_to edit_admin_order_url(@order) + end + rescue Spree::Core::GatewayError => e + flash[:error] = e.message.to_s + redirect_to new_admin_order_payment_path(@order) + end + end + + # When a user fires an event, take them back to where they came from + # (we can't use respond_override because Spree no longer uses respond_with) + def fire + event = params[:e] + return unless event && @payment.payment_source + + # Because we have a transition method also called void, we do this to avoid conflicts. + event = "void_transaction" if event == "void" + if @payment.public_send("#{event}!") + flash[:success] = t(:payment_updated) + else + flash[:error] = t(:cannot_perform_operation) + end + rescue Spree::Core::GatewayError => e + flash[:error] = e.message + ensure + redirect_to request.referer + end + + private + + def load_payment_source + if @payment.payment_method.is_a?(Spree::Gateway) && + @payment.payment_method.payment_profiles_supported? && + params[:card].present? && + (params[:card] != 'new') + @payment.source = CreditCard.find_by_id(params[:card]) + end + end + + def object_params + if params[:payment] && + params[:payment_source] && + source_params = params.delete(:payment_source)[params[:payment][:payment_method_id]] + params[:payment][:source_attributes] = source_params + end + params[:payment] + end + + def load_data + @amount = params[:amount] || load_order.total + + # Only show payments for the order's distributor + @payment_methods = PaymentMethod. + available(:back_end). + select{ |pm| pm.has_distributor? @order.distributor } + + @payment_method = if @payment && @payment.payment_method + @payment.payment_method + else + @payment_methods.first + end + + @previous_cards = @order.credit_cards.with_payment_profile + end + + # At this point admin should have passed through Customer Details step + # where order.next is called which leaves the order in payment step + # + # Orders in complete step also allows to access this controller + # + # Otherwise redirect user to that step + def can_transition_to_payment + return if @order.payment? || @order.complete? + + flash[:notice] = Spree.t(:fill_in_customer_info) + redirect_to edit_admin_order_customer_url(@order) + end + + def load_order + @order = Order.find_by_number!(params[:order_id]) + authorize! action, @order + @order + end + + def load_payment + @payment = Payment.find(params[:id]) + end + end + end +end diff --git a/app/controllers/spree/admin/payments_controller_decorator.rb b/app/controllers/spree/admin/payments_controller_decorator.rb deleted file mode 100644 index 41d43f2e56..0000000000 --- a/app/controllers/spree/admin/payments_controller_decorator.rb +++ /dev/null @@ -1,59 +0,0 @@ -Spree::Admin::PaymentsController.class_eval do - append_before_filter :filter_payment_methods - - def create - @payment = @order.payments.build(object_params) - if @payment.payment_method.is_a?(Spree::Gateway) && @payment.payment_method.payment_profiles_supported? && params[:card].present? && (params[:card] != 'new') - @payment.source = CreditCard.find_by_id(params[:card]) - end - - begin - unless @payment.save - redirect_to admin_order_payments_path(@order) - return - end - - if @order.completed? - @payment.process! - flash[:success] = flash_message_for(@payment, :successfully_created) - - redirect_to admin_order_payments_path(@order) - else - AdvanceOrderService.new(@order).call! - - flash[:success] = Spree.t(:new_order_completed) - redirect_to edit_admin_order_url(@order) - end - rescue Spree::Core::GatewayError => e - flash[:error] = e.message.to_s - redirect_to new_admin_order_payment_path(@order) - end - end - - # When a user fires an event, take them back to where they came from - # (we can't use respond_override because Spree no longer uses respond_with) - def fire - event = params[:e] - return unless event && @payment.payment_source - - # Because we have a transition method also called void, we do this to avoid conflicts. - event = "void_transaction" if event == "void" - if @payment.public_send("#{event}!") - flash[:success] = t(:payment_updated) - else - flash[:error] = t(:cannot_perform_operation) - end - rescue Spree::Core::GatewayError => e - flash[:error] = e.message - ensure - redirect_to request.referer - end - - private - - # Only show payments for the order's distributor - def filter_payment_methods - @payment_methods = @payment_methods.select{ |pm| pm.has_distributor? @order.distributor } - @payment_method ||= @payment_methods.first - end -end diff --git a/app/helpers/spree/admin/payments_helper.rb b/app/helpers/spree/admin/payments_helper.rb new file mode 100644 index 0000000000..529ef90adf --- /dev/null +++ b/app/helpers/spree/admin/payments_helper.rb @@ -0,0 +1,11 @@ +module Spree + module Admin + module PaymentsHelper + def payment_method_name(payment) + # hack to allow us to retrieve the name of a "deleted" payment method + id = payment.payment_method_id + Spree::PaymentMethod.find_with_destroyed(id).name + end + end + end +end diff --git a/app/views/spree/admin/payments/source_forms/_check.html.haml b/app/views/spree/admin/payments/source_forms/_check.html.haml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/spree/admin/payments/source_views/_check.html.haml b/app/views/spree/admin/payments/source_views/_check.html.haml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/config/locales/en.yml b/config/locales/en.yml index 5db0124b51..0de0059f3d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2988,6 +2988,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using zipcode: Postcode weight: Weight (per kg) error_user_destroy_with_orders: "Users with completed orders may not be deleted" + cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined." + please_define_payment_methods: "Please define some payment methods first." options: "Options" actions: diff --git a/config/routes/spree.rb b/config/routes/spree.rb index cb1b5e28a3..e7fcf0d2cb 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -97,6 +97,12 @@ Spree::Core::Engine.routes.draw do end resources :adjustments + + resources :payments do + member do + put :fire + end + end end resources :users do