From 9643e9f46db3f9b4d38256224ba2dd3348da8c61 Mon Sep 17 00:00:00 2001 From: shibao Date: Mon, 5 Jun 2023 20:47:12 -0400 Subject: [PATCH] improve Ammo.get_round_count --- lib/cannery/ammo.ex | 61 ++++++++++--------- .../core_components/container_card.html.heex | 2 +- .../controllers/export_controller.ex | 7 +-- lib/cannery_web/live/container_live/show.ex | 2 +- lib/cannery_web/live/type_live/show.ex | 2 +- priv/gettext/de/LC_MESSAGES/errors.po | 2 +- priv/gettext/en/LC_MESSAGES/errors.po | 2 +- priv/gettext/errors.pot | 2 +- priv/gettext/es/LC_MESSAGES/errors.po | 2 +- priv/gettext/fr/LC_MESSAGES/errors.po | 2 +- priv/gettext/ga/LC_MESSAGES/errors.po | 2 +- test/cannery/ammo_test.exs | 20 +++--- .../controllers/export_controller_test.exs | 4 +- 13 files changed, 56 insertions(+), 54 deletions(-) diff --git a/lib/cannery/ammo.ex b/lib/cannery/ammo.ex index 6b049e30..300feb88 100644 --- a/lib/cannery/ammo.ex +++ b/lib/cannery/ammo.ex @@ -185,25 +185,49 @@ defmodule Cannery.Ammo do |> Map.new() end + @type get_round_count_option :: {:type_id, Type.id() | nil} | {:container_id, Container.id()} + @type get_round_count_options :: [get_round_count_option()] + @doc """ Gets the total number of rounds for a type ## Examples - iex> get_round_count_for_type( - ...> %Type{id: 123, user_id: 456}, - ...> %User{id: 456} - ...> ) + iex> get_round_count(%User{id: 456}, type_id: 123) 35 + iex> get_round_count(%User{id: 456}, container_id: 123) + 25 + """ - @spec get_round_count_for_type(Type.t(), User.t()) :: non_neg_integer() - def get_round_count_for_type(%Type{id: type_id} = type, user) do - [type] - |> get_round_count_for_types(user) - |> Map.get(type_id, 0) + @spec get_round_count(User.t()) :: non_neg_integer() + @spec get_round_count(User.t(), get_round_count_options()) :: non_neg_integer() + def get_round_count(%User{id: user_id}, opts \\ []) do + from(p in Pack, + as: :p, + where: p.user_id == ^user_id, + select: sum(p.count), + distinct: true + ) + |> get_round_count_type_id(Keyword.get(opts, :type_id)) + |> get_round_count_container_id(Keyword.get(opts, :container_id)) + |> Repo.one() || 0 end + @spec get_round_count_type_id(Queryable.t(), Type.id() | nil) :: Queryable.t() + defp get_round_count_type_id(query, type_id) when type_id |> is_binary() do + query |> where([p: p], p.type_id == ^type_id) + end + + defp get_round_count_type_id(query, _nil), do: query + + @spec get_round_count_container_id(Queryable.t(), Container.id() | nil) :: Queryable.t() + defp get_round_count_container_id(query, container_id) when container_id |> is_binary() do + query |> where([p: p], p.container_id == ^container_id) + end + + defp get_round_count_container_id(query, _nil), do: query + @doc """ Gets the total number of rounds for multiple types @@ -670,25 +694,6 @@ defmodule Cannery.Ammo do query |> where([p: p], not (p.count == 0)) end - @doc """ - Returns number of rounds in a container. - - ## Examples - - iex> get_round_count_for_container( - ...> %Container{id: 123, user_id: 456}, - ...> %User{id: 456} - ...> ) - 5 - - """ - @spec get_round_count_for_container!(Container.t(), User.t()) :: non_neg_integer() - def get_round_count_for_container!(%Container{id: container_id} = container, user) do - [container] - |> get_round_count_for_containers(user) - |> Map.get(container_id, 0) - end - @doc """ Returns number of ammo packs in multiple containers. diff --git a/lib/cannery_web/components/core_components/container_card.html.heex b/lib/cannery_web/components/core_components/container_card.html.heex index a202f8a3..af95cf26 100644 --- a/lib/cannery_web/components/core_components/container_card.html.heex +++ b/lib/cannery_web/components/core_components/container_card.html.heex @@ -35,7 +35,7 @@ <%= gettext("Rounds:") %> - <%= @container |> Ammo.get_round_count_for_container!(@current_user) %> + <%= Ammo.get_round_count(@current_user, container_id: @container.id) %> <% end %> diff --git a/lib/cannery_web/controllers/export_controller.ex b/lib/cannery_web/controllers/export_controller.ex index 4a6de939..eea39c2e 100644 --- a/lib/cannery_web/controllers/export_controller.ex +++ b/lib/cannery_web/controllers/export_controller.ex @@ -59,15 +59,12 @@ defmodule CanneryWeb.ExportController do containers = Containers.list_containers(current_user) |> Enum.map(fn container -> - pack_count = Ammo.get_packs_count(current_user, container_id: container.id) - round_count = container |> Ammo.get_round_count_for_container!(current_user) - container |> Jason.encode!() |> Jason.decode!() |> Map.merge(%{ - "pack_count" => pack_count, - "round_count" => round_count + "pack_count" => Ammo.get_packs_count(current_user, container_id: container.id), + "round_count" => Ammo.get_round_count(current_user, container_id: container.id) }) end) diff --git a/lib/cannery_web/live/container_live/show.ex b/lib/cannery_web/live/container_live/show.ex index 9bfb8b0d..165271c2 100644 --- a/lib/cannery_web/live/container_live/show.ex +++ b/lib/cannery_web/live/container_live/show.ex @@ -122,7 +122,7 @@ defmodule CanneryWeb.ContainerLive.Show do socket |> assign( container: container, - round_count: container |> Ammo.get_round_count_for_container!(current_user), + round_count: Ammo.get_round_count(current_user, container_id: container.id), packs_count: Ammo.get_packs_count(current_user, container_id: container.id), packs: packs, original_counts: original_counts, diff --git a/lib/cannery_web/live/type_live/show.ex b/lib/cannery_web/live/type_live/show.ex index 4b2c2870..18cabd18 100644 --- a/lib/cannery_web/live/type_live/show.ex +++ b/lib/cannery_web/live/type_live/show.ex @@ -95,7 +95,7 @@ defmodule CanneryWeb.TypeLive.Show do cprs: packs |> Ammo.get_cprs(current_user), last_used_dates: packs |> ActivityLog.get_last_used_dates(current_user), avg_cost_per_round: type |> Ammo.get_average_cost_for_type(current_user), - rounds: type |> Ammo.get_round_count_for_type(current_user), + rounds: Ammo.get_round_count(current_user, type_id: type.id), original_counts: original_counts, used_rounds: used_rounds, historical_round_count: historical_round_count, diff --git a/priv/gettext/de/LC_MESSAGES/errors.po b/priv/gettext/de/LC_MESSAGES/errors.po index 72f10b8a..474336e6 100644 --- a/priv/gettext/de/LC_MESSAGES/errors.po +++ b/priv/gettext/de/LC_MESSAGES/errors.po @@ -170,7 +170,7 @@ msgstr "" "Ungültige Nummer an Kopien. Muss zwischen 1 and %{max} liegen. War " "%{multiplier}" -#: lib/cannery/ammo.ex:980 +#: lib/cannery/ammo.ex:985 #, elixir-autogen, elixir-format msgid "Invalid multiplier" msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/errors.po b/priv/gettext/en/LC_MESSAGES/errors.po index 5e90c994..0b613cf9 100644 --- a/priv/gettext/en/LC_MESSAGES/errors.po +++ b/priv/gettext/en/LC_MESSAGES/errors.po @@ -153,7 +153,7 @@ msgstr "" msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" -#: lib/cannery/ammo.ex:980 +#: lib/cannery/ammo.ex:985 #, elixir-autogen, elixir-format msgid "Invalid multiplier" msgstr "" diff --git a/priv/gettext/errors.pot b/priv/gettext/errors.pot index 429fa75b..c115f5c5 100644 --- a/priv/gettext/errors.pot +++ b/priv/gettext/errors.pot @@ -152,7 +152,7 @@ msgstr "" msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" -#: lib/cannery/ammo.ex:980 +#: lib/cannery/ammo.ex:985 #, elixir-autogen, elixir-format msgid "Invalid multiplier" msgstr "" diff --git a/priv/gettext/es/LC_MESSAGES/errors.po b/priv/gettext/es/LC_MESSAGES/errors.po index 55130a15..a8d564f5 100644 --- a/priv/gettext/es/LC_MESSAGES/errors.po +++ b/priv/gettext/es/LC_MESSAGES/errors.po @@ -168,7 +168,7 @@ msgstr "No se ha podido procesar el número de copias" msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "Número inválido de copias, debe ser entre 1 y %{max}. Fue %{multiplier" -#: lib/cannery/ammo.ex:980 +#: lib/cannery/ammo.ex:985 #, elixir-autogen, elixir-format msgid "Invalid multiplier" msgstr "Multiplicador inválido" diff --git a/priv/gettext/fr/LC_MESSAGES/errors.po b/priv/gettext/fr/LC_MESSAGES/errors.po index 7b4a7ece..a419ed51 100644 --- a/priv/gettext/fr/LC_MESSAGES/errors.po +++ b/priv/gettext/fr/LC_MESSAGES/errors.po @@ -169,7 +169,7 @@ msgstr "Impossible d'analyser le nombre de copies" msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "Nombre de copies invalide, doit être 1 et %{max}. Été %{multiplier}" -#: lib/cannery/ammo.ex:980 +#: lib/cannery/ammo.ex:985 #, elixir-autogen, elixir-format msgid "Invalid multiplier" msgstr "Multiplicateur invalide" diff --git a/priv/gettext/ga/LC_MESSAGES/errors.po b/priv/gettext/ga/LC_MESSAGES/errors.po index c49a3e7a..946299ad 100644 --- a/priv/gettext/ga/LC_MESSAGES/errors.po +++ b/priv/gettext/ga/LC_MESSAGES/errors.po @@ -168,7 +168,7 @@ msgstr "" msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}" msgstr "" -#: lib/cannery/ammo.ex:980 +#: lib/cannery/ammo.ex:985 #, elixir-autogen, elixir-format msgid "Invalid multiplier" msgstr "" diff --git a/test/cannery/ammo_test.exs b/test/cannery/ammo_test.exs index affa70fd..5d63aba6 100644 --- a/test/cannery/ammo_test.exs +++ b/test/cannery/ammo_test.exs @@ -343,24 +343,24 @@ defmodule Cannery.AmmoTest do assert %{^another_type_id => 25.0} = average_costs end - test "get_round_count_for_type/2 gets accurate round count for type", + test "get_round_count/2 gets accurate round count for type", %{type: type, current_user: current_user, container: container} do another_type = type_fixture(current_user) - assert 0 = Ammo.get_round_count_for_type(another_type, current_user) + assert 0 = Ammo.get_round_count(current_user, type_id: another_type.id) {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) - assert 1 = Ammo.get_round_count_for_type(type, current_user) + assert 1 = Ammo.get_round_count(current_user, type_id: type.id) {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) - assert 51 = Ammo.get_round_count_for_type(type, current_user) + assert 51 = Ammo.get_round_count(current_user, type_id: type.id) shot_record_fixture(%{count: 26}, current_user, pack) - assert 25 = Ammo.get_round_count_for_type(type, current_user) + assert 25 = Ammo.get_round_count(current_user, type_id: type.id) shot_record_fixture(%{count: 1}, current_user, first_pack) - assert 24 = Ammo.get_round_count_for_type(type, current_user) + assert 24 = Ammo.get_round_count(current_user, type_id: type.id) end test "get_round_count_for_types/2 gets accurate round counts for types", %{ @@ -635,18 +635,18 @@ defmodule Cannery.AmmoTest do assert %{^another_container_id => 1} = packs_count end - test "get_round_count_for_container!/2 gets accurate total round count for container", + test "get_round_count/2 gets accurate total round count for container_id", %{type: type, current_user: current_user, container: container} do {1, [first_pack]} = pack_fixture(%{count: 5}, type, container, current_user) - assert 5 = container |> Ammo.get_round_count_for_container!(current_user) + assert 5 = Ammo.get_round_count(current_user, container_id: container.id) {25, _packs} = pack_fixture(%{count: 5}, 25, type, container, current_user) - assert 130 = container |> Ammo.get_round_count_for_container!(current_user) + assert 130 = Ammo.get_round_count(current_user, container_id: container.id) shot_record_fixture(%{count: 5}, current_user, first_pack) - assert 125 = container |> Ammo.get_round_count_for_container!(current_user) + assert 125 = Ammo.get_round_count(current_user, container_id: container.id) end test "get_round_count_for_containers/2 gets accurate total round count for containers", diff --git a/test/cannery_web/controllers/export_controller_test.exs b/test/cannery_web/controllers/export_controller_test.exs index b65a0d36..d182eae2 100644 --- a/test/cannery_web/controllers/export_controller_test.exs +++ b/test/cannery_web/controllers/export_controller_test.exs @@ -91,7 +91,7 @@ defmodule CanneryWeb.ExportControllerTest do "shot_charge_weight" => type.shot_charge_weight, "dram_equivalent" => type.dram_equivalent, "average_cost" => type |> Ammo.get_average_cost_for_type(current_user), - "round_count" => type |> Ammo.get_round_count_for_type(current_user), + "round_count" => Ammo.get_round_count(current_user, type_id: type.id), "used_count" => ActivityLog.get_used_count(current_user, type_id: type.id), "pack_count" => Ammo.get_packs_count(current_user, type_id: type.id), "total_pack_count" => @@ -113,7 +113,7 @@ defmodule CanneryWeb.ExportControllerTest do ], "type" => container.type, "pack_count" => Ammo.get_packs_count(current_user, container_id: container.id), - "round_count" => container |> Ammo.get_round_count_for_container!(current_user) + "round_count" => Ammo.get_round_count(current_user, container_id: container.id) } ideal_shot_record = %{