Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store credit cancel #6

Merged
merged 4 commits into from
Nov 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions core/app/models/spree/payment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,20 @@ def credit_allowed
amount - (offsets_total.abs + refunds.sum(:amount))
end

# The total amount this payment can be credited in cents.
#
# For currencies which do not support decimal places, it will return the
# full value.
#
# @return [Fixnum] The amount of this payment minus offets and refunds
# in cents.
def credit_allowed_in_cents
Spree::Money.new(
credit_allowed,
currency: currency
).money.cents
end

# @return [Boolean] true when this payment can be credited
def can_credit?
credit_allowed > 0
Expand Down
22 changes: 18 additions & 4 deletions core/app/models/spree/payment_method/store_credit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,16 @@ def credit(amount_in_cents, auth_code, gateway_options)
currency = gateway_options[:currency] || store_credit.currency
originator = gateway_options[:originator]

store_credit.credit(amount_in_cents / 100.0.to_d, auth_code, currency, action_originator: originator)
if amount_in_cents > 0
store_credit.credit(
::Money.new(amount_in_cents, currency).to_d,
auth_code,
currency,
action_originator: originator
)
else
ActiveMerchant::Billing::Response.new(true, '')
end
end

handle_action(action, :credit, auth_code)
Expand All @@ -78,13 +87,18 @@ def cancel(auth_code)
store_credit = store_credit_event.try(:store_credit)

if store_credit_event.nil? || store_credit.nil?
return false
ActiveMerchant::Billing::Response.new(false, '', {}, {})
elsif store_credit_event.capture_action?
store_credit.credit(store_credit_event.amount, auth_code, store_credit.currency)
amount = if store_credit_event.originator_type == 'Spree::Payment'
store_credit_event.originator.credit_allowed_in_cents
else
(store_credit_event.amount * 100).round
end
credit(amount, auth_code, { originator: store_credit_event.originator })
elsif store_credit_event.authorization_action?
store_credit.void(auth_code)
else
return false
ActiveMerchant::Billing::Response.new(false, '', {}, {})
end
end

Expand Down
59 changes: 49 additions & 10 deletions core/spec/models/spree/payment_method/store_credit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,19 @@
end
end

context "when attempting to credit for zero" do
let(:credit_amount) { 0 }

it "does not credit the store credit" do
expect_any_instance_of(Spree::StoreCredit).to_not receive(:credit)
subject
end

it "returns a success response" do
expect(subject.success?).to be true
end
end

context "when the store credit isn't credited successfully" do
before { allow_any_instance_of(Spree::StoreCredit).to receive_messages(credit: false) }

Expand Down Expand Up @@ -255,15 +268,41 @@
let(:auth_code) { "1-SC-20141111111111" }
let(:captured_amount) { 10.0 }

shared_examples "a spree payment method" do
it "returns an ActiveMerchant::Billing::Response" do
expect(subject).to be_instance_of(ActiveMerchant::Billing::Response)
end
end

context "capture event found" do
let!(:store_credit_event) { create(:store_credit_capture_event,
authorization_code: auth_code,
amount: captured_amount,
store_credit: store_credit) }
let!(:store_credit_event) do
create(
:store_credit_capture_event,
authorization_code: auth_code,
amount: captured_amount,
store_credit: store_credit,
originator: originator
)
end
let(:payment) { create(:payment, order: order, amount: 5) }
let(:originator) { nil }

it "creates a store credit for the same amount that was captured" do
expect_any_instance_of(Spree::StoreCredit).to receive(:credit).with(captured_amount, auth_code, store_credit.currency)
subject
it_behaves_like "a spree payment method"

context "when originator is nil" do
it "refunds the event amount" do
expect { subject }.to change{ store_credit.reload.amount_remaining }.
from(140).to(150)
end
end

context "when the originator is the payment" do
let(:originator) { payment }

it "refunds the payment credit allowed amount" do
expect { subject }.to change{ store_credit.reload.amount_remaining }.
from(140).to(145)
end
end
end

Expand All @@ -285,9 +324,9 @@
Spree::PaymentMethod::StoreCredit.new.cancel('INVALID')
end

it "returns false" do
expect(subject).to be false
end
it_behaves_like "a spree payment method"

it { expect(subject.success?).to be(false) }
end
end
end
Expand Down
47 changes: 47 additions & 0 deletions core/spec/models/spree/payment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,53 @@
end
end

describe "#credit_allowed_in_cents" do
subject { payment.credit_allowed_in_cents }

let(:currency) { 'USD' }
let(:order) { create :order, currency: currency }
let(:payment) do
create :payment, amount: 100, order: order, state: 'completed'
end

context "when there are no offsets" do
context "when the currency is USD" do
it "it returns the payment amount in cents" do
expect(subject).to eq(10000)
end
end

context "when the currency is JPY" do
let(:currency) { 'JPY' }
it "it returns the total amount" do
expect(subject).to eq(100)
end
end
end

context "when there are offsets" do
before do
payment.offsets.create!(
amount: -80,
order: order,
source: payment,
state: 'completed'
)
end

it "is the difference between offsets total and payment amount in cents" do
expect(subject).to eq(2000)
end

context "when the currency is JPY" do
let(:currency) { 'JPY' }
it "it returns the total amount minus offsets" do
expect(subject).to eq(20)
end
end
end
end

describe "#can_credit?" do
it "is true if credit_allowed > 0" do
allow(payment).to receive(:credit_allowed).and_return(100)
Expand Down