diff --git a/lib/store/inventory.ex b/lib/store/inventory.ex index 76a517a..8ebb9fb 100644 --- a/lib/store/inventory.ex +++ b/lib/store/inventory.ex @@ -344,65 +344,77 @@ defmodule Store.Inventory do alias Store.Accounts.User def purchase(%User{} = user, %Product{} = product, product_params) do - order = - Order - |> where(user_id: ^user.id) - |> where(status: :draft) - |> Repo.one() - |> Repo.preload([:user, :products]) + order = get_user_draft_order(user) - if order do - order_products = - OrdersProducts - |> where(order_id: ^order.id) - |> where(product_id: ^product.id) - |> Repo.all() - - quantity = String.to_integer(product_params["quantity"]) - - total_quantity_user = - Enum.reduce(order_products, 0, fn order_product, acc -> acc + order_product.quantity end) - - if order_products != nil do - if total_quantity_user + quantity > product.max_per_user, - do: - {:error, "The maximum quantity for this product per user is #{product.max_per_user}."} - - controlo = - for(order_product <- order_products) do - if order_product.size == String.to_existing_atom(product_params["size"]) do - update_order_product(order_product, %{quantity: order_product.quantity + quantity}) - 1 - else - 0 - end - end - - if Enum.sum(controlo) == 0 do - add_product_to_order(order, product, product_params) - end - - {:ok, product} + case order do + %Order{} -> + handle_existing_order(order, product, product_params) + + nil -> + handle_new_order(user, product, product_params) + end + end + + defp get_user_draft_order(user) do + Order + |> where(user_id: ^user.id, status: :draft) + |> Repo.one() + |> Repo.preload([:user, :products]) + end + + defp handle_existing_order(order, product, product_params) do + quantity = String.to_integer(product_params["quantity"]) + + order_products = + OrdersProducts + |> where(order_id: ^order.id, product_id: ^product.id) + |> Repo.all() + + total_quantity_user = + Enum.reduce(order_products, 0, fn order_product, acc -> acc + order_product.quantity end) + + if total_quantity_user + quantity > product.max_per_user do + {:error, "The maximum quantity for this product per user is #{product.max_per_user}."} + else + size_found = + Enum.any?(order_products, fn order_product -> + order_product.size == String.to_existing_atom(product_params["size"]) + end) + + if size_found do + update_order_products(order_products, product_params, quantity) else add_product_to_order(order, product, product_params) end - else - {:ok, order} = create_order(%{user_id: user.id}) - add_product_to_order(order, product, product_params) + + {:ok, product} end end + defp update_order_products(order_products, product_params, quantity) do + Enum.each(order_products, fn order_product -> + if order_product.size == String.to_existing_atom(product_params["size"]) do + update_order_product(order_product, %{quantity: order_product.quantity + quantity}) + end + end) + end + + defp handle_new_order(user, product, product_params) do + {:ok, order} = create_order(%{user_id: user.id}) + add_product_to_order(order, product, product_params) + end + def add_product_to_order(%Order{} = order, %Product{} = product, product_params) do - {val, _} = Integer.parse(product_params["quantity"]) + quantity = String.to_integer(product_params["quantity"]) size = product_params["size"] - if update_stock_sizes(product, size, val) == {:error, "Not enough stock."} do + if update_stock_sizes(product, size, quantity) == {:error, "Not enough stock."} do {:error, "Not enough stock."} else create_order_product(%{ order_id: order.id, product_id: product.id, - quantity: val, + quantity: quantity, size: size }) end