solidus_core 2.1.1 → 2.2.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +0 -1
- data/app/assets/config/solidus_core_manifest.js +1 -0
- data/app/assets/javascripts/spree.js.erb +72 -0
- data/app/helpers/spree/store_helper.rb +5 -0
- data/app/jobs/spree/promotion_code_batch_job.rb +24 -0
- data/app/mailers/spree/promotion_code_batch_mailer.rb +13 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +1 -1
- data/app/models/concerns/spree/ordered_property_value_list.rb +2 -2
- data/app/models/concerns/spree/user_address_book.rb +4 -4
- data/app/models/concerns/spree/user_methods.rb +7 -0
- data/app/models/concerns/spree/user_payment_source.rb +12 -5
- data/app/models/spree/address.rb +14 -3
- data/app/models/spree/adjustment.rb +13 -1
- data/app/models/spree/app_configuration.rb +0 -19
- data/app/models/spree/base.rb +2 -0
- data/app/models/spree/credit_card.rb +34 -43
- data/app/models/spree/gateway/bogus.rb +1 -1
- data/app/models/spree/gateway.rb +6 -4
- data/app/models/spree/inventory_unit.rb +3 -2
- data/app/models/spree/order/checkout.rb +187 -273
- data/app/models/spree/order.rb +137 -71
- data/app/models/spree/order_contents.rb +1 -1
- data/app/models/spree/order_inventory.rb +11 -11
- data/app/models/spree/order_promotion.rb +2 -0
- data/app/models/spree/order_update_attributes.rb +1 -8
- data/app/models/spree/order_updater.rb +67 -63
- data/app/models/spree/payment.rb +0 -1
- data/app/models/spree/payment_create.rb +27 -7
- data/app/models/spree/payment_method/store_credit.rb +3 -3
- data/app/models/spree/payment_method.rb +4 -1
- data/app/models/spree/payment_source.rb +45 -0
- data/app/models/spree/product/scopes.rb +24 -24
- data/app/models/spree/product.rb +4 -4
- data/app/models/spree/promotion.rb +2 -0
- data/app/models/spree/promotion_code/batch_builder.rb +63 -0
- data/app/models/spree/promotion_code.rb +1 -0
- data/app/models/spree/promotion_code_batch.rb +25 -0
- data/app/models/spree/promotion_handler/cart.rb +2 -2
- data/app/models/spree/promotion_handler/coupon.rb +1 -2
- data/app/models/spree/promotion_handler/free_shipping.rb +32 -21
- data/app/models/spree/promotion_handler/page.rb +1 -1
- data/app/models/spree/reimbursement.rb +1 -1
- data/app/models/spree/return_authorization.rb +0 -28
- data/app/models/spree/return_item.rb +1 -1
- data/app/models/spree/shipment.rb +4 -4
- data/app/models/spree/shipping_method.rb +2 -2
- data/app/models/spree/shipping_rate.rb +1 -1
- data/app/models/spree/stock/availability_validator.rb +16 -17
- data/app/models/spree/stock/coordinator.rb +3 -3
- data/app/models/spree/stock/package.rb +1 -1
- data/app/models/spree/stock/quantifier.rb +5 -4
- data/app/models/spree/stock_location.rb +2 -2
- data/app/models/spree/store.rb +2 -2
- data/app/models/spree/store_credit.rb +1 -1
- data/app/models/spree/tax/tax_helpers.rb +3 -3
- data/app/models/spree/tax_rate.rb +7 -1
- data/app/models/spree/taxonomy.rb +1 -1
- data/app/models/spree/variant/scopes.rb +5 -5
- data/app/models/spree/variant/vat_price_generator.rb +8 -5
- data/app/models/spree/variant.rb +1 -0
- data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +19 -10
- data/app/models/spree/wallet/default_payment_builder.rb +6 -6
- data/app/models/spree/wallet.rb +71 -0
- data/app/models/spree/wallet_payment_source.rb +17 -0
- data/app/models/spree/zone.rb +1 -1
- data/app/views/spree/carton_mailer/shipped_email.text.erb +1 -1
- data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
- data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
- data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -7
- data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -5
- data/app/views/spree/shared/_error_messages.html.erb +1 -1
- data/app/views/spree/shipment_mailer/shipped_email.html.erb +1 -1
- data/config/initializers/assets.rb +1 -1
- data/config/initializers/friendly_id.rb +1 -1
- data/config/locales/en.yml +50 -12
- data/db/default/spree/store_credit.rb +2 -1
- data/db/migrate/20130826062534_add_depth_to_spree_taxons.rb +4 -6
- data/db/migrate/20160420044191_create_spree_wallet_payment_sources.rb +23 -0
- data/db/migrate/20160420181916_migrate_credit_cards_to_wallet_payment_sources.rb +26 -0
- data/db/migrate/20161017102621_create_spree_promotion_code_batch.rb +36 -0
- data/db/migrate/20161129035810_add_index_to_spree_payments_number.rb +5 -0
- data/db/migrate/20170223235001_remove_spree_store_credits_column.rb +5 -0
- data/lib/generators/spree/dummy/templates/rails/application.rb +1 -1
- data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
- data/lib/generators/spree/install/install_generator.rb +6 -5
- data/lib/spree/core/controller_helpers/payment_parameters.rb +54 -0
- data/lib/spree/core/engine.rb +6 -9
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +0 -1
- data/lib/spree/money.rb +18 -0
- data/lib/spree/permission_sets/default_customer.rb +1 -1
- data/lib/spree/permitted_attributes.rb +1 -1
- data/lib/spree/testing_support/authorization_helpers.rb +1 -0
- data/lib/spree/testing_support/capybara_ext.rb +13 -0
- data/lib/spree/testing_support/factories/order_factory.rb +5 -1
- data/lib/spree/testing_support/factories/payment_factory.rb +1 -1
- data/lib/spree/testing_support/factories/shipment_factory.rb +0 -1
- data/solidus_core.gemspec +3 -3
- data/spec/jobs/promotion_code_batch_job_spec.rb +65 -0
- data/spec/lib/calculated_adjustments_spec.rb +105 -1
- data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +4 -1
- data/spec/lib/spree/core/testing_support/factories/payment_factory_spec.rb +8 -0
- data/spec/lib/spree/money_spec.rb +32 -0
- data/spec/lib/spree/permission_sets/default_customer_spec.rb +20 -0
- data/spec/mailers/promotion_code_batch_mailer_spec.rb +45 -0
- data/spec/models/spree/credit_card_spec.rb +86 -86
- data/spec/models/spree/gateway_spec.rb +3 -1
- data/spec/models/spree/inventory_unit_spec.rb +12 -4
- data/spec/models/spree/order/checkout_spec.rb +11 -32
- data/spec/models/spree/order/tax_spec.rb +2 -2
- data/spec/models/spree/order_contents_spec.rb +24 -1
- data/spec/models/spree/order_inventory_spec.rb +130 -83
- data/spec/models/spree/order_spec.rb +15 -117
- data/spec/models/spree/order_update_attributes_spec.rb +1 -44
- data/spec/models/spree/order_updater_spec.rb +10 -13
- data/spec/models/spree/payment_create_spec.rb +5 -1
- data/spec/models/spree/payment_method_spec.rb +16 -0
- data/spec/models/spree/payment_spec.rb +14 -8
- data/spec/models/spree/promotion_code/batch_builder_spec.rb +61 -0
- data/spec/models/spree/promotion_code_batch_spec.rb +58 -0
- data/spec/models/spree/promotion_code_spec.rb +4 -0
- data/spec/models/spree/promotion_spec.rb +3 -6
- data/spec/models/spree/return_authorization_spec.rb +0 -59
- data/spec/models/spree/shipment_spec.rb +4 -4
- data/spec/models/spree/stock/availability_validator_spec.rb +64 -9
- data/spec/models/spree/tax/item_adjuster_spec.rb +1 -2
- data/spec/models/spree/unit_cancel_spec.rb +0 -85
- data/spec/models/spree/user_spec.rb +3 -1
- data/spec/models/spree/variant/vat_price_generator_spec.rb +8 -2
- data/spec/models/spree/variant_spec.rb +16 -4
- data/spec/models/spree/wallet_payment_source_spec.rb +46 -0
- data/spec/models/spree/wallet_spec.rb +128 -0
- data/spec/support/concerns/payment_source.rb +64 -0
- metadata +51 -25
- data/app/assets/javascripts/spree.js.coffee.erb +0 -64
- data/app/models/spree/promotion_builder.rb +0 -55
- data/app/models/spree/promotion_code/code_builder.rb +0 -62
- data/config/initializers/premailer_assets.rb +0 -1
- data/lib/spree/core/unreturned_item_charger.rb +0 -106
- data/lib/tasks/exchanges.rake +0 -47
- data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -126
- data/spec/lib/tasks/exchanges_spec.rb +0 -220
- data/spec/models/spree/promotion_builder_spec.rb +0 -120
- data/spec/models/spree/promotion_code/code_builder_spec.rb +0 -77
|
@@ -2,328 +2,242 @@ module Spree
|
|
|
2
2
|
class Order < Spree::Base
|
|
3
3
|
module Checkout
|
|
4
4
|
def self.included(klass)
|
|
5
|
-
klass.
|
|
6
|
-
|
|
7
|
-
class_attribute :previous_states
|
|
8
|
-
class_attribute :checkout_flow
|
|
9
|
-
class_attribute :checkout_steps
|
|
10
|
-
class_attribute :removed_transitions
|
|
11
|
-
|
|
12
|
-
def self.checkout_flow(&block)
|
|
13
|
-
if block_given?
|
|
14
|
-
@checkout_flow = block
|
|
15
|
-
define_state_machine!
|
|
16
|
-
else
|
|
17
|
-
@checkout_flow
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def self.define_state_machine!
|
|
22
|
-
self.checkout_steps = {}
|
|
23
|
-
self.next_event_transitions = []
|
|
24
|
-
self.previous_states = [:cart]
|
|
25
|
-
self.removed_transitions = []
|
|
26
|
-
|
|
27
|
-
# Build the checkout flow using the checkout_flow defined either
|
|
28
|
-
# within the Order class, or a decorator for that class.
|
|
29
|
-
#
|
|
30
|
-
# This method may be called multiple times depending on if the
|
|
31
|
-
# checkout_flow is re-defined in a decorator or not.
|
|
32
|
-
instance_eval(&checkout_flow)
|
|
33
|
-
|
|
34
|
-
klass = self
|
|
35
|
-
|
|
36
|
-
# To avoid multiple occurrences of the same transition being defined
|
|
37
|
-
# On first definition, state_machines will not be defined
|
|
38
|
-
state_machines.clear if respond_to?(:state_machines)
|
|
39
|
-
state_machine :state, initial: :cart, use_transactions: false do
|
|
40
|
-
klass.next_event_transitions.each { |t| transition(t.merge(on: :next)) }
|
|
41
|
-
|
|
42
|
-
# Persist the state on the order
|
|
43
|
-
after_transition do |order, transition|
|
|
44
|
-
order.state = order.state
|
|
45
|
-
order.state_changes.create(
|
|
46
|
-
previous_state: transition.from,
|
|
47
|
-
next_state: transition.to,
|
|
48
|
-
name: 'order',
|
|
49
|
-
user_id: order.user_id
|
|
50
|
-
)
|
|
51
|
-
order.save
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
event :cancel do
|
|
55
|
-
transition to: :canceled, if: :allow_cancel?
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
event :return do
|
|
59
|
-
transition to: :returned, from: [:returned, :complete, :awaiting_return, :canceled], if: :all_inventory_units_returned?
|
|
60
|
-
end
|
|
5
|
+
klass.extend ClassMethods
|
|
6
|
+
end
|
|
61
7
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
8
|
+
module ClassMethods
|
|
9
|
+
attr_accessor :next_event_transitions
|
|
10
|
+
attr_accessor :previous_states
|
|
11
|
+
attr_accessor :checkout_steps
|
|
12
|
+
attr_accessor :removed_transitions
|
|
65
13
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
14
|
+
def checkout_flow(&block)
|
|
15
|
+
if block_given?
|
|
16
|
+
@checkout_flow = block
|
|
17
|
+
define_state_machine!
|
|
18
|
+
else
|
|
19
|
+
@checkout_flow
|
|
20
|
+
end
|
|
21
|
+
end
|
|
69
22
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
23
|
+
def define_state_machine!
|
|
24
|
+
self.checkout_steps = {}
|
|
25
|
+
self.next_event_transitions = []
|
|
26
|
+
self.previous_states = [:cart]
|
|
27
|
+
self.removed_transitions = []
|
|
73
28
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
29
|
+
# Build the checkout flow using the checkout_flow defined either
|
|
30
|
+
# within the Order class, or a decorator for that class.
|
|
31
|
+
#
|
|
32
|
+
# This method may be called multiple times depending on if the
|
|
33
|
+
# checkout_flow is re-defined in a decorator or not.
|
|
34
|
+
instance_eval(&checkout_flow)
|
|
35
|
+
|
|
36
|
+
klass = self
|
|
37
|
+
|
|
38
|
+
# To avoid multiple occurrences of the same transition being defined
|
|
39
|
+
# On first definition, state_machines will not be defined
|
|
40
|
+
state_machines.clear if respond_to?(:state_machines)
|
|
41
|
+
state_machine :state, initial: :cart, use_transactions: false do
|
|
42
|
+
klass.next_event_transitions.each { |t| transition(t.merge(on: :next)) }
|
|
43
|
+
|
|
44
|
+
# Persist the state on the order
|
|
45
|
+
after_transition do |order, transition|
|
|
46
|
+
order.state = order.state
|
|
47
|
+
order.state_changes.create(
|
|
48
|
+
previous_state: transition.from,
|
|
49
|
+
next_state: transition.to,
|
|
50
|
+
name: 'order',
|
|
51
|
+
user_id: order.user_id
|
|
52
|
+
)
|
|
53
|
+
order.save
|
|
54
|
+
end
|
|
78
55
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
56
|
+
event :cancel do
|
|
57
|
+
transition to: :canceled, if: :allow_cancel?
|
|
58
|
+
end
|
|
82
59
|
|
|
83
|
-
|
|
60
|
+
event :return do
|
|
61
|
+
transition to: :returned, from: [:returned, :complete, :awaiting_return, :canceled], if: :all_inventory_units_returned?
|
|
62
|
+
end
|
|
84
63
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
64
|
+
event :resume do
|
|
65
|
+
transition to: :resumed, from: :canceled, if: :canceled?
|
|
66
|
+
end
|
|
88
67
|
|
|
89
|
-
|
|
68
|
+
event :authorize_return do
|
|
69
|
+
transition to: :awaiting_return
|
|
70
|
+
end
|
|
90
71
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
end
|
|
72
|
+
event :complete do
|
|
73
|
+
transition to: :complete, from: :confirm
|
|
74
|
+
end
|
|
95
75
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
before_transition to: :delivery, do: :ensure_available_shipping_rates
|
|
100
|
-
before_transition to: :delivery, do: :set_shipments_cost
|
|
101
|
-
before_transition from: :delivery, do: :apply_free_shipping_promotions
|
|
76
|
+
if states[:payment]
|
|
77
|
+
event :payment_failed do
|
|
78
|
+
transition to: :payment, from: :confirm
|
|
102
79
|
end
|
|
103
80
|
|
|
104
|
-
|
|
105
|
-
before_transition to: :
|
|
81
|
+
after_transition to: :complete, do: :add_payment_sources_to_wallet
|
|
82
|
+
before_transition to: :payment, do: :add_default_payment_from_wallet
|
|
106
83
|
|
|
107
|
-
|
|
108
|
-
# calls matter so that we do not process payments
|
|
109
|
-
# until validations have passed
|
|
110
|
-
before_transition to: :complete, do: :validate_line_item_availability, unless: :unreturned_exchange?
|
|
111
|
-
if states[:delivery]
|
|
112
|
-
before_transition to: :complete, do: :ensure_available_shipping_rates
|
|
113
|
-
end
|
|
114
|
-
before_transition to: :complete, do: :ensure_promotions_eligible
|
|
115
|
-
before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted
|
|
116
|
-
before_transition to: :complete, do: :ensure_inventory_units, unless: :unreturned_exchange?
|
|
117
|
-
if states[:payment]
|
|
118
|
-
before_transition to: :complete, do: :process_payments_before_complete
|
|
119
|
-
end
|
|
84
|
+
before_transition to: :confirm, do: :add_store_credit_payments
|
|
120
85
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
86
|
+
# see also process_payments_before_complete below which needs to
|
|
87
|
+
# be added in the correct sequence.
|
|
88
|
+
end
|
|
124
89
|
|
|
125
|
-
|
|
126
|
-
order.update_totals
|
|
127
|
-
order.persist_totals
|
|
128
|
-
end
|
|
90
|
+
before_transition from: :cart, do: :ensure_line_items_present
|
|
129
91
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
92
|
+
if states[:address]
|
|
93
|
+
before_transition to: :address, do: :assign_default_addresses!
|
|
94
|
+
before_transition from: :address, do: :persist_user_address!
|
|
95
|
+
end
|
|
133
96
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
97
|
+
if states[:delivery]
|
|
98
|
+
before_transition to: :delivery, do: :ensure_shipping_address
|
|
99
|
+
before_transition to: :delivery, do: :create_proposed_shipments
|
|
100
|
+
before_transition to: :delivery, do: :ensure_available_shipping_rates
|
|
101
|
+
before_transition from: :delivery, do: :apply_free_shipping_promotions
|
|
137
102
|
end
|
|
138
103
|
|
|
139
|
-
|
|
140
|
-
|
|
104
|
+
before_transition to: :resumed, do: :ensure_line_item_variants_are_not_deleted
|
|
105
|
+
before_transition to: :resumed, do: :validate_line_item_availability
|
|
141
106
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
107
|
+
# Sequence of before_transition to: :complete
|
|
108
|
+
# calls matter so that we do not process payments
|
|
109
|
+
# until validations have passed
|
|
110
|
+
before_transition to: :complete, do: :validate_line_item_availability
|
|
111
|
+
if states[:delivery]
|
|
112
|
+
before_transition to: :complete, do: :ensure_available_shipping_rates
|
|
146
113
|
end
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
114
|
+
before_transition to: :complete, do: :ensure_promotions_eligible
|
|
115
|
+
before_transition to: :complete, do: :ensure_line_item_variants_are_not_deleted
|
|
116
|
+
before_transition to: :complete, do: :ensure_inventory_units
|
|
117
|
+
if states[:payment]
|
|
118
|
+
before_transition to: :complete, do: :process_payments_before_complete
|
|
151
119
|
end
|
|
152
|
-
end
|
|
153
120
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
after = checkout_steps.keys.last unless before || after
|
|
158
|
-
|
|
159
|
-
cloned_steps = checkout_steps.clone
|
|
160
|
-
cloned_removed_transitions = removed_transitions.clone
|
|
161
|
-
checkout_flow do
|
|
162
|
-
cloned_steps.each_pair do |key, value|
|
|
163
|
-
go_to_state(name, options) if key == before
|
|
164
|
-
go_to_state(key, value)
|
|
165
|
-
go_to_state(name, options) if key == after
|
|
166
|
-
end
|
|
167
|
-
cloned_removed_transitions.each do |transition|
|
|
168
|
-
remove_transition(transition)
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end
|
|
121
|
+
after_transition to: :complete, do: :finalize!
|
|
122
|
+
after_transition to: :resumed, do: :after_resume
|
|
123
|
+
after_transition to: :canceled, do: :after_cancel
|
|
172
124
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
cloned_removed_transitions = removed_transitions.clone
|
|
176
|
-
checkout_flow do
|
|
177
|
-
cloned_steps.each_pair do |key, value|
|
|
178
|
-
go_to_state(key, value) unless key == name
|
|
179
|
-
end
|
|
180
|
-
cloned_removed_transitions.each do |transition|
|
|
181
|
-
remove_transition(transition)
|
|
182
|
-
end
|
|
125
|
+
after_transition from: any - :cart, to: any - [:confirm, :complete] do |order|
|
|
126
|
+
order.update!
|
|
183
127
|
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def self.remove_transition(options = {})
|
|
187
|
-
removed_transitions << options
|
|
188
|
-
next_event_transitions.delete(find_transition(options))
|
|
189
|
-
end
|
|
190
128
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
next_event_transitions.detect do |transition|
|
|
194
|
-
transition[options[:from].to_sym] == options[:to].to_sym
|
|
129
|
+
after_transition do |order, transition|
|
|
130
|
+
order.logger.debug "Order #{order.number} transitioned from #{transition.from} to #{transition.to} via #{transition.event}"
|
|
195
131
|
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def self.next_event_transitions
|
|
199
|
-
@next_event_transitions ||= []
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def self.checkout_steps
|
|
203
|
-
@checkout_steps ||= {}
|
|
204
|
-
end
|
|
205
132
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
def self.add_transition(options)
|
|
211
|
-
next_event_transitions << { options.delete(:from) => options.delete(:to) }.merge(options)
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def checkout_steps
|
|
215
|
-
steps = self.class.checkout_steps.each_with_object([]) { |(step, options), checkout_steps|
|
|
216
|
-
next if options.include?(:if) && !options[:if].call(self)
|
|
217
|
-
checkout_steps << step
|
|
218
|
-
}.map(&:to_s)
|
|
219
|
-
# Ensure there is always a complete step
|
|
220
|
-
steps << "complete" unless steps.include?("complete")
|
|
221
|
-
steps
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def has_checkout_step?(step)
|
|
225
|
-
step.present? && checkout_steps.include?(step)
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def passed_checkout_step?(step)
|
|
229
|
-
has_checkout_step?(step) && checkout_step_index(step) < checkout_step_index(state)
|
|
133
|
+
after_failure do |order, transition|
|
|
134
|
+
order.logger.debug "Order #{order.number} halted transition on event #{transition.event} state #{transition.from}: #{order.errors.full_messages.join}"
|
|
135
|
+
end
|
|
230
136
|
end
|
|
137
|
+
end
|
|
231
138
|
|
|
232
|
-
|
|
233
|
-
|
|
139
|
+
def go_to_state(name, options = {})
|
|
140
|
+
checkout_steps[name] = options
|
|
141
|
+
previous_states.each do |state|
|
|
142
|
+
add_transition({ from: state, to: name }.merge(options))
|
|
234
143
|
end
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
144
|
+
if options[:if]
|
|
145
|
+
previous_states << name
|
|
146
|
+
else
|
|
147
|
+
self.previous_states = [name]
|
|
238
148
|
end
|
|
149
|
+
end
|
|
239
150
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
151
|
+
def insert_checkout_step(name, options = {})
|
|
152
|
+
before = options.delete(:before)
|
|
153
|
+
after = options.delete(:after) unless before
|
|
154
|
+
after = checkout_steps.keys.last unless before || after
|
|
155
|
+
|
|
156
|
+
cloned_steps = checkout_steps.clone
|
|
157
|
+
cloned_removed_transitions = removed_transitions.clone
|
|
158
|
+
checkout_flow do
|
|
159
|
+
cloned_steps.each_pair do |key, value|
|
|
160
|
+
go_to_state(name, options) if key == before
|
|
161
|
+
go_to_state(key, value)
|
|
162
|
+
go_to_state(name, options) if key == after
|
|
163
|
+
end
|
|
164
|
+
cloned_removed_transitions.each do |transition|
|
|
165
|
+
remove_transition(transition)
|
|
166
|
+
end
|
|
243
167
|
end
|
|
168
|
+
end
|
|
244
169
|
|
|
245
|
-
|
|
246
|
-
|
|
170
|
+
def remove_checkout_step(name)
|
|
171
|
+
cloned_steps = checkout_steps.clone
|
|
172
|
+
cloned_removed_transitions = removed_transitions.clone
|
|
173
|
+
checkout_flow do
|
|
174
|
+
cloned_steps.each_pair do |key, value|
|
|
175
|
+
go_to_state(key, value) unless key == name
|
|
176
|
+
end
|
|
177
|
+
cloned_removed_transitions.each do |transition|
|
|
178
|
+
remove_transition(transition)
|
|
179
|
+
end
|
|
247
180
|
end
|
|
181
|
+
end
|
|
248
182
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
183
|
+
def remove_transition(options = {})
|
|
184
|
+
removed_transitions << options
|
|
185
|
+
next_event_transitions.delete(find_transition(options))
|
|
186
|
+
end
|
|
252
187
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
# Skip setting ship address if order doesn't have a delivery checkout step
|
|
258
|
-
# to avoid triggering validations on shipping address
|
|
259
|
-
self.ship_address ||= user.ship_address if user.ship_address.try!(:valid?) && checkout_steps.include?("delivery")
|
|
260
|
-
end
|
|
188
|
+
def find_transition(options = {})
|
|
189
|
+
return nil if options.nil? || !options.include?(:from) || !options.include?(:to)
|
|
190
|
+
next_event_transitions.detect do |transition|
|
|
191
|
+
transition[options[:from].to_sym] == options[:to].to_sym
|
|
261
192
|
end
|
|
193
|
+
end
|
|
262
194
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
end
|
|
267
|
-
end
|
|
195
|
+
def next_event_transitions
|
|
196
|
+
@next_event_transitions ||= []
|
|
197
|
+
end
|
|
268
198
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
add_to_wallet
|
|
273
|
-
end
|
|
274
|
-
alias_method :persist_user_credit_card, :add_payment_sources_to_wallet
|
|
275
|
-
deprecate :persist_user_credit_card
|
|
199
|
+
def checkout_steps
|
|
200
|
+
@checkout_steps ||= {}
|
|
201
|
+
end
|
|
276
202
|
|
|
277
|
-
|
|
278
|
-
|
|
203
|
+
def checkout_step_names
|
|
204
|
+
checkout_steps.keys
|
|
205
|
+
end
|
|
279
206
|
|
|
280
|
-
|
|
281
|
-
|
|
207
|
+
def add_transition(options)
|
|
208
|
+
next_event_transitions << { options.delete(:from) => options.delete(:to) }.merge(options)
|
|
209
|
+
end
|
|
282
210
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
end
|
|
211
|
+
def removed_transitions
|
|
212
|
+
@removed_transitions ||= []
|
|
213
|
+
end
|
|
214
|
+
end
|
|
290
215
|
|
|
291
|
-
|
|
216
|
+
def checkout_steps
|
|
217
|
+
steps = self.class.checkout_steps.each_with_object([]) { |(step, options), checkout_steps|
|
|
218
|
+
next if options.include?(:if) && !options[:if].call(self)
|
|
219
|
+
checkout_steps << step
|
|
220
|
+
}.map(&:to_s)
|
|
221
|
+
# Ensure there is always a complete step
|
|
222
|
+
steps << "complete" unless steps.include?("complete")
|
|
223
|
+
steps
|
|
224
|
+
end
|
|
292
225
|
|
|
293
|
-
|
|
294
|
-
|
|
226
|
+
def has_checkout_step?(step)
|
|
227
|
+
step.present? && checkout_steps.include?(step)
|
|
228
|
+
end
|
|
295
229
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
end
|
|
230
|
+
def passed_checkout_step?(step)
|
|
231
|
+
has_checkout_step?(step) && checkout_step_index(step) < checkout_step_index(state)
|
|
232
|
+
end
|
|
300
233
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
saved_errors = errors[:base]
|
|
305
|
-
payment_failed!
|
|
306
|
-
saved_errors.each { |error| errors.add(:base, error) }
|
|
307
|
-
false
|
|
308
|
-
end
|
|
309
|
-
end
|
|
234
|
+
def checkout_step_index(step)
|
|
235
|
+
checkout_steps.index(step).to_i
|
|
236
|
+
end
|
|
310
237
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
# {
|
|
315
|
-
# "order": {
|
|
316
|
-
# "existing_card": "2"
|
|
317
|
-
# }
|
|
318
|
-
# }
|
|
319
|
-
#
|
|
320
|
-
def update_params_payment_source
|
|
321
|
-
if @updating_params[:order] && (@updating_params[:order][:payments_attributes] || @updating_params[:order][:existing_card])
|
|
322
|
-
@updating_params[:order][:payments_attributes] ||= [{}]
|
|
323
|
-
@updating_params[:order][:payments_attributes].first[:amount] = total
|
|
324
|
-
end
|
|
325
|
-
end
|
|
326
|
-
end
|
|
238
|
+
def can_go_to_state?(state)
|
|
239
|
+
return false unless has_checkout_step?(self.state) && has_checkout_step?(state)
|
|
240
|
+
checkout_step_index(state) > checkout_step_index(self.state)
|
|
327
241
|
end
|
|
328
242
|
end
|
|
329
243
|
end
|