forked from shibao/cannery
		
	add multiple ammo groups at one time
This commit is contained in:
		@@ -3,6 +3,7 @@
 | 
				
			|||||||
- Add prompt to create first container before first ammo group
 | 
					- Add prompt to create first container before first ammo group
 | 
				
			||||||
- Edit and delete shot groups from ammo group show page
 | 
					- Edit and delete shot groups from ammo group show page
 | 
				
			||||||
- Use today's date when adding new shot groups
 | 
					- Use today's date when adding new shot groups
 | 
				
			||||||
 | 
					- Create multiple ammo groups at one time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# v0.2.3
 | 
					# v0.2.3
 | 
				
			||||||
- Fix modals with overflowing forms
 | 
					- Fix modals with overflowing forms
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,9 @@ defmodule Cannery.Ammo do
 | 
				
			|||||||
  import Ecto.Query, warn: false
 | 
					  import Ecto.Query, warn: false
 | 
				
			||||||
  alias Cannery.{Accounts.User, Containers, Repo}
 | 
					  alias Cannery.{Accounts.User, Containers, Repo}
 | 
				
			||||||
  alias Cannery.Ammo.{AmmoGroup, AmmoType}
 | 
					  alias Cannery.Ammo.{AmmoGroup, AmmoType}
 | 
				
			||||||
  alias Ecto.Changeset
 | 
					  alias Ecto.{Changeset, Multi}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ammo_group_create_limit 10_000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Returns the list of ammo_types.
 | 
					  Returns the list of ammo_types.
 | 
				
			||||||
@@ -327,36 +329,63 @@ defmodule Cannery.Ammo do
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Creates a ammo_group.
 | 
					  Creates multiple ammo_groups at once.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ## Examples
 | 
					  ## Examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      iex> create_ammo_group(%{field: value}, %User{id: 123})
 | 
					      iex> create_ammo_groups(%{field: value}, 3, %User{id: 123})
 | 
				
			||||||
      {:ok, %AmmoGroup{}}
 | 
					      {:ok, {3, [%AmmoGroup{}]}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      iex> create_ammo_group(%{field: bad_value}, %User{id: 123})
 | 
					      iex> create_ammo_groups(%{field: bad_value}, 3, %User{id: 123})
 | 
				
			||||||
      {:error, %Changeset{}}
 | 
					      {:error, %Changeset{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec create_ammo_group(attrs :: map(), User.t()) ::
 | 
					  @spec create_ammo_groups(attrs :: map(), multiplier :: non_neg_integer(), User.t()) ::
 | 
				
			||||||
          {:ok, AmmoGroup.t()} | {:error, Changeset.t(AmmoGroup.new_ammo_group())}
 | 
					          {:ok, {count :: non_neg_integer(), [AmmoGroup.t()] | nil}}
 | 
				
			||||||
  def create_ammo_group(
 | 
					          | {:error, Changeset.t(AmmoGroup.new_ammo_group()) | nil}
 | 
				
			||||||
 | 
					  def create_ammo_groups(
 | 
				
			||||||
        %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs,
 | 
					        %{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs,
 | 
				
			||||||
 | 
					        multiplier,
 | 
				
			||||||
        %User{id: user_id} = user
 | 
					        %User{id: user_id} = user
 | 
				
			||||||
      ) do
 | 
					      )
 | 
				
			||||||
 | 
					      when multiplier >= 1 and multiplier <= @ammo_group_create_limit do
 | 
				
			||||||
    # validate ammo type and container ids belong to user
 | 
					    # validate ammo type and container ids belong to user
 | 
				
			||||||
    _valid_ammo_type = get_ammo_type!(ammo_type_id, user)
 | 
					    _valid_ammo_type = get_ammo_type!(ammo_type_id, user)
 | 
				
			||||||
    _valid_container = Containers.get_container!(container_id, user)
 | 
					    _valid_container = Containers.get_container!(container_id, user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    %AmmoGroup{}
 | 
					    now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
 | 
				
			||||||
    |> AmmoGroup.create_changeset(attrs |> Map.put("user_id", user_id))
 | 
					
 | 
				
			||||||
    |> Repo.insert()
 | 
					    changesets =
 | 
				
			||||||
 | 
					      Enum.map(1..multiplier, fn _count ->
 | 
				
			||||||
 | 
					        %AmmoGroup{} |> AmmoGroup.create_changeset(attrs |> Map.put("user_id", user_id))
 | 
				
			||||||
 | 
					      end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if changesets |> Enum.all?(fn %{valid?: valid} -> valid end) do
 | 
				
			||||||
 | 
					      Multi.new()
 | 
				
			||||||
 | 
					      |> Multi.insert_all(
 | 
				
			||||||
 | 
					        :create_ammo_groups,
 | 
				
			||||||
 | 
					        AmmoGroup,
 | 
				
			||||||
 | 
					        changesets
 | 
				
			||||||
 | 
					        |> Enum.map(fn changeset ->
 | 
				
			||||||
 | 
					          changeset
 | 
				
			||||||
 | 
					          |> Map.get(:changes)
 | 
				
			||||||
 | 
					          |> Map.merge(%{inserted_at: now, updated_at: now})
 | 
				
			||||||
 | 
					        end),
 | 
				
			||||||
 | 
					        returning: true
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      |> Repo.transaction()
 | 
				
			||||||
 | 
					      |> case do
 | 
				
			||||||
 | 
					        {:ok, %{create_ammo_groups: {count, ammo_groups}}} -> {:ok, {count, ammo_groups}}
 | 
				
			||||||
 | 
					        {:error, :create_ammo_groups, changeset, _changes_so_far} -> {:error, changeset}
 | 
				
			||||||
 | 
					        {:error, _other_transaction, _value, _changes_so_far} -> {:error, nil}
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      {:error, changesets |> List.first()}
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def create_ammo_group(invalid_attrs, _user) do
 | 
					  def create_ammo_groups(invalid_attrs, _multiplier, _user) do
 | 
				
			||||||
    %AmmoGroup{}
 | 
					    {:error, %AmmoGroup{} |> AmmoGroup.create_changeset(invalid_attrs)}
 | 
				
			||||||
    |> AmmoGroup.create_changeset(invalid_attrs |> Map.put("user_id", "-1"))
 | 
					 | 
				
			||||||
    |> Repo.insert()
 | 
					 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do
 | 
				
			|||||||
  alias Ecto.Changeset
 | 
					  alias Ecto.Changeset
 | 
				
			||||||
  alias Phoenix.LiveView.Socket
 | 
					  alias Phoenix.LiveView.Socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ammo_group_create_limit 10_000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @impl true
 | 
					  @impl true
 | 
				
			||||||
  @spec update(
 | 
					  @spec update(
 | 
				
			||||||
          %{:ammo_group => AmmoGroup.t(), :current_user => User.t(), optional(any) => any},
 | 
					          %{:ammo_group => AmmoGroup.t(), :current_user => User.t(), optional(any) => any},
 | 
				
			||||||
@@ -22,6 +24,7 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do
 | 
				
			|||||||
  def update(%{assigns: %{ammo_group: ammo_group, current_user: current_user}} = socket) do
 | 
					  def update(%{assigns: %{ammo_group: ammo_group, current_user: current_user}} = socket) do
 | 
				
			||||||
    socket =
 | 
					    socket =
 | 
				
			||||||
      socket
 | 
					      socket
 | 
				
			||||||
 | 
					      |> assign(:ammo_group_create_limit, @ammo_group_create_limit)
 | 
				
			||||||
      |> assign(:changeset, Ammo.change_ammo_group(ammo_group))
 | 
					      |> assign(:changeset, Ammo.change_ammo_group(ammo_group))
 | 
				
			||||||
      |> assign(:ammo_types, Ammo.list_ammo_types(current_user))
 | 
					      |> assign(:ammo_types, Ammo.list_ammo_types(current_user))
 | 
				
			||||||
      |> assign_new(:containers, fn -> Containers.list_containers(current_user) end)
 | 
					      |> assign_new(:containers, fn -> Containers.list_containers(current_user) end)
 | 
				
			||||||
@@ -80,20 +83,68 @@ defmodule CanneryWeb.AmmoGroupLive.FormComponent do
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp save_ammo_group(
 | 
					  defp save_ammo_group(
 | 
				
			||||||
         %{assigns: %{current_user: current_user, return_to: return_to}} = socket,
 | 
					         %{assigns: %{changeset: changeset}} = socket,
 | 
				
			||||||
         :new,
 | 
					         :new,
 | 
				
			||||||
         ammo_group_params
 | 
					         %{"multiplier" => multiplier_str} = ammo_group_params
 | 
				
			||||||
       ) do
 | 
					       ) do
 | 
				
			||||||
    socket =
 | 
					    socket =
 | 
				
			||||||
      case Ammo.create_ammo_group(ammo_group_params, current_user) do
 | 
					      case multiplier_str |> Integer.parse() do
 | 
				
			||||||
        {:ok, _ammo_group} ->
 | 
					        {multiplier, _remainder}
 | 
				
			||||||
          prompt = dgettext("prompts", "Ammo group created successfully")
 | 
					        when multiplier >= 1 and multiplier <= @ammo_group_create_limit ->
 | 
				
			||||||
          socket |> put_flash(:info, prompt) |> push_redirect(to: return_to)
 | 
					          socket |> create_multiple(ammo_group_params, multiplier)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {:error, %Changeset{} = changeset} ->
 | 
					        {multiplier, _remainder} ->
 | 
				
			||||||
          socket |> assign(changeset: changeset)
 | 
					          error_msg =
 | 
				
			||||||
 | 
					            dgettext(
 | 
				
			||||||
 | 
					              "errors",
 | 
				
			||||||
 | 
					              "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}",
 | 
				
			||||||
 | 
					              max: @ammo_group_create_limit,
 | 
				
			||||||
 | 
					              multiplier: multiplier
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {:error, changeset} =
 | 
				
			||||||
 | 
					            changeset
 | 
				
			||||||
 | 
					            |> Changeset.add_error(:multiplier, error_msg)
 | 
				
			||||||
 | 
					            |> Changeset.apply_action(:insert)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          socket |> assign(:changeset, changeset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        :error ->
 | 
				
			||||||
 | 
					          error_msg = dgettext("errors", "Could not parse number of copies")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {:error, changeset} =
 | 
				
			||||||
 | 
					            changeset
 | 
				
			||||||
 | 
					            |> Changeset.add_error(:multiplier, error_msg)
 | 
				
			||||||
 | 
					            |> Changeset.apply_action(:insert)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          socket |> assign(:changeset, changeset)
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {:noreply, socket}
 | 
					    {:noreply, socket}
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  defp create_multiple(
 | 
				
			||||||
 | 
					         %{assigns: %{current_user: current_user, return_to: return_to}} = socket,
 | 
				
			||||||
 | 
					         ammo_group_params,
 | 
				
			||||||
 | 
					         multiplier
 | 
				
			||||||
 | 
					       ) do
 | 
				
			||||||
 | 
					    case Ammo.create_ammo_groups(ammo_group_params, multiplier, current_user) do
 | 
				
			||||||
 | 
					      {:ok, {count, _ammo_groups}} ->
 | 
				
			||||||
 | 
					        prompt =
 | 
				
			||||||
 | 
					          dngettext(
 | 
				
			||||||
 | 
					            "prompts",
 | 
				
			||||||
 | 
					            "Ammo group created successfully",
 | 
				
			||||||
 | 
					            "Ammo groups created successfully",
 | 
				
			||||||
 | 
					            count
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        socket |> put_flash(:info, prompt) |> push_redirect(to: return_to)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {:error, %Changeset{} = changeset} ->
 | 
				
			||||||
 | 
					        socket |> assign(changeset: changeset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {:error, nil} ->
 | 
				
			||||||
 | 
					        socket
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <%= label(f, :price_paid, gettext("Price paid"), class: "title text-lg text-primary-600") %>
 | 
					    <%= label(f, :price_paid, gettext("Price paid"), class: "title text-lg text-primary-600") %>
 | 
				
			||||||
    <%= number_input(f, :price_paid,
 | 
					    <%= number_input(f, :price_paid,
 | 
				
			||||||
      step: "0.01",
 | 
					      step: 0.01,
 | 
				
			||||||
      class: "text-center col-span-2 input input-primary"
 | 
					      class: "text-center col-span-2 input input-primary"
 | 
				
			||||||
    ) %>
 | 
					    ) %>
 | 
				
			||||||
    <%= error_tag(f, :price_paid, "col-span-3 text-center") %>
 | 
					    <%= error_tag(f, :price_paid, "col-span-3 text-center") %>
 | 
				
			||||||
@@ -51,9 +51,29 @@
 | 
				
			|||||||
    ) %>
 | 
					    ) %>
 | 
				
			||||||
    <%= error_tag(f, :container_id, "col-span-3 text-center") %>
 | 
					    <%= error_tag(f, :container_id, "col-span-3 text-center") %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <%= submit(dgettext("actions", "Save"),
 | 
					    <%= case @action do %>
 | 
				
			||||||
      phx_disable_with: dgettext("prompts", "Saving..."),
 | 
					      <% :new -> %>
 | 
				
			||||||
      class: "mx-auto col-span-3 btn btn-primary"
 | 
					        <hr class="hr col-span-3" />
 | 
				
			||||||
    ) %>
 | 
					
 | 
				
			||||||
 | 
					        <%= label(f, :multiplier, gettext("Copies"), class: "title text-lg text-primary-600") %>
 | 
				
			||||||
 | 
					        <%= number_input(f, :multiplier,
 | 
				
			||||||
 | 
					          max: @ammo_group_create_limit,
 | 
				
			||||||
 | 
					          class: "text-center input input-primary",
 | 
				
			||||||
 | 
					          value: 1,
 | 
				
			||||||
 | 
					          phx_update: "ignore"
 | 
				
			||||||
 | 
					        ) %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <%= submit(dgettext("actions", "Create"),
 | 
				
			||||||
 | 
					          phx_disable_with: dgettext("prompts", "Creating..."),
 | 
				
			||||||
 | 
					          class: "mx-auto btn btn-primary"
 | 
				
			||||||
 | 
					        ) %>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <%= error_tag(f, :multiplier, "col-span-3 text-center") %>
 | 
				
			||||||
 | 
					      <% :edit -> %>
 | 
				
			||||||
 | 
					        <%= submit(dgettext("actions", "Save"),
 | 
				
			||||||
 | 
					          phx_disable_with: dgettext("prompts", "Saving..."),
 | 
				
			||||||
 | 
					          class: "mx-auto col-span-3 btn btn-primary"
 | 
				
			||||||
 | 
					        ) %>
 | 
				
			||||||
 | 
					    <% end %>
 | 
				
			||||||
  </.form>
 | 
					  </.form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -125,7 +125,7 @@ msgstr ""
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
#: lib/cannery_web/components/add_shot_group_component.html.heex:46
 | 
					#: lib/cannery_web/components/add_shot_group_component.html.heex:46
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:54
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:73
 | 
				
			||||||
#: lib/cannery_web/live/ammo_type_live/form_component.html.heex:156
 | 
					#: lib/cannery_web/live/ammo_type_live/form_component.html.heex:156
 | 
				
			||||||
#: lib/cannery_web/live/container_live/form_component.html.heex:50
 | 
					#: lib/cannery_web/live/container_live/form_component.html.heex:50
 | 
				
			||||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:28
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:28
 | 
				
			||||||
@@ -196,3 +196,8 @@ msgstr ""
 | 
				
			|||||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:36
 | 
					#: lib/cannery_web/live/ammo_group_live/index.html.heex:36
 | 
				
			||||||
msgid "add a container first"
 | 
					msgid "add a container first"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:66
 | 
				
			||||||
 | 
					msgid "Create"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -834,3 +834,8 @@ msgstr ""
 | 
				
			|||||||
#: lib/cannery_web/live/range_live/index.ex:28
 | 
					#: lib/cannery_web/live/range_live/index.ex:28
 | 
				
			||||||
msgid "Record Shots"
 | 
					msgid "Record Shots"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:58
 | 
				
			||||||
 | 
					msgid "Copies"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -157,3 +157,13 @@ msgstr ""
 | 
				
			|||||||
#: lib/cannery_web/live/container_live/edit_tags_component.ex:52
 | 
					#: lib/cannery_web/live/container_live/edit_tags_component.ex:52
 | 
				
			||||||
msgid "Tag could not be removed"
 | 
					msgid "Tag could not be removed"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.ex:113
 | 
				
			||||||
 | 
					msgid "Could not parse number of copies"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.ex:98
 | 
				
			||||||
 | 
					msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}"
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,11 +61,6 @@ msgstr ""
 | 
				
			|||||||
msgid "A link to confirm your email change has been sent to the new address."
 | 
					msgid "A link to confirm your email change has been sent to the new address."
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/form_component.ex:90
 | 
					 | 
				
			||||||
msgid "Ammo group created successfully"
 | 
					 | 
				
			||||||
msgstr ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/index.ex:56
 | 
					#: lib/cannery_web/live/ammo_group_live/index.ex:56
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/show.ex:52
 | 
					#: lib/cannery_web/live/ammo_group_live/show.ex:52
 | 
				
			||||||
@@ -73,7 +68,7 @@ msgid "Ammo group deleted succesfully"
 | 
				
			|||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/form_component.ex:72
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.ex:75
 | 
				
			||||||
msgid "Ammo group updated successfully"
 | 
					msgid "Ammo group updated successfully"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -160,7 +155,7 @@ msgstr ""
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#, elixir-autogen, elixir-format
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
#: lib/cannery_web/components/add_shot_group_component.html.heex:48
 | 
					#: lib/cannery_web/components/add_shot_group_component.html.heex:48
 | 
				
			||||||
#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:55
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:74
 | 
				
			||||||
#: lib/cannery_web/live/ammo_type_live/form_component.html.heex:157
 | 
					#: lib/cannery_web/live/ammo_type_live/form_component.html.heex:157
 | 
				
			||||||
#: lib/cannery_web/live/container_live/form_component.html.heex:52
 | 
					#: lib/cannery_web/live/container_live/form_component.html.heex:52
 | 
				
			||||||
#: lib/cannery_web/live/invite_live/form_component.html.heex:30
 | 
					#: lib/cannery_web/live/invite_live/form_component.html.heex:30
 | 
				
			||||||
@@ -251,3 +246,15 @@ msgstr ""
 | 
				
			|||||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:33
 | 
					#: lib/cannery_web/live/ammo_group_live/index.html.heex:33
 | 
				
			||||||
msgid "You'll need to"
 | 
					msgid "You'll need to"
 | 
				
			||||||
msgstr ""
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:67
 | 
				
			||||||
 | 
					msgid "Creating..."
 | 
				
			||||||
 | 
					msgstr ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#, elixir-autogen, elixir-format
 | 
				
			||||||
 | 
					#: lib/cannery_web/live/ammo_group_live/form_component.ex:134
 | 
				
			||||||
 | 
					msgid "Ammo group created successfully"
 | 
				
			||||||
 | 
					msgid_plural "Ammo groups created successfully"
 | 
				
			||||||
 | 
					msgstr[0] ""
 | 
				
			||||||
 | 
					msgstr[1] ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,8 +20,8 @@ defmodule Cannery.ActivityLogTest do
 | 
				
			|||||||
      container = container_fixture(current_user)
 | 
					      container = container_fixture(current_user)
 | 
				
			||||||
      ammo_type = ammo_type_fixture(current_user)
 | 
					      ammo_type = ammo_type_fixture(current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      %{id: ammo_group_id} =
 | 
					      {1, [%{id: ammo_group_id} = ammo_group]} =
 | 
				
			||||||
        ammo_group = ammo_group_fixture(%{"count" => 25}, ammo_type, container, current_user)
 | 
					        ammo_group_fixture(%{"count" => 25}, ammo_type, container, current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      shot_group =
 | 
					      shot_group =
 | 
				
			||||||
        %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"}
 | 
					        %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -108,7 +108,7 @@ defmodule Cannery.AmmoTest do
 | 
				
			|||||||
      current_user = user_fixture()
 | 
					      current_user = user_fixture()
 | 
				
			||||||
      ammo_type = ammo_type_fixture(current_user)
 | 
					      ammo_type = ammo_type_fixture(current_user)
 | 
				
			||||||
      container = container_fixture(current_user)
 | 
					      container = container_fixture(current_user)
 | 
				
			||||||
      ammo_group = ammo_group_fixture(ammo_type, container, current_user)
 | 
					      {1, [ammo_group]} = ammo_group_fixture(ammo_type, container, current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      [
 | 
					      [
 | 
				
			||||||
        ammo_type: ammo_type,
 | 
					        ammo_type: ammo_type,
 | 
				
			||||||
@@ -129,28 +129,28 @@ defmodule Cannery.AmmoTest do
 | 
				
			|||||||
               ammo_group |> Repo.preload(:shot_groups)
 | 
					               ammo_group |> Repo.preload(:shot_groups)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test "create_ammo_group/1 with valid data creates a ammo_group",
 | 
					    test "create_ammo_groups/3 with valid data creates a ammo_group",
 | 
				
			||||||
         %{
 | 
					         %{
 | 
				
			||||||
           ammo_type: ammo_type,
 | 
					           ammo_type: ammo_type,
 | 
				
			||||||
           container: container,
 | 
					           container: container,
 | 
				
			||||||
           current_user: current_user
 | 
					           current_user: current_user
 | 
				
			||||||
         } do
 | 
					         } do
 | 
				
			||||||
      assert {:ok, %AmmoGroup{} = ammo_group} =
 | 
					      assert {:ok, {1, [%AmmoGroup{} = ammo_group]}} =
 | 
				
			||||||
               @valid_attrs
 | 
					               @valid_attrs
 | 
				
			||||||
               |> Map.merge(%{"ammo_type_id" => ammo_type.id, "container_id" => container.id})
 | 
					               |> Map.merge(%{"ammo_type_id" => ammo_type.id, "container_id" => container.id})
 | 
				
			||||||
               |> Ammo.create_ammo_group(current_user)
 | 
					               |> Ammo.create_ammo_groups(1, current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      assert ammo_group.count == 42
 | 
					      assert ammo_group.count == 42
 | 
				
			||||||
      assert ammo_group.notes == "some notes"
 | 
					      assert ammo_group.notes == "some notes"
 | 
				
			||||||
      assert ammo_group.price_paid == 120.5
 | 
					      assert ammo_group.price_paid == 120.5
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test "create_ammo_group/1 with invalid data returns error changeset",
 | 
					    test "create_ammo_groups/3 with invalid data returns error changeset",
 | 
				
			||||||
         %{ammo_type: ammo_type, container: container, current_user: current_user} do
 | 
					         %{ammo_type: ammo_type, container: container, current_user: current_user} do
 | 
				
			||||||
      assert {:error, %Changeset{}} =
 | 
					      assert {:error, %Changeset{}} =
 | 
				
			||||||
               @invalid_attrs
 | 
					               @invalid_attrs
 | 
				
			||||||
               |> Map.merge(%{"ammo_type_id" => ammo_type.id, "container_id" => container.id})
 | 
					               |> Map.merge(%{"ammo_type_id" => ammo_type.id, "container_id" => container.id})
 | 
				
			||||||
               |> Ammo.create_ammo_group(current_user)
 | 
					               |> Ammo.create_ammo_groups(1, current_user)
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test "update_ammo_group/2 with valid data updates the ammo_group",
 | 
					    test "update_ammo_group/2 with valid data updates the ammo_group",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,19 +6,20 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
 | 
				
			|||||||
  use CanneryWeb.ConnCase
 | 
					  use CanneryWeb.ConnCase
 | 
				
			||||||
  import Phoenix.LiveViewTest
 | 
					  import Phoenix.LiveViewTest
 | 
				
			||||||
  import CanneryWeb.Gettext
 | 
					  import CanneryWeb.Gettext
 | 
				
			||||||
  alias Cannery.Repo
 | 
					  alias Cannery.{Ammo, Repo}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @moduletag :ammo_group_live_test
 | 
					  @moduletag :ammo_group_live_test
 | 
				
			||||||
  @shot_group_create_attrs %{"ammo_left" => 5, "notes" => "some notes"}
 | 
					  @shot_group_create_attrs %{"ammo_left" => 5, "notes" => "some notes"}
 | 
				
			||||||
  @shot_group_update_attrs %{"count" => 5, "notes" => "some updated notes"}
 | 
					  @shot_group_update_attrs %{"count" => 5, "notes" => "some updated notes"}
 | 
				
			||||||
  @create_attrs %{count: 42, notes: "some notes", price_paid: 120.5}
 | 
					  @create_attrs %{"count" => 42, "notes" => "some notes", "price_paid" => 120.5}
 | 
				
			||||||
  @update_attrs %{count: 43, notes: "some updated notes", price_paid: 456.7}
 | 
					  @update_attrs %{"count" => 43, "notes" => "some updated notes", "price_paid" => 456.7}
 | 
				
			||||||
 | 
					  @ammo_group_create_limit 10_000
 | 
				
			||||||
  # @invalid_attrs %{count: -1, notes: nil, price_paid: nil}
 | 
					  # @invalid_attrs %{count: -1, notes: nil, price_paid: nil}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  defp create_ammo_group(%{current_user: current_user}) do
 | 
					  defp create_ammo_group(%{current_user: current_user}) do
 | 
				
			||||||
    ammo_type = ammo_type_fixture(current_user)
 | 
					    ammo_type = ammo_type_fixture(current_user)
 | 
				
			||||||
    container = container_fixture(current_user)
 | 
					    container = container_fixture(current_user)
 | 
				
			||||||
    ammo_group = ammo_group_fixture(ammo_type, container, current_user)
 | 
					    {1, [ammo_group]} = ammo_group_fixture(ammo_type, container, current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shot_group =
 | 
					    shot_group =
 | 
				
			||||||
      %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"}
 | 
					      %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"}
 | 
				
			||||||
@@ -38,7 +39,7 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
 | 
				
			|||||||
      assert html =~ ammo_group.ammo_type.name
 | 
					      assert html =~ ammo_group.ammo_type.name
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test "saves new ammo_group", %{conn: conn} do
 | 
					    test "saves a single new ammo_group", %{conn: conn} do
 | 
				
			||||||
      {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
 | 
					      {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~
 | 
					      assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~
 | 
				
			||||||
@@ -60,6 +61,68 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
 | 
				
			|||||||
      assert html =~ "42"
 | 
					      assert html =~ "42"
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "saves multiple new ammo_groups", %{conn: conn, current_user: current_user} do
 | 
				
			||||||
 | 
					      multiplier = 25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~
 | 
				
			||||||
 | 
					               gettext("New Ammo group")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert_patch(index_live, Routes.ammo_group_index_path(conn, :new))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # assert index_live
 | 
				
			||||||
 | 
					      #        |> form("#ammo_group-form", ammo_group: @invalid_attrs)
 | 
				
			||||||
 | 
					      #        |> render_change() =~ dgettext("errors", "can't be blank")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {:ok, _, html} =
 | 
				
			||||||
 | 
					        index_live
 | 
				
			||||||
 | 
					        |> form("#ammo_group-form",
 | 
				
			||||||
 | 
					          ammo_group: @create_attrs |> Map.put("multiplier", to_string(multiplier))
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        |> render_submit()
 | 
				
			||||||
 | 
					        |> follow_redirect(conn, Routes.ammo_group_index_path(conn, :index))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert html =~ dgettext("prompts", "Ammo groups created successfully")
 | 
				
			||||||
 | 
					      assert Ammo.list_ammo_groups(current_user) |> Enum.count() == multiplier + 1
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test "does not save invalid number of new ammo_groups", %{conn: conn} do
 | 
				
			||||||
 | 
					      {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert index_live |> element("a", dgettext("actions", "New Ammo group")) |> render_click() =~
 | 
				
			||||||
 | 
					               gettext("New Ammo group")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert_patch(index_live, Routes.ammo_group_index_path(conn, :new))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      # assert index_live
 | 
				
			||||||
 | 
					      #        |> form("#ammo_group-form", ammo_group: @invalid_attrs)
 | 
				
			||||||
 | 
					      #        |> render_change() =~ dgettext("errors", "can't be blank")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert index_live
 | 
				
			||||||
 | 
					             |> form("#ammo_group-form", ammo_group: @create_attrs |> Map.put("multiplier", "0"))
 | 
				
			||||||
 | 
					             |> render_submit() =~
 | 
				
			||||||
 | 
					               dgettext(
 | 
				
			||||||
 | 
					                 "errors",
 | 
				
			||||||
 | 
					                 "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}",
 | 
				
			||||||
 | 
					                 multiplier: 0,
 | 
				
			||||||
 | 
					                 max: @ammo_group_create_limit
 | 
				
			||||||
 | 
					               )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      assert index_live
 | 
				
			||||||
 | 
					             |> form("#ammo_group-form",
 | 
				
			||||||
 | 
					               ammo_group:
 | 
				
			||||||
 | 
					                 @create_attrs |> Map.put("multiplier", to_string(@ammo_group_create_limit + 1))
 | 
				
			||||||
 | 
					             )
 | 
				
			||||||
 | 
					             |> render_submit() =~
 | 
				
			||||||
 | 
					               dgettext(
 | 
				
			||||||
 | 
					                 "errors",
 | 
				
			||||||
 | 
					                 "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}",
 | 
				
			||||||
 | 
					                 multiplier: @ammo_group_create_limit + 1,
 | 
				
			||||||
 | 
					                 max: @ammo_group_create_limit
 | 
				
			||||||
 | 
					               )
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do
 | 
					    test "saves new shot_group", %{conn: conn, ammo_group: ammo_group} do
 | 
				
			||||||
      {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
 | 
					      {:ok, index_live, _html} = live(conn, Routes.ammo_group_index_path(conn, :index))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,9 @@ defmodule CanneryWeb.RangeLiveTest do
 | 
				
			|||||||
  defp create_shot_group(%{current_user: current_user}) do
 | 
					  defp create_shot_group(%{current_user: current_user}) do
 | 
				
			||||||
    container = container_fixture(%{"staged" => true}, current_user)
 | 
					    container = container_fixture(%{"staged" => true}, current_user)
 | 
				
			||||||
    ammo_type = ammo_type_fixture(current_user)
 | 
					    ammo_type = ammo_type_fixture(current_user)
 | 
				
			||||||
    ammo_group = ammo_group_fixture(%{"staged" => true}, ammo_type, container, current_user)
 | 
					
 | 
				
			||||||
 | 
					    {1, [ammo_group]} =
 | 
				
			||||||
 | 
					      ammo_group_fixture(%{"staged" => true}, ammo_type, container, current_user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shot_group =
 | 
					    shot_group =
 | 
				
			||||||
      %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"}
 | 
					      %{"count" => 5, "date" => ~N[2022-02-13 03:17:00], "notes" => "some notes"}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,10 +111,20 @@ defmodule Cannery.Fixtures do
 | 
				
			|||||||
  @doc """
 | 
					  @doc """
 | 
				
			||||||
  Generate a AmmoGroup
 | 
					  Generate a AmmoGroup
 | 
				
			||||||
  """
 | 
					  """
 | 
				
			||||||
  @spec ammo_group_fixture(AmmoType.t(), Container.t(), User.t()) :: AmmoGroup.t()
 | 
					  @spec ammo_group_fixture(AmmoType.t(), Container.t(), User.t()) ::
 | 
				
			||||||
  @spec ammo_group_fixture(attrs :: map(), AmmoType.t(), Container.t(), User.t()) :: AmmoGroup.t()
 | 
					          {count :: non_neg_integer(), [AmmoGroup.t()]}
 | 
				
			||||||
 | 
					  @spec ammo_group_fixture(attrs :: map(), AmmoType.t(), Container.t(), User.t()) ::
 | 
				
			||||||
 | 
					          {count :: non_neg_integer(), [AmmoGroup.t()]}
 | 
				
			||||||
 | 
					  @spec ammo_group_fixture(
 | 
				
			||||||
 | 
					          attrs :: map(),
 | 
				
			||||||
 | 
					          multiplier :: non_neg_integer(),
 | 
				
			||||||
 | 
					          AmmoType.t(),
 | 
				
			||||||
 | 
					          Container.t(),
 | 
				
			||||||
 | 
					          User.t()
 | 
				
			||||||
 | 
					        ) :: {count :: non_neg_integer(), [AmmoGroup.t()]}
 | 
				
			||||||
  def ammo_group_fixture(
 | 
					  def ammo_group_fixture(
 | 
				
			||||||
        attrs \\ %{},
 | 
					        attrs \\ %{},
 | 
				
			||||||
 | 
					        multiplier \\ 1,
 | 
				
			||||||
        %AmmoType{id: ammo_type_id},
 | 
					        %AmmoType{id: ammo_type_id},
 | 
				
			||||||
        %Container{id: container_id},
 | 
					        %Container{id: container_id},
 | 
				
			||||||
        %User{} = user
 | 
					        %User{} = user
 | 
				
			||||||
@@ -125,7 +135,7 @@ defmodule Cannery.Fixtures do
 | 
				
			|||||||
      "container_id" => container_id,
 | 
					      "container_id" => container_id,
 | 
				
			||||||
      "count" => 20
 | 
					      "count" => 20
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    |> Ammo.create_ammo_group(user)
 | 
					    |> Ammo.create_ammo_groups(multiplier, user)
 | 
				
			||||||
    |> unwrap_ok_tuple()
 | 
					    |> unwrap_ok_tuple()
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user