core/app/models/spree/refund.rb
module Spree
class Refund < Spree::Base
include Spree::Metadata
if defined?(Spree::Webhooks::HasWebhooks)
include Spree::Webhooks::HasWebhooks
end
if defined?(Spree::Security::Refunds)
include Spree::Security::Refunds
end
with_options inverse_of: :refunds do
belongs_to :payment
belongs_to :reimbursement, optional: true
end
belongs_to :reason, class_name: 'Spree::RefundReason', foreign_key: :refund_reason_id
has_many :log_entries, as: :source
with_options presence: true do
validates :payment, :reason
# can't require this on create because the perform! in after_create needs to run first
validates :transaction_id, on: :update
validates :amount, numericality: { greater_than: 0, allow_nil: true }
end
validate :amount_is_less_than_or_equal_to_allowed_amount, on: :create, if: :amount
after_create :perform!
after_create :create_log_entry
scope :non_reimbursement, -> { where(reimbursement_id: nil) }
attr_reader :response
def money
Spree::Money.new(amount, currency: payment.currency)
end
alias display_amount money
class << self
def total_amount_reimbursed_for(reimbursement)
reimbursement.refunds.to_a.sum(&:amount)
end
end
def description
payment.payment_method.name
end
private
# attempts to perform the refund.
# raises an error if the refund fails.
def perform!
return true if transaction_id.present?
credit_cents = Spree::Money.new(amount.to_f, currency: payment.currency).amount_in_cents
@response = process!(credit_cents)
self.transaction_id = @response.authorization
update_columns(transaction_id: transaction_id)
update_order
end
# return an activemerchant response object if successful or else raise an error
def process!(credit_cents)
response = if payment.payment_method.payment_profiles_supported?
payment.payment_method.credit(credit_cents, payment.source, payment.transaction_id, originator: self)
else
payment.payment_method.credit(credit_cents, payment.transaction_id, originator: self)
end
unless response.success?
Rails.logger.error(Spree.t(:gateway_error) + " #{response.to_yaml}")
text = response.params['message'] || response.params['response_reason_text'] || response.message
raise Core::GatewayError, text
end
response
rescue ActiveMerchant::ConnectionError => e
Rails.logger.error(Spree.t(:gateway_error) + " #{e.inspect}")
raise Core::GatewayError, Spree.t(:unable_to_connect_to_gateway)
end
def create_log_entry
log_entries.create!(details: @response.to_yaml)
end
def amount_is_less_than_or_equal_to_allowed_amount
if amount > payment.credit_allowed
errors.add(:amount, :greater_than_allowed)
end
end
def update_order
payment.order.updater.update
end
end
end