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

Interfaces for persist_user_credit_card and assign_default_credit_card #1086

Merged
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 CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
## Solidus 1.4.0 (master, unreleased)

* Make some 'wallet' behavior configurable

NOTE: `Order#persist_user_credit_card` has been renamed to
`Order#add_payment_sources_to_wallet`. If you are overriding
`persist_user_credit_card` you need to update your code.

The following extension points have been added for customizing 'wallet'
behavior.

* Spree::Config.add_payment_sources_to_wallet_class
* Spree::Config.default_payment_builder_class

https://github.com/solidusio/solidus/pull/1086

* Backend: UI, Remove icons from buttons and tabs

* Backend: Deprecate args/options that add icons to buttons
Expand Down
22 changes: 22 additions & 0 deletions core/app/models/spree/app_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,28 @@ def order_merger_class
@order_merger_class ||= Spree::OrderMerger
end

# Allows providing your own class for adding default payments to a user's
# order from their "wallet".
#
# @!attribute [rw] default_payment_builder_class
# @return [Class] a class with the same public interfaces as
# Spree::Wallet::DefaultPaymentBuilder.
attr_writer :default_payment_builder_class
def default_payment_builder_class
@default_payment_builder_class ||= Spree::Wallet::DefaultPaymentBuilder
end

# Allows providing your own class for adding payment sources to a user's
# "wallet" after an order moves to the complete state.
#
# @!attribute [rw] add_payment_sources_to_wallet_class
# @return [Class] a class with the same public interfaces
# as Spree::Wallet::AddPaymentSourcesToWallet.
attr_writer :add_payment_sources_to_wallet_class
def add_payment_sources_to_wallet_class
@add_payment_sources_to_wallet_class ||= Spree::Wallet::AddPaymentSourcesToWallet
end

def static_model_preferences
@static_model_preferences ||= Spree::Preferences::StaticModelPreferences.new
end
Expand Down
31 changes: 17 additions & 14 deletions core/app/models/spree/order/checkout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def self.define_state_machine!
transition to: :payment, from: :confirm
end

after_transition to: :complete, do: :persist_user_credit_card
after_transition to: :complete, do: :add_payment_sources_to_wallet
before_transition to: :payment, do: :set_shipments_cost
before_transition to: :payment, do: :create_tax_charge!
before_transition to: :payment, do: :assign_default_credit_card
Expand Down Expand Up @@ -309,22 +309,25 @@ def persist_user_address!
end
end

def persist_user_credit_card
if !temporary_credit_card && user_id && valid_credit_cards.present?
default_cc = valid_credit_cards.first
# TODO: target for refactoring -- why is order checkout responsible for the user -> credit_card relationship?
default_cc.user_id = user_id
default_cc.default = true
default_cc.save
end
def add_payment_sources_to_wallet
Spree::Config.
add_payment_sources_to_wallet_class.new(self).
add_to_wallet
end
alias_method :persist_user_credit_card, :add_payment_sources_to_wallet
deprecate :persist_user_credit_card

def assign_default_credit_card
if payments.from_credit_card.count == 0 && user && user.default_credit_card.try(:valid?)
cc = user.default_credit_card
payments.create!(payment_method_id: cc.payment_method_id, source: cc)
# this is one of 2 places still using User#bill_address
self.bill_address ||= user.default_credit_card.address || user.bill_address
builder = Spree::Config.default_payment_builder_class.new(self)

if payment = builder.build
payments << payment

if bill_address.nil?
# this is one of 2 places still using User#bill_address
self.bill_address = payment.source.try(:address) ||
user.bill_address
end
end
end

Expand Down
29 changes: 29 additions & 0 deletions core/app/models/spree/wallet/add_payment_sources_to_wallet.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This class is responsible for saving payment sources in the user's "wallet"
# for future use. You can substitute your own class via
# `Spree::Config.add_payment_sources_to_wallet_class`.
class Spree::Wallet::AddPaymentSourcesToWallet
def initialize(order)
@order = order
end

# This is called after an order transistions to complete and should save the
# order's payment source/s in the user's "wallet" for future use.
#
# @return [undefined]
def add_to_wallet
if !order.temporary_credit_card &&
order.user_id &&
order.valid_credit_cards.present?
# arbitrarily pick the first one for the default
default_cc = order.valid_credit_cards.first
# TODO: target for refactoring -- why is order checkout responsible for the user -> credit_card relationship?
default_cc.user_id = order.user_id
default_cc.default = true
default_cc.save
end
end

private

attr_reader :order
end
26 changes: 26 additions & 0 deletions core/app/models/spree/wallet/default_payment_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This class is responsible for building a default payment on an order, using a
# payment source that is already in the user's "wallet".
class Spree::Wallet::DefaultPaymentBuilder
def initialize(order)
@order = order
end

# Build a payment to be added to an order prior to moving into the "payment"
# state.
#
# @return [Payment] the unsaved payment to be added, or nil if none.
def build
credit_card = order.user.try!(:default_credit_card)

if credit_card.try!(:valid?) && order.payments.from_credit_card.count == 0
Spree::Payment.new(
payment_method_id: credit_card.payment_method_id,
source: credit_card,
)
end
end

private

attr_reader :order
end