module Spree::Core::StateMachines::Order::ClassMethods
Attributes
checkout_steps[W]
next_event_transitions[W]
previous_states[RW]
removed_transitions[W]
Public Instance Methods
add_transition(options)
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 209 def add_transition(options) next_event_transitions << { options.delete(:from) => options.delete(:to) }.merge(options) end
checkout_flow(&block)
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 17 def checkout_flow(&block) if block_given? @checkout_flow = block define_state_machine! else @checkout_flow end end
checkout_step_names()
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 205 def checkout_step_names checkout_steps.keys end
checkout_steps()
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 201 def checkout_steps @checkout_steps ||= {} end
define_state_machine!()
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 26 def define_state_machine! self.checkout_steps = {} self.next_event_transitions = [] self.previous_states = [:cart] self.removed_transitions = [] # Build the checkout flow using the checkout_flow defined either # within the Order class, or a decorator for that class. # # This method may be called multiple times depending on if the # checkout_flow is re-defined in a decorator or not. instance_eval(&checkout_flow) klass = self # To avoid multiple occurrences of the same transition being defined # On first definition, state_machines will not be defined state_machines.clear if respond_to?(:state_machines) state_machine :state, initial: :cart, use_transactions: false do klass.next_event_transitions.each { |state| transition(state.merge(on: :next)) } # Persist the state on the order after_transition do |order, transition| order.state = order.state order.state_changes.create( previous_state: transition.from, next_state: transition.to, name: 'order', user_id: order.user_id ) order.save end event :cancel do transition to: :canceled, if: :allow_cancel?, from: :complete end event :return do transition to: :returned, from: [:complete, :awaiting_return], if: :all_inventory_units_returned? end event :resume do transition to: :resumed, from: :canceled, if: :canceled? end event :authorize_return do transition to: :awaiting_return, from: :complete end event :complete do transition to: :complete, from: klass.checkout_steps.keys.last end if states[:payment] event :payment_failed do transition to: :payment, from: :confirm end after_transition to: :complete, do: :add_payment_sources_to_wallet before_transition to: :payment, do: :add_default_payment_from_wallet before_transition to: :payment, do: :ensure_billing_address before_transition to: :confirm, do: :add_store_credit_payments # see also process_payments_before_complete below which needs to # be added in the correct sequence. end before_transition from: :cart, do: :ensure_line_items_present if states[:address] before_transition to: :address, do: :assign_default_user_addresses before_transition from: :address, do: :persist_user_address! end if states[:delivery] before_transition to: :delivery, do: :ensure_shipping_address before_transition to: :delivery, do: :create_proposed_shipments before_transition to: :delivery, do: :ensure_available_shipping_rates before_transition from: :delivery, do: :apply_shipping_promotions end before_transition to: :resumed, do: :ensure_line_item_variants_are_not_deleted before_transition to: :resumed, do: :validate_line_item_availability # Sequence of before_transition to: :complete # calls matter so that we do not process payments # until validations have passed before_transition to: :complete, do: :validate_line_item_availability before_transition to: :complete, do: :ensure_promotions_eligible before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted before_transition to: :complete, do: :ensure_inventory_units if states[:payment] before_transition to: :complete, do: :process_payments_before_complete end after_transition to: :complete, do: :finalize! after_transition to: :resumed, do: :after_resume after_transition to: :canceled, do: :after_cancel after_transition from: any - :cart, to: any - [:confirm, :complete] do |order| order.recalculate end after_transition do |order, transition| order.logger.debug "Order #{order.number} transitioned from #{transition.from} to #{transition.to} via #{transition.event}" end after_failure do |order, transition| order.logger.debug "Order #{order.number} halted transition on event #{transition.event} state #{transition.from}: #{order.errors.full_messages.join}" end end end
find_transition(options = {})
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 189 def find_transition(options = {}) return nil if options.nil? || !options.include?(:from) || !options.include?(:to) next_event_transitions.detect do |transition| transition[options[:from].to_sym] == options[:to].to_sym end end
go_to_state(name, options = {})
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 140 def go_to_state(name, options = {}) checkout_steps[name] = options previous_states.each do |state| add_transition({ from: state, to: name }.merge(options)) end if options[:if] previous_states << name else self.previous_states = [name] end end
insert_checkout_step(name, options = {})
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 152 def insert_checkout_step(name, options = {}) before = options.delete(:before) after = options.delete(:after) unless before after = checkout_steps.keys.last unless before || after cloned_steps = checkout_steps.clone cloned_removed_transitions = removed_transitions.clone checkout_flow do cloned_steps.each_pair do |key, value| go_to_state(name, options) if key == before go_to_state(key, value) go_to_state(name, options) if key == after end cloned_removed_transitions.each do |transition| remove_transition(transition) end end end
next_event_transitions()
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 197 def next_event_transitions @next_event_transitions ||= [] end
remove_checkout_step(name)
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 171 def remove_checkout_step(name) cloned_steps = checkout_steps.clone cloned_removed_transitions = removed_transitions.clone checkout_flow do cloned_steps.each_pair do |key, value| go_to_state(key, value) unless key == name end cloned_removed_transitions.each do |transition| remove_transition(transition) end end end
remove_transition(options = {})
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 184 def remove_transition(options = {}) removed_transitions << options next_event_transitions.delete(find_transition(options)) end
removed_transitions()
click to toggle source
# File lib/spree/core/state_machines/order.rb, line 213 def removed_transitions @removed_transitions ||= [] end