14 - 建立訂單

我們在check_out.html 裡面引入 order_form.html,並將 submit連到 ordercreate,所以需要 OrderControllercreate方法才能建立訂單,而且要先登入才能結帳

#web/controllers/order_controller.ex
alias ShoppingSite.Order
alias ShoppingSite.OrderItem
alias ShoppingSite.Repo

import ShoppingSite.UserController, only: [authenticate: 2]
import ShoppingSite.CartController, only: [current_cart: 1]
plug :authenticate when action in [:create]

def create(conn, %{"order" => order_params}) do

  new_order_params =
    order_params
      |> Map.put("user_id", Integer.to_string(conn.assigns.current_user.id))
      |> Map.put("total", Integer.to_string(get_total_price(conn)))

  order_changeset =
    Order.changeset(%Order{}, new_order_params)

  if order_changeset.valid? do
    case Repo.insert(order_changeset) do
      {:ok, order} ->
        build_order_item(conn, order)
        ShoppingSite.Cart.clean_cart_items(current_cart(conn))
        conn
          |> put_flash(:info, "Order created successfully")
          |> redirect(to: cart_path(conn, :index))
      {:error, order_changeset} ->
        render(conn, "index.html", changeset: order_changeset)
    end
  else
    conn
      |> put_flash(:warning, "something wrong")
      |> redirect(to: cart_path(conn, :index))
  end
end

app.html 加入 warning

#web/templayes/layout/app.html.eex
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+<p class="alert alert-warning" role-"alert"><%= get_flash(@conn, :warning) %></p>


我們從填寫表單建立好 order:info後,就會進來這個create方法建立訂單,但order有兩個欄位我們要自己加入,就是是哪個使用者以及總共多少錢,也就是

new_order_params =
  order_params
    |> Map.put("user_id", Integer.to_string(conn.assigns.current_user.id))
    |> Map.put("total", Integer.to_string(get_total_price(conn)))

要注意在網路傳送都是要送 string,所以我們轉成 string


再來把這個訂單資訊插入到資料庫裡,插入成功就接著做兩件事:建立訂單物品快照和清空購物車
為什麼要建立訂單物品快照? 因為建立訂單之後購物車會清空,之後就不知道你的訂單有什麼物品,因此要在 order裡面存入物品資訊,以後可以直接從訂單取得物品資訊

首先將購物車裡的所有物品做成 map集合,形式為 %{product: x, quantity: y}
接著將每一個 map的元素用 build_assoc 跟 order 連結上關係,最後再更新這個快照 changeset

#web/controllers/order_controller.ex
def build_order_item(conn, order) do
  products =
    Repo.preload(current_cart(conn), :cart_items).cart_items
      |> Repo.preload(:product)
      |> Enum.map(& &1.product} end)

  for item <- products do
    order_item_changeset =
      build_assoc(order, :items)
        |> OrderItem.changeset(%{"product_name" => item.title,
                                 "price" => item.price,
                                 "quantity" => 1})
    case Repo.insert(order_item_changeset) do
      {:ok, _order_item} ->
        conn
      {:error, _changeset} ->
        render(conn, "show.html")
    end
  end
end

訂單建立後清空購物車

#web/models/cart.ex
alias ShoppingSite.Repo

def clean_cart_items(cart) do
  Repo.preload(cart, :cart_items).cart_items
    |> Enum.map($ Repo.delete(&1))
end

results matching ""

    No results matching ""