https://solidus.io logo
Title
j

jakemumu

05/24/2023, 10:14 PM
trying to make a conditional confirm step:
base.remove_checkout_step :confirm

        # our custom confirm step
        base.insert_checkout_step :tax_confirmation, {
          after: :payment, if: ->(order) {
            order.tax_total != 0
          }
        }
-- however this totally breaks checkout and i just get an obtuse error:
State cannot transition via next
-- any tips for debugging that?
a

Adam Mueller

05/24/2023, 11:02 PM
If I had to hazard a guess, the state machine probably doesn't handle conditional final steps very well. There's some code that injects a transition on
complete
from the final checkout step to the
completed
state, and all other checkout states transition on
next
.
But the logic to setup all of the state machine transitions just runs once, so it's unaware of the dynamic nature of that step. If you look at the events on the state machine I'd bet there isn't a transition to complete from the payment step. (That information should be in
Spree::Order.state_machines[:state].events
)
You might be able to hack in the missing transition yourself, but it probably wouldn't be the prettiest code. Something like:
base.state_machines[:state].event :complete do
  transition to: :complete, from: :payment
end
My advice would be to instead keep the final checkout step constant and handle skipping past it in your checkout controller.
☝️ 1
☝️🏼 1
j

jakemumu

05/25/2023, 1:31 AM
nice! Okay yeah thanks Adam talked to someone else at your team as well 😅 -- I tried to do the override on the checkout controller and that worked for some payment methods but not others -- i'm on the legacy frontend and stripe uses the frontend controller, but the paypal extension uses the API which then also would need to be overridden. I think i'll try the transition event cause hopefully it'd work in both places without two decorators, if it does work i think it should mention some more about that in the docs and how to create the transition events as well? I was basically just following the docs on it
Yeah this is totally the way:
base.state_machine.after_transition(to: :confirm) do |order|
          order.complete if order.tax_total.zero? && order.can_complete?
        end