diff --git a/app/controllers/spree/admin/payments_controller.rb b/app/controllers/spree/admin/payments_controller.rb index 5c73ae1e0c..b95070ccf2 100644 --- a/app/controllers/spree/admin/payments_controller.rb +++ b/app/controllers/spree/admin/payments_controller.rb @@ -5,7 +5,7 @@ module Spree class PaymentsController < Spree::Admin::BaseController before_action :load_order, except: [:show] before_action :load_payment, only: [:fire, :show] - before_action :load_data + before_action :load_data, except: [:credit_customer] before_action :can_transition_to_payment # We ensure that items are in stock before all screens if the order is in the Payment state. # This way, we don't allow someone to enter credit card details for an order only to be told @@ -92,6 +92,18 @@ module Spree end end + def credit_customer + response = ::Orders::CustomerCreditService.new(@order).refund + + if response.success? + flash[:success] = Spree.t(:customer_credit_successful, scope: "admin.payments") + else + flash[:error] = response.message + end + + redirect_to admin_order_payments_path(@order) + end + private def load_payment_source diff --git a/app/views/spree/admin/payments/index.html.haml b/app/views/spree/admin/payments/index.html.haml index c3c52c2a23..6ae3e35b21 100644 --- a/app/views/spree/admin/payments/index.html.haml +++ b/app/views/spree/admin/payments/index.html.haml @@ -2,6 +2,10 @@ = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' } - content_for :page_actions do + - if @order.payment_state == "credit_owed" + %li#credit_customer_section + = button_link_to t(:credit_customer), admin_order_payments_credit_customer_url(@order), data: { method: :post } + - if @order.outstanding_balance? %li#new_payment_section = button_link_to t(:new_payment), new_admin_order_payment_url(@order), icon: 'icon-plus' diff --git a/config/locales/en.yml b/config/locales/en.yml index 4271e34a22..3dfbe85d2e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3589,6 +3589,7 @@ en: no_orders_found: "No Orders Found" order_information: "Order Information" new_payment: "New Payment" + credit_customer: Credit customer create_or_update_invoice: "Create or Update Invoice" date_completed: "Date Completed" amount: "Amount" @@ -4716,6 +4717,8 @@ en: submitting_payment: Submitting payment... paypal: no_payment_via_admin_backend: Paypal payments cannot be captured in the Backoffice + customer_credit_successful: Customer has been successfully credited! + products: image_upload_error: "Please upload the image in JPG, PNG, GIF, SVG or WEBP format." image_not_processable: "Image attachment is not a valid image." diff --git a/config/routes/spree.rb b/config/routes/spree.rb index 01d6d4ad3e..a02cef65c9 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -99,6 +99,8 @@ Spree::Core::Engine.routes.draw do post :generate end + post "payments/credit_customer", to: "payments#credit_customer" + resources :payments do member do put :fire diff --git a/spec/requests/spree/admin/payments_spec.rb b/spec/requests/spree/admin/payments_spec.rb index 1b7667ca25..b0d02adfd5 100644 --- a/spec/requests/spree/admin/payments_spec.rb +++ b/spec/requests/spree/admin/payments_spec.rb @@ -169,6 +169,7 @@ RSpec.describe Spree::Admin::PaymentsController do end end + # TODO with internal_void event context "with 'void' event" do before do allow(Spree::Payment).to receive(:find).and_return(payment) @@ -360,6 +361,53 @@ RSpec.describe Spree::Admin::PaymentsController do end end + describe "POST /admin/orders/:order_number/payments/credit_customer" do + let(:credit_payment_method) { order.distributor.payment_methods.customer_credit } + let(:success_response) { + Orders::CustomerCreditService::Response.new(success: true, message: "Refund successful!") + } + let(:customer_credit_service_mock) { instance_double(Orders::CustomerCreditService) } + + before do + allow(customer_credit_service_mock).to receive(:apply) + # order setup will call Orders::CustomerCreditService once + expect(Orders::CustomerCreditService).to receive(:new).and_call_original + expect(Orders::CustomerCreditService).to receive(:new).and_return( + customer_credit_service_mock + ) + end + + it "creates a customer credit payment" do + expect(customer_credit_service_mock).to receive(:refund).and_return(success_response) + + post("/admin/orders/#{order.number}/payments/credit_customer") + end + + it "redirect to payments page" do + expect(customer_credit_service_mock).to receive(:refund).and_return(success_response) + + post("/admin/orders/#{order.number}/payments/credit_customer") + + expect(response).to redirect_to(spree.admin_order_payments_path(order)) + expect(flash[:success]).to eq "Customer has been successfully credited!" + end + + context "when failing to create payment" do + let(:failure_response) { + Orders::CustomerCreditService::Response.new(success: false, message: "Some error") + } + + it "redirects to payments page" do + expect(customer_credit_service_mock).to receive(:refund).and_return(failure_response) + + post("/admin/orders/#{order.number}/payments/credit_customer") + + expect(response).to redirect_to(spree.admin_order_payments_path(order)) + expect(flash[:error]).to eq "Some error" + end + end + end + def add_voucher_to_order(voucher, order) voucher.create_adjustment(voucher.code, order) OrderManagement::Order::Updater.new(order).update_voucher