修改結帳流程

舉例來說,若我們想要移除 address 和 delivery 兩步驟,那麼我們可以對 Spree::Order 加 decorator 進行以下修改

Spree::Order.class_eval do
  remove_checkout_step :address
  remove_checkout_step :delivery
end

少掉了兩個步驟之後,你可能需要兩個 callback,一個是在進入結帳頁時(因為 payment 變成第一個步驟了,所以在進入結帳頁就會發生),一個是在離開結帳頁時,準確的說,是發生在 order.next 時。

以下是新增兩個 callback 的程式碼,其中 setup_payment 是進入結帳頁時會執行。

Spree::Order.class_eval do
  remove_checkout_step :address
  remove_checkout_step :delivery

  state_machine.before_transition to: :payment, do: :setup_payment
  state_machine.before_transition from: :payment, do: :from_payment

  def setup_payment
  end

  def from_payment
  end
end

關於 @order.next,Spree 使用了 state machines 來做狀態管理。

Spree 定義了一個行為叫做 next,用來做訂單狀態之間的切換。當 order 出問題時,我們可能希望要維持原狀態並且做 rollback。

state machines 會根據 callback 的傳回值來判斷是否成功,若成功則傳回 true,如果我們希望讓他不要成功的話,就要傳回 false。

參考 Spree 原始碼 Spree::CheckoutController 中的 update 方法,會發現如果 order.next 失敗的話會進入錯誤處理流程。

module Spree
  class CheckoutController < Spree::StoreController

    ...

    def update
      if @order.update_from_params(params, permitted_checkout_attributes, request.headers.env)
        @order.temporary_address = !params[:save_user_address]
        unless @order.next
          flash[:error] = @order.errors.full_messages.join("\n")
          redirect_to(checkout_state_path(@order.state)) && return
        end

        if @order.completed?
          @current_order = nil
          flash.notice = Spree.t(:order_processed_successfully)
          flash['order_completed'] = true
          redirect_to completion_route
        else
          redirect_to checkout_state_path(@order.state)
        end
      else
        render :edit
      end
    end

    ...

  end
end

為了使 order 發生錯誤時能夠順利進入錯誤處理流程,我們應該要這樣寫:

Spree::Order.class_eval do
  remove_checkout_step :address
  remove_checkout_step :delivery

  state_machine.before_transition to: :payment, do: :setup_payment
  state_machine.before_transition from: :payment, do: :from_payment

  def setup_payment
  end

  def from_payment

    ...

    self.errors.empty?
  end
end

在 from_payment 的最後一行加上 self.errors.empty? 可以確保當 order 出錯的時候會進入錯誤處理流程。

to_delivery 做的事

  • 刪除所有的 shipments 之後
    • 對所有 line_item 建立對應的 inventory_units
      • 根據 stock_locations 來建立新的 shipments
        • Coordinator
        • InventoryUnitBuilder
        • Packer
        • Package
        • ContentItem
        • Prioritizer
        • Adjuster
        • Estimator

results matching ""

    No results matching ""