From 5cd7e8a307b5e8dfe1aaa329ca4b2ff2bc12ce14 Mon Sep 17 00:00:00 2001 From: Sergey Zubkov Date: Sat, 18 Nov 2023 18:17:19 +0300 Subject: [PATCH] add retailer products --- lib/market/accounts.ex | 16 ++++++-- lib/market/products.ex | 10 +++++ .../retailer/product_controller.ex | 17 +++++++++ .../controllers/retailer/product_json.ex | 21 +++++++++++ lib/market_web/router.ex | 7 +--- test/market/products_test.exs | 1 + .../retailer/product_controller_test.exs | 37 +++++++++++++++++++ .../retailer/session_controller_test.exs | 5 ++- .../vendor/category_controller_test.exs | 1 + 9 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 lib/market_web/controllers/retailer/product_controller.ex create mode 100644 lib/market_web/controllers/retailer/product_json.ex create mode 100644 test/market_web/controllers/retailer/product_controller_test.exs diff --git a/lib/market/accounts.ex b/lib/market/accounts.ex index 2f0eec3..3955033 100644 --- a/lib/market/accounts.ex +++ b/lib/market/accounts.ex @@ -227,7 +227,10 @@ defmodule Market.Accounts do Ecto.Multi.new() |> Ecto.Multi.update(:retailer, changeset) - |> Ecto.Multi.delete_all(:tokens, RetailerToken.retailer_and_contexts_query(retailer, [context])) + |> Ecto.Multi.delete_all( + :tokens, + RetailerToken.retailer_and_contexts_query(retailer, [context]) + ) end def deliver_retailer_update_email_instructions( @@ -240,7 +243,11 @@ defmodule Market.Accounts do RetailerToken.build_email_token(retailer, "change:#{current_email}") Repo.insert!(retailer_token) - RetailerNotifier.deliver_update_email_instructions(retailer, update_email_url_fun.(encoded_token)) + + RetailerNotifier.deliver_update_email_instructions( + retailer, + update_email_url_fun.(encoded_token) + ) end def change_retailer_password(retailer, attrs \\ %{}) do @@ -307,7 +314,10 @@ defmodule Market.Accounts do defp confirm_retailer_multi(retailer) do Ecto.Multi.new() |> Ecto.Multi.update(:retailer, Retailer.confirm_changeset(retailer)) - |> Ecto.Multi.delete_all(:tokens, RetailerToken.retailer_and_contexts_query(retailer, ["confirm"])) + |> Ecto.Multi.delete_all( + :tokens, + RetailerToken.retailer_and_contexts_query(retailer, ["confirm"]) + ) end def deliver_retailer_reset_password_instructions(%Retailer{} = retailer, reset_password_url_fun) diff --git a/lib/market/products.ex b/lib/market/products.ex index ae0ec0f..8bb721a 100644 --- a/lib/market/products.ex +++ b/lib/market/products.ex @@ -8,11 +8,21 @@ defmodule Market.Products do Repo.all(query) end + def list_products() do + query = from(Product) + Repo.all(query) + end + def get_product!(vendor_id, id) do query = from(Product, where: [id: ^id, vendor_id: ^vendor_id]) Repo.one!(query) end + def get_product!(id) do + query = from(Product, where: [id: ^id]) + Repo.one!(query) + end + def create_product(vendor, attrs) do Ecto.build_assoc(vendor, :products) |> change_product(attrs) |> Repo.insert() end diff --git a/lib/market_web/controllers/retailer/product_controller.ex b/lib/market_web/controllers/retailer/product_controller.ex new file mode 100644 index 0000000..3175a40 --- /dev/null +++ b/lib/market_web/controllers/retailer/product_controller.ex @@ -0,0 +1,17 @@ +defmodule MarketWeb.Retailer.ProductController do + use MarketWeb, :controller + + alias Market.Products + + action_fallback MarketWeb.FallbackController + + def index(conn, _params) do + products = Products.list_products() + render(conn, :index, products: products) + end + + def show(conn, %{"id" => id}) do + product = Products.get_product!(id) + render(conn, :show, product: product) + end +end diff --git a/lib/market_web/controllers/retailer/product_json.ex b/lib/market_web/controllers/retailer/product_json.ex new file mode 100644 index 0000000..a6d490d --- /dev/null +++ b/lib/market_web/controllers/retailer/product_json.ex @@ -0,0 +1,21 @@ +defmodule MarketWeb.Retailer.ProductJSON do + alias Market.Products.Product + + def index(%{products: products}) do + %{data: for(product <- products, do: data(product))} + end + + def show(%{product: product}) do + %{data: data(product)} + end + + defp data(%Product{} = product) do + %{ + id: product.id, + name: product.name, + vendor_id: product.vendor_id, + description: product.description, + price: product.price + } + end +end diff --git a/lib/market_web/router.ex b/lib/market_web/router.ex index 3f28d7e..9865789 100644 --- a/lib/market_web/router.ex +++ b/lib/market_web/router.ex @@ -42,19 +42,14 @@ defmodule MarketWeb.Router do pipe_through [:vendor_api] resources "/products", ProductController, only: [:index, :show, :create, :delete, :update] - resources "/categories", CategoryController, only: [:index, :show, :create, :delete, :update] - resources "/orders", OrderController, only: [:index, :show, :update] end scope "/retailers", MarketWeb.Retailer do pipe_through [:retailer_api] - # resources "/products", ProductController, only: [:index, :show] - # - # resources "/categories", CategoryController, only: [:index, :show] - + resources "/products", ProductController, only: [:index, :show] resources "/orders", OrderController, only: [:index, :show, :update, :create, :delete] end diff --git a/test/market/products_test.exs b/test/market/products_test.exs index 16d5c55..dcaebec 100644 --- a/test/market/products_test.exs +++ b/test/market/products_test.exs @@ -25,6 +25,7 @@ defmodule Market.ProductsTest do test "create_product/2 with valid data creates a product" do vendor = insert(:vendor) + valid_attrs = %{ description: "some description", name: "some name", diff --git a/test/market_web/controllers/retailer/product_controller_test.exs b/test/market_web/controllers/retailer/product_controller_test.exs new file mode 100644 index 0000000..717b3bb --- /dev/null +++ b/test/market_web/controllers/retailer/product_controller_test.exs @@ -0,0 +1,37 @@ +defmodule MarketWeb.Retailer.ProductControllerTest do + use MarketWeb.ConnCase + + import Market.Factory + + setup :register_and_log_in_retailer + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all products", %{conn: conn} do + insert_list(2, :product, vendor: insert(:vendor)) + + conn = get(conn, ~p"/retailers/products") + assert length(json_response(conn, 200)["data"]) == 2 + end + end + + describe "show product" do + test "renders product", %{conn: conn} do + vendor = insert(:vendor) + product = insert(:product, vendor: vendor) + + conn = get(conn, ~p"/retailers/products/#{product.id}") + + assert %{ + "id" => product.id, + "description" => product.description, + "name" => product.name, + "price" => product.price, + "vendor_id" => vendor.id + } == json_response(conn, 200)["data"] + end + end +end diff --git a/test/market_web/controllers/retailer/session_controller_test.exs b/test/market_web/controllers/retailer/session_controller_test.exs index 55661b7..1f46dd0 100644 --- a/test/market_web/controllers/retailer/session_controller_test.exs +++ b/test/market_web/controllers/retailer/session_controller_test.exs @@ -56,7 +56,10 @@ defmodule MarketWeb.Retailer.SessionControllerTest do describe "DELETE /retailers/log_out" do test "logs the retailer out", %{conn: conn, retailer: retailer} do conn = - conn |> init_test_session([]) |> log_in_retailer(retailer) |> delete(~p"/retailers/log_out") + conn + |> init_test_session([]) + |> log_in_retailer(retailer) + |> delete(~p"/retailers/log_out") refute get_session(conn, :retailer_token) end diff --git a/test/market_web/controllers/vendor/category_controller_test.exs b/test/market_web/controllers/vendor/category_controller_test.exs index 0e25c51..2b454f0 100644 --- a/test/market_web/controllers/vendor/category_controller_test.exs +++ b/test/market_web/controllers/vendor/category_controller_test.exs @@ -14,6 +14,7 @@ defmodule MarketWeb.Vendor.CategoryControllerTest do @invalid_attrs %{name: nil} setup :register_and_log_in_vendor + setup %{conn: conn} do {:ok, conn: put_req_header(conn, "accept", "application/json")} end