Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Commit

Permalink
Merge pull request #48 from solidusio/transaction_import_state_advancing
Browse files Browse the repository at this point in the history
Pass order state to transaction import
  • Loading branch information
adammathys authored Apr 18, 2017
2 parents 881ae01 + 70de643 commit df6808d
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 33 deletions.
4 changes: 2 additions & 2 deletions app/models/solidus_paypal_braintree/source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class Source < ApplicationRecord

belongs_to :customer, class_name: "SolidusPaypalBraintree::Customer"

scope :with_payment_profile, -> { joins(:customer) }
scope :credit_card, -> { where(payment_type: CREDIT_CARD) }
scope(:with_payment_profile, -> { joins(:customer) })
scope(:credit_card, -> { where(payment_type: CREDIT_CARD) })

delegate :last_4, :card_type, to: :braintree_payment_method, allow_nil: true

Expand Down
1 change: 0 additions & 1 deletion app/models/solidus_paypal_braintree/transaction.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'active_model'
require 'solidus_paypal_braintree/transaction_address'

module SolidusPaypalBraintree
class Transaction
Expand Down
35 changes: 24 additions & 11 deletions app/models/solidus_paypal_braintree/transaction_import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def user
order.user
end

def import!
def import!(end_state)
if valid?
order.email = user.try!(:email) || transaction.email

Expand All @@ -43,20 +43,14 @@ def import!
# work around a bug in most solidus versions
# about tax zone cachine between address changes
order.instance_variable_set("@tax_zone", nil)
order.next
end

if order.checkout_steps.index("payment") > (order.checkout_steps.index(order.state) || 0)
advance_order "payment"
end

order.payments.new source: source,
payment = order.payments.new source: source,
payment_method: transaction.payment_method,
amount: order.total

order.save!

advance_order
advance_order(payment, end_state)
else
raise InvalidImportError,
"Validation failed: #{errors.full_messages.join(', ')}"
Expand All @@ -69,10 +63,29 @@ def address
end
end

def state_before_current?(state)
steps = order.checkout_steps
steps.index(state) < (steps.index(order.state) || 0)
end

protected

def advance_order(state = "confirm")
order.next! until order.state == state
def advance_order(payment, end_state)
return if state_before_current?(end_state)

until order.state == end_state
order.next!
update_payment_total(payment) if order.payment?
end
end

def update_payment_total(payment)
payment_total = order.payments.where(state: %w[checkout pending]).sum(:amount)
remaining_total = order.outstanding_balance - payment_total

if remaining_total > 0
payment.update!(amount: payment.amount + remaining_total)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def create

respond_to do |format|
if import.valid?
import.import!
import.import!(import_state)

format.html { redirect_to redirect_url(import) }
format.json { render json: { redirectUrl: redirect_url(import) } }
Expand All @@ -32,6 +32,10 @@ def create

private

def import_state
params[:state] || 'confirm'
end

def import_error(import)
raise InvalidImportError,
"Import invalid: #{import.errors.full_messages.join(', ')}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,27 @@
RSpec.describe SolidusPaypalBraintree::TransactionsController, type: :controller do
routes { SolidusPaypalBraintree::Engine.routes }

include_context "order ready for payment"
let!(:country) { create :country }
let!(:state) { create :state, abbr: 'WA', country: country }
let(:user) { create :user }
let(:line_item) { create :line_item, price: 50 }
let(:address) { create :address, country: country }
let(:order) do
Spree::Order.create!(
line_items: [line_item],
email: '[email protected]',
bill_address: address,
ship_address: address,
user: user
)
end

let(:payment_method) { create_gateway }

before do
allow(controller).to receive(:spree_current_user) { user }
allow(controller).to receive(:current_order) { order }
create :shipping_method, cost: 5
end

cassette_options = { cassette_name: "transactions_controller/create" }
Expand Down Expand Up @@ -58,6 +72,22 @@
expect(order.payments.first.amount).to eq 55
end

context "no end state is provided" do
it "advances the order to confirm" do
post_create
expect(order).to be_confirm
end
end

context "end state provided is delivery" do
let(:params) { super().merge(state: 'delivery') }

it "advances the order to delivery" do
post_create
expect(order).to be_delivery
end
end

context "and an address is provided" do
it "creates a new address" do
# Creating the order also creates 3 addresses, we want to make sure
Expand Down
51 changes: 34 additions & 17 deletions spec/models/solidus_paypal_braintree/transaction_import_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
let(:payment_method) { create_gateway }
let(:country) { create :country, iso: 'US', states_required: true }
let(:transaction_address) { nil }
let(:end_state) { 'confirm' }

let(:transaction) do
SolidusPaypalBraintree::Transaction.new nonce: 'fake-valid-nonce',
Expand All @@ -104,30 +105,46 @@
and_return("ABCD1234")
end

subject { described_class.new(order, transaction).import! }
subject { described_class.new(order, transaction).import!(end_state) }

context "passes validation", vcr: { cassette_name: 'transaction/import/valid' } do
it 'advances order to confirm state' do
subject
expect(order.state).to eq 'confirm'
end
context "order end state is confirm" do
it 'advances order to confirm state' do
subject
expect(order.state).to eq 'confirm'
end

it 'has a payment for the cost of line items + shipment' do
subject
expect(order.payments.first.amount).to eq 15
end

it 'is complete and capturable', aggregate_failures: true,
vcr: { cassette_name: 'transaction/import/valid/capture' } do
subject
order.complete

expect(order).to be_complete
expect(order.payments.first).to be_pending

it 'has a payment for the cost of line items + shipment' do
subject
expect(order.payments.first.amount).to eq 15
order.payments.first.capture!
# need to reload, as capture will update the order
expect(order.reload).to be_paid
end
end

it 'is complete and capturable', aggregate_failures: true,
vcr: { cassette_name: 'transaction/import/valid/capture' } do
subject
order.complete
context "order end state is delivery" do
let(:end_state) { 'delivery' }

expect(order).to be_complete
expect(order.payments.first).to be_pending
it "advances the order to delivery" do
subject
expect(order.state).to eq 'delivery'
end

order.payments.first.capture!
# need to reload, as capture will update the order
expect(order.reload).to be_paid
it "has a payment for the cost of line items" do
subject
expect(order.payments.first.amount).to eq 10
end
end

context 'transaction has address' do
Expand Down

0 comments on commit df6808d

Please sign in to comment.