Skip to content

Instantly share code, notes, and snippets.

@imme5150
Created January 21, 2014 07:12
Show Gist options
  • Save imme5150/8535642 to your computer and use it in GitHub Desktop.
Save imme5150/8535642 to your computer and use it in GitHub Desktop.
Partial payments for shipments in Spree 1.1.0 - only for credit card payments and shipping is applied only to the first shipment.
module Spree
Payment.class_eval do
def complete_or_partial_capture!(amount)
return false if amount <= 0 || self.state != 'pending'
# if it's close to total payment, round up or down to total payment
# this is to counteract rounding errors from tax calculations
amount = self.amount if ((amount-0.02)..(amount+0.02)).include?(self.amount)
# check to make sure there is enough money authorized for this payment
return false if amount > self.amount
if amount < self.amount # split the payment
new_payment = self.dup
new_payment.amount = self.amount - amount
new_payment.save
self.update_attribute(:amount, amount)
end
if Rails.env.production?
self.capture!
else
self.update_attribute_without_callbacks(:state, 'completed')
end
rescue Exception => e
if e.message && (
e.message.starts_with?('This transaction is locked down') ||
e.message.starts_with?('This industry type (eCOMMERCE) does not allow a capture greater than the value of the auth') )
return false # This payment was already captured or the order price changed
else
raise
end
end
private
def record_response(response)
details = response.doc.to_s if response.respond_to?(:doc)
details ||= response.to_yaml
details.gsub!(/AccountNum>\d+<\/AccountNum/, 'AccountNum FILTERED /')
log_entries.create({:details => details}, :without_protection => true)
end
end
end
Spree::Shipment.class_eval do
attr_accessor :payment_successful
def shipping_cost
# shipping cost is for ONLY the first shipment
order.shipments.shipped.order(:shipped_at).first == self ? order.ship_total : 0
end
def price
# create a dummy order to keep track of the line itmes in the current shipment
dummy_order = order.dup
dummy_order.line_items = order.shipped_line_items( self )
price = dummy_order.line_items.map(&:total).sum
price -= dummy_order.line_item_discounts
if (tax_rate = order.tax_rate)
price += (tax_rate * price).round(2)
end
price += shipping_cost
end
private
def after_ship
update_attribute_without_callbacks :shipped_at, Time.now
inventory_units.each &:ship!
self.payment_successful = capture_credit_card_payment_if_needed!
Spree::OrderMailer.confirm_email(order, false, self).deliver
end
def capture_credit_card_payment_if_needed!
return true unless (payment = order.payments.pending.from_creditcard.first)
payment.complete_or_partial_capture!( self.price )
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment