Skip to content

Instantly share code, notes, and snippets.

@rterbush
Last active December 16, 2015 02:49
Show Gist options
  • Save rterbush/5364940 to your computer and use it in GitHub Desktop.
Save rterbush/5364940 to your computer and use it in GitHub Desktop.
Add states to Spree::Shipment model
Spree::Shipment.class_eval do
scope :sent, -> { with_state('sent') }
scope :confirmed, -> { with_state('confirmed') }
Spree::Shipment.state_machines[:state] =
StateMachine::Machine.new(Spree::Shipment, initial: :pending, use_transactions: false) do
event :ready do
transition from: :pending, to: :ready, if: lambda { |shipment|
shipment.determine_state(shipment.order) == 'ready'
}
end
event :pend do
transition from: :ready, to: :pending
end
event :sent do
transition from: :ready, to: :sent
end
after_transition to: :sent, do: :after_sent
event :confirm do
transition from: :sent, to: :confirmed
end
after_transition to: :confirmed, do: :after_confirmed
event :ship do
transition from: :confirmed, to: :shipped
end
after_transition to: :shipped, do: :after_ship
event :cancel do
transition to: :canceled, from: [:pending, :ready]
end
after_transition to: :canceled, do: :after_cancel
event :resume do
transition from: :canceled, to: :ready, if: lambda { |shipment|
shipment.determine_state(shipment.order) == 'ready'
}
transition from: :canceled, to: :pending, if: lambda { |shipment|
shipment.determine_state(shipment.order) == 'ready'
}
transition from: :canceled, to: :pending
end
after_transition from: :canceled, to: [:pending, :ready], do: :after_resume
end
def after_confirmed
order.update!
end
def after_sent
order.update!
end
def to_package
package = Spree::Stock::Package.new(stock_location, order)
inventory_units.includes(:variant).each do |inventory_unit|
package.add inventory_unit.variant, 1, inventory_unit.state
end
package
end
# Determines the appropriate +state+ according to the following logic:
#
# pending unless order is complete and +order.payment_state+ is +paid+
# sent order sent to fulfillment
# confirmed order line_items confirmed by fulfilment
# shipped if already shipped (ie. does not change the state)
# ready all other cases
def determine_state(order)
return 'canceled' if order.canceled?
return 'pending' unless order.can_ship?
return 'pending' if inventory_units.any? &:backordered?
return 'shipped' if state == 'shipped'
return 'sent' if state == 'sent'
return 'confirmed' if state == 'confirmed'
order.paid? ? 'ready' : 'pending'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment