Add button to credit customer when order is credit owed state

It will add a negative payment, matching the amount credited in the
customer_account_transaction
This commit is contained in:
Gaetan Craig-Riou
2026-02-23 14:32:19 +11:00
parent ee13a3abaf
commit 3e2e7f1799
5 changed files with 70 additions and 1 deletions

View File

@@ -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

View File

@@ -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'

View File

@@ -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."

View File

@@ -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

View File

@@ -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