Add error handling around payment with credit

For now we log error but don't report it to the user, so they can
proceed through the checkout.
This commit is contained in:
Gaetan Craig-Riou
2026-02-17 10:52:18 +11:00
parent f5a3093e41
commit c8dbf4c6f0
2 changed files with 75 additions and 6 deletions

View File

@@ -127,9 +127,10 @@ class CheckoutController < BaseController
@order.select_shipping_method(params[:shipping_method_id])
@order.update(order_params)
add_payment_with_credit if credit_available? && details_step?
@order.update(order_params)
# We need to update voucher to take into account:
# * when moving away from "details" step : potential change in shipping method fees
# * when moving away from "payment" step : payment fees
@@ -156,14 +157,27 @@ class CheckoutController < BaseController
def add_payment_with_credit
credit_payment_method = @order.distributor.payment_methods.customer_credit
if credit_payment_method.nil?
error_message = "Customer credit payment method is missing, please check configuration"
log_error(error_message)
return
end
return if @order.payments.where(payment_method: credit_payment_method).exists?
amount = [available_credit, @order.total].min
ActiveRecord::Base.transaction do
# we are already in a transaction because the order is locked, so we force creating a new one
# to make sure the rollback works as expected :
# https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html#module-ActiveRecord::Transactions::ClassMethods-label-Nested+transactions
ActiveRecord::Base.transaction(requires_new: true) do
amount = [available_credit, @order.total].min
payment = @order.payments.create!(payment_method: credit_payment_method, amount:)
payment.internal_purchase!
end
rescue StandardError => e
# Even though the transaction rolled back, the order still have a payment in memory,
# so we reload the payments so the payment doesn't get saved later on
@order.payments.reload
log_error(e)
end
def available_credit
@@ -194,4 +208,9 @@ class CheckoutController < BaseController
@order.back_to_address
end
def log_error(error)
Rails.logger.error("CheckoutController: #{error}")
Alert.raise(error)
end
end

View File

@@ -308,7 +308,7 @@ RSpec.describe CheckoutController do
end
end
context "with credit availablle" do
context "with credit available" do
let(:checkout_params) do
{
order: {
@@ -390,7 +390,57 @@ RSpec.describe CheckoutController do
end
end
# TODO cover error scenarios here
context "when payment creation fails" do
before do
# Add credit
create(
:customer_account_transaction,
amount: 5.00,
customer: order.customer,
payment_method: credit_payment_method
)
allow_any_instance_of(Spree::Payment).to receive(:internal_purchase!)
.and_raise(Spree::Core::GatewayError)
end
it "logs the error" do
expect(Alert).to receive(:raise).with(Spree::Core::GatewayError)
put(:update, params:)
end
it "doesn't create a credit payment" do
put(:update, params:)
credit_payment = order.payments.find_by(payment_method: credit_payment_method)
expect(credit_payment).to be_nil
end
end
context "when credit payment method is missing" do
before do
# Add credit
create(
:customer_account_transaction,
amount: 5.00,
customer: order.customer,
payment_method: credit_payment_method
)
credit_payment_method.destroy!
end
it "logs the error" do
expect(Alert).to receive(:raise).with(
"Customer credit payment method is missing, please check configuration"
)
put(:update, params:)
end
it "doesn't create a credit payment" do
put(:update, params:)
expect(order.payments).to be_empty
end
end
end
end
end