4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# File 'app/models/spree/order/checkout.rb', line 4
def self.included(klass)
klass.class_eval do
class_attribute :next_event_transitions
class_attribute :previous_states
class_attribute :checkout_flow
class_attribute :checkout_steps
def self.checkout_flow(&block)
if block_given?
@checkout_flow = block
define_state_machine!
else
@checkout_flow
end
end
def self.define_state_machine!
self.checkout_steps = ActiveSupport::OrderedHash.new
self.next_event_transitions = []
self.previous_states = [:cart]
instance_eval(&checkout_flow)
klass = self
StateMachine::Machine.ignore_method_conflicts = true
state_machines.clear if respond_to?(:state_machines)
state_machine :state, :initial => :cart do
klass.next_event_transitions.each { |t| transition(t.merge(:on => :next)) }
after_transition do |order|
order.state = order.state
order.save
end
event :cancel do
transition :to => :canceled, :if => :allow_cancel?
end
event :return do
transition :to => :returned, :from => :awaiting_return
end
event :resume do
transition :to => :resumed, :from => :canceled, :if => :allow_resume?
end
event :authorize_return do
transition :to => :awaiting_return
end
before_transition :to => :complete do |order|
begin
order.process_payments!
rescue Spree::Core::GatewayError
!!Spree::Config[:allow_checkout_on_gateway_error]
end
end
before_transition :to => :delivery, :do => :remove_invalid_shipments!
after_transition :to => :complete, :do => :finalize!
after_transition :to => :delivery, :do => :create_tax_charge!
after_transition :to => :resumed, :do => :after_resume
after_transition :to => :canceled, :do => :after_cancel
after_transition :from => :delivery, :do => :create_shipment!
end
end
def self.go_to_state(name, options={})
self.checkout_steps[name] = options
if options[:if]
previous_states.each do |state|
add_transition({:from => state, :to => name}.merge(options))
end
self.previous_states << name
else
previous_states.each do |state|
add_transition({:from => state, :to => name}.merge(options))
end
self.previous_states = [name]
end
end
def self.remove_transition(options={})
if transition = find_transition(options)
self.next_event_transitions.delete(transition)
end
end
def self.find_transition(options={})
self.next_event_transitions.detect do |transition|
transition[options[:from].to_sym] == options[:to].to_sym
end
end
def self.next_event_transitions
@next_event_transitions ||= []
end
def self.checkout_steps
@checkout_steps ||= ActiveSupport::OrderedHash.new
end
def self.add_transition(options)
self.next_event_transitions << { options.delete(:from) => options.delete(:to) }.merge(options)
end
def checkout_steps
checkout_steps = []
self.class.checkout_steps.each do |step, options|
if options[:if]
next unless options[:if].call(self)
end
checkout_steps << step
end
checkout_steps.map(&:to_s)
end
end
end
|