Files
openfoodnetwork/app/models/spree/payment_method/customer_credit.rb
2026-03-10 16:07:43 +11:00

111 lines
3.4 KiB
Ruby

# frozen_string_literal: true
module Spree
class PaymentMethod
class CustomerCredit < Spree::PaymentMethod
# Name and description are translatable string, to allow instances to customise them
def name
"credit_payment_method.name"
end
def description
"credit_payment_method.description"
end
def actions
%w{internal_void}
end
# We should only void complete payment, otherwise we will be refunding credit that was
# not used in the first place.
def can_internal_void?(payment)
payment.state == "completed"
end
# Main method called by Spree::Payment::Processing during checkout
# - amount is in cents
# - options: {
# customer_id:, payment_id:, order_number:
# }
def purchase(amount, _source, options)
calculated_amount = amount / 100.00
customer = Customer.find_by(id: options[:customer_id])
return error_response("customer_not_found") if customer.nil?
return error_response("missing_payment") if options[:payment_id].nil?
available_credit = customer.customer_account_transactions.last&.balance
return error_response("no_credit_available") if available_credit.nil?
return error_response("not_enough_credit_available") if calculated_amount > available_credit
customer.with_lock do
description = I18n.t(
"order_payment_description",
scope: "credit_payment_method",
order_number: options[:order_number]
)
customer.customer_account_transactions.create(
amount: -calculated_amount,
currency:,
payment_id: options[:payment_id],
description:
)
end
message = I18n.t("success", scope: "credit_payment_method")
ActiveMerchant::Billing::Response.new(true, message)
end
# Main method called by Spree::Payment::Processing for void
# - amount is in cents
# - options: {
# customer_id:, payment_id:, order_number:, user_id: (optional)
# }
def void(amount, _source, options)
calculated_amount = amount / 100.00
customer = Customer.find_by(id: options[:customer_id])
return error_response("customer_not_found") if customer.nil?
return error_response("missing_payment") if options[:payment_id].nil?
customer.with_lock do
description = I18n.t(
"order_void_description",
scope: "credit_payment_method",
order_number: options[:order_number]
)
customer.customer_account_transactions.create(
amount: calculated_amount,
currency:,
payment_id: options[:payment_id],
description:,
created_by_id: options[:user_id]
)
end
message = I18n.t("void_success", scope: "credit_payment_method")
ActiveMerchant::Billing::Response.new(true, message)
end
def method_type
"check" # empty view
end
def source_required?
false
end
private
def error_response(translation_key)
message = I18n.t(translation_key, scope: "credit_payment_method.errors")
ActiveMerchant::Billing::Response.new(false, message)
end
def currency
CurrentConfig.get(:currency)
end
end
end
end