I just added a step to my checkout process, and it was definitely a
matter of piecing together a lot of info from a lot of sources. The
guides don't seem to tell the whole story, and in some cases appear to
be wrong. I thought I'd list my process here, in the hopes it helps
someone, and in case I've done something wrong!
So...step 1 - redefine the state machine, as described in the guide.
However, I had to add two additional lines of code:
StateMachine::Machine.ignore_method_conflicts = true
Spree::Order.state_machines.clear
The first to suppress the conflict warnings, and the second to clear
the old state machine. So my code in app/models/order_decorator.rb
for this looks like (I added a "dates" step to the order process):
Spree::Order.class_eval do
StateMachine::Machine.ignore_method_conflicts = true
Spree::Order.state_machines.clear
# order state machine (see http://github.com/pluginaweek/state_machine/tree/master
for details)
state_machine :initial => 'cart', :use_transactions => false do
event :next do
transition :from => 'cart', :to => 'address'
transition :from => 'address', :to => 'delivery'
transition :from => 'delivery', :to => 'dates'
transition :from => 'dates', :to => 'payment', :if
=> :payment_required?
transition :from => 'dates', :to => 'complete'
transition :from => 'confirm', :to => 'complete'
# note: some payment methods will not support a confirm step
transition :from => 'payment', :to => 'confirm',
:if => Proc.new { |order|
order.payment_method &&
order.payment_method.payment_profiles_supported? }
transition :from => 'payment', :to => 'complete'
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 Core::GatewayError
if Spree::Config[:allow_checkout_on_gateway_error]
true
else
false
end
end
end
before_transition :to => ['delivery'] do |order|
order.shipments.each { |s| s.destroy unless
s.shipping_method.available_to_order?(order) }
end
after_transition :to => 'complete', :do => :finalize!
after_transition :to => 'delivery', :do => :create_tax_charge!
after_transition :to => 'payment', :do => :create_shipment!
after_transition :to => 'resumed', :do => :after_resume
after_transition :to => 'canceled', :do => :after_cancel
end
end
Ok...then, it doesn't work. I had to add a app/helpers/
checkout_helper_decorator.rb, with the following:
module Spree
module CheckoutHelper
def checkout_states
if @order.payment and
@order.payment.payment_method.payment_profiles_supported?
%w(address delivery dates payment confirm complete)
else
%w(address delivery dates payment complete)
end
end
end
end
Basically, I needed to add in my new step into the list.
Then, I needed to add a translation for my new step; contrary to what
the guide says, this needed to be something like
en:
order_state:
dates: Dates
not "checkout_states" as indicated in the guide.
Then I needed a view, which had to be in app/views/spree/checkout/
_dates.html.erb. Leaving out the "spree" folder in the middle of that
path would not work.
Anyway, if I've done something silly let me know...and hopefully this
will help someone else from having to spend so much time trying to do
this!
Greg