remove all n+1 queries for real this time

This commit is contained in:
shibao 2023-03-19 15:05:09 -04:00
parent 071eb1b3c9
commit 03f8a2e8a7
24 changed files with 240 additions and 131 deletions

View File

@ -4,6 +4,7 @@
- Only show historical ammo type information when displaying "Show used" in table
- Only show historical ammo group information when displaying "Show used" in table
- Fix some values not being sorted in tables properly
- Code quality improvements
# v0.8.5
- Add link in readme to github mirror

View File

@ -843,12 +843,39 @@ defmodule Cannery.Ammo do
"""
@spec get_percentage_remaining(AmmoGroup.t(), User.t()) :: non_neg_integer()
def get_percentage_remaining(%AmmoGroup{count: 0, user_id: user_id}, %User{id: user_id}) do
0
def get_percentage_remaining(%AmmoGroup{id: ammo_group_id} = ammo_group, user) do
[ammo_group]
|> get_percentages_remaining(user)
|> Map.fetch!(ammo_group_id)
end
def get_percentage_remaining(%AmmoGroup{count: count} = ammo_group, current_user) do
round(count / get_original_count(ammo_group, current_user) * 100)
@doc """
Calculates the percentages remaining of multiple ammo groups out of 100
## Examples
iex> get_percentages_remaining(
...> [%AmmoGroup{id: 123, count: 5, user_id: 456}],
...> %User{id: 456}
...> )
%{123 => 100}
"""
@spec get_percentages_remaining([AmmoGroup.t()], User.t()) ::
%{optional(AmmoGroup.id()) => non_neg_integer()}
def get_percentages_remaining(ammo_groups, %User{id: user_id} = user) do
original_counts = get_original_counts(ammo_groups, user)
ammo_groups
|> Map.new(fn %AmmoGroup{id: ammo_group_id, count: count, user_id: ^user_id} ->
percentage =
case count do
0 -> 0
count -> round(count / Map.fetch!(original_counts, ammo_group_id) * 100)
end
{ammo_group_id, percentage}
end)
end
@doc """

View File

@ -92,7 +92,7 @@ defmodule Cannery.Containers do
@doc """
Gets a single container.
Raises `Ecto.NoResultsError` if the Container does not exist.
Raises `KeyError` if the Container does not exist.
## Examples
@ -100,18 +100,37 @@ defmodule Cannery.Containers do
%Container{}
iex> get_container!(456, %User{id: 123})
** (Ecto.NoResultsError)
** (KeyError)
"""
@spec get_container!(Container.id(), User.t()) :: Container.t()
def get_container!(id, %User{id: user_id}) do
Repo.one!(
def get_container!(id, user) do
[id]
|> get_containers(user)
|> Map.fetch!(id)
end
@doc """
Gets multiple containers.
## Examples
iex> get_containers([123], %User{id: 123})
%{123 => %Container{}}
"""
@spec get_containers([Container.id()], User.t()) :: %{optional(Container.id()) => Container.t()}
def get_containers(ids, %User{id: user_id}) do
Repo.all(
from c in Container,
where: c.user_id == ^user_id,
where: c.id == ^id,
where: c.id in ^ids,
order_by: c.name,
preload: ^@container_preloads
preload: ^@container_preloads,
select: {c.id, c}
)
|> Map.new()
end
@doc """

View File

@ -108,14 +108,21 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
[%{label: gettext("Ammo type"), key: :ammo_type} | columns]
end
containers =
ammo_groups
|> Enum.map(fn %{container_id: container_id} -> container_id end)
|> Containers.get_containers(current_user)
extra_data = %{
current_user: current_user,
ammo_type: ammo_type,
columns: columns,
container: container,
containers: containers,
original_counts: Ammo.get_original_counts(ammo_groups, current_user),
cprs: Ammo.get_cprs(ammo_groups, current_user),
last_used_dates: ActivityLog.get_last_used_dates(ammo_groups, current_user),
percentages_remaining: Ammo.get_percentages_remaining(ammo_groups, current_user),
actions: actions,
range: range
}
@ -202,8 +209,12 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
"""}
end
defp get_value_for_key(:remaining, ammo_group, %{current_user: current_user}) do
percentage = ammo_group |> Ammo.get_percentage_remaining(current_user)
defp get_value_for_key(
:remaining,
%{id: ammo_group_id},
%{percentages_remaining: percentages_remaining}
) do
percentage = Map.fetch!(percentages_remaining, ammo_group_id)
{percentage, gettext("%{percentage}%", percentage: percentage)}
end
@ -220,12 +231,13 @@ defmodule CanneryWeb.Components.AmmoGroupTableComponent do
defp get_value_for_key(
:container,
%{container_id: container_id} = ammo_group,
%{container: container, current_user: current_user}
%{container: container_block, containers: containers}
) do
container = %{name: container_name} = Map.fetch!(containers, container_id)
assigns = %{
container:
%{name: container_name} = container_id |> Containers.get_container!(current_user),
container_block: container,
container: container,
container_block: container_block,
ammo_group: ammo_group
}

View File

@ -6,7 +6,7 @@ defmodule CanneryWeb.CoreComponents do
import CanneryWeb.{Gettext, ViewHelpers}
alias Cannery.{Accounts, Accounts.Invite, Accounts.User}
alias Cannery.{Ammo, Ammo.AmmoGroup}
alias Cannery.{Containers, Containers.Container, Containers.Tag}
alias Cannery.{Containers.Container, Containers.Tag}
alias CanneryWeb.{Endpoint, HomeLive}
alias CanneryWeb.Router.Helpers, as: Routes
alias Phoenix.LiveView.{JS, Rendered}
@ -91,7 +91,7 @@ defmodule CanneryWeb.CoreComponents do
attr :original_count, :integer, default: nil
attr :cpr, :integer, default: nil
attr :last_used_date, Date, default: nil
attr :show_container, :boolean, default: false
attr :container, Container, default: nil
slot(:inner_block)
def ammo_group_card(assigns)

View File

@ -50,17 +50,11 @@
<%= gettext("$%{amount}", amount: display_currency(@cpr)) %>
</span>
<span
:if={@show_container && Containers.get_container!(@ammo_group.container_id, @current_user)}
class="rounded-lg title text-lg"
>
<span :if={@container} class="rounded-lg title text-lg">
<%= gettext("Container:") %>
<.link
navigate={Routes.container_show_path(Endpoint, :show, @ammo_group.container_id)}
class="link"
>
<%= Containers.get_container!(@ammo_group.container_id, @current_user).name %>
<.link navigate={Routes.container_show_path(Endpoint, :show, @container)} class="link">
<%= @container.name %>
</.link>
</span>
</div>

View File

@ -32,18 +32,17 @@ defmodule CanneryWeb.ExportController do
used_counts = ammo_groups |> ActivityLog.get_used_counts(current_user)
original_counts = ammo_groups |> Ammo.get_original_counts(current_user)
cprs = ammo_groups |> Ammo.get_cprs(current_user)
percentages_remaining = ammo_groups |> Ammo.get_percentages_remaining(current_user)
ammo_groups =
ammo_groups
|> Enum.map(fn %{id: ammo_group_id} = ammo_group ->
percentage_remaining = ammo_group |> Ammo.get_percentage_remaining(current_user)
ammo_group
|> Jason.encode!()
|> Jason.decode!()
|> Map.merge(%{
"used_count" => Map.get(used_counts, ammo_group_id),
"percentage_remaining" => percentage_remaining,
"percentage_remaining" => Map.fetch!(percentages_remaining, ammo_group_id),
"original_count" => Map.get(original_counts, ammo_group_id),
"cpr" => Map.get(cprs, ammo_group_id)
})

View File

@ -4,7 +4,7 @@ defmodule CanneryWeb.AmmoTypeLive.Show do
"""
use CanneryWeb, :live_view
alias Cannery.{ActivityLog, Ammo, Ammo.AmmoType}
alias Cannery.{ActivityLog, Ammo, Ammo.AmmoType, Containers}
alias CanneryWeb.Endpoint
@fields_list [
@ -104,11 +104,17 @@ defmodule CanneryWeb.AmmoTypeLive.Show do
:edit -> gettext("Edit %{ammo_type_name}", ammo_type_name: ammo_type_name)
end
containers =
ammo_groups
|> Enum.map(fn %{container_id: container_id} -> container_id end)
|> Containers.get_containers(current_user)
socket
|> assign(
page_title: page_title,
ammo_type: ammo_type,
ammo_groups: ammo_groups,
containers: containers,
cprs: ammo_groups |> Ammo.get_cprs(current_user),
last_used_dates: ammo_groups |> ActivityLog.get_last_used_dates(current_user),
avg_cost_per_round: ammo_type |> Ammo.get_average_cost_for_ammo_type(current_user),

View File

@ -184,13 +184,13 @@
<% else %>
<div class="flex flex-wrap justify-center items-stretch">
<.ammo_group_card
:for={%{id: ammo_group_id} = ammo_group <- @ammo_groups}
:for={%{id: ammo_group_id, container_id: container_id} = ammo_group <- @ammo_groups}
ammo_group={ammo_group}
original_count={@original_counts && Map.fetch!(@original_counts, ammo_group_id)}
cpr={Map.get(@cprs, ammo_group_id)}
last_used_date={Map.get(@last_used_dates, ammo_group_id)}
current_user={@current_user}
show_container={true}
container={Map.fetch!(@containers, container_id)}
/>
</div>
<% end %>

View File

@ -525,8 +525,8 @@ msgstr "Kein weiterer Behälter"
msgid "Shot log"
msgstr "Schießkladde"
#: lib/cannery_web/components/ammo_group_table_component.ex:173
#: lib/cannery_web/components/ammo_group_table_component.ex:251
#: lib/cannery_web/components/ammo_group_table_component.ex:180
#: lib/cannery_web/components/ammo_group_table_component.ex:263
#: lib/cannery_web/components/ammo_type_table_component.ex:235
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:45
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:50
@ -620,8 +620,8 @@ msgstr "Editiere %{name} Tags"
msgid "Rounds:"
msgstr "Patronen:"
#: lib/cannery_web/components/ammo_group_table_component.ex:170
#: lib/cannery_web/components/ammo_group_table_component.ex:247
#: lib/cannery_web/components/ammo_group_table_component.ex:177
#: lib/cannery_web/components/ammo_group_table_component.ex:259
#: lib/cannery_web/components/ammo_type_table_component.ex:234
#: lib/cannery_web/live/ammo_type_live/show.html.heex:139
#, elixir-autogen, elixir-format
@ -796,7 +796,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:57
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:54
#, elixir-autogen, elixir-format, fuzzy
msgid "Container:"
msgstr "Behälter"
@ -809,7 +809,7 @@ msgstr "Behälter"
msgid "Show used"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:207
#: lib/cannery_web/components/ammo_group_table_component.ex:218
#: lib/cannery_web/live/ammo_group_live/show.html.heex:19
#, elixir-autogen, elixir-format
msgid "%{percentage}%"
@ -996,7 +996,7 @@ msgstr ""
msgid "Edit %{ammo_type_name}"
msgstr "%{name} bearbeiten"
#: lib/cannery_web/components/ammo_group_table_component.ex:255
#: lib/cannery_web/components/ammo_group_table_component.ex:267
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "Empty"
@ -1042,7 +1042,7 @@ msgstr ""
msgid "Last used on:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:191
#: lib/cannery_web/components/ammo_group_table_component.ex:198
#, elixir-autogen, elixir-format
msgid "Never used"
msgstr ""

View File

@ -23,7 +23,7 @@ msgstr ""
## Run "mix gettext.extract" to bring this file up to
## date. Leave "msgstr"s empty as changing them here has no
## effect: edit them in PO (.po) files instead.
#: lib/cannery/containers.ex:201
#: lib/cannery/containers.ex:220
#, elixir-autogen, elixir-format
msgid "Container must be empty before deleting"
msgstr "Behälter muss vor dem Löschen leer sein"
@ -172,7 +172,7 @@ msgstr ""
"Ungültige Nummer an Kopien. Muss zwischen 1 and %{max} liegen. War "
"%{multiplier}"
#: lib/cannery/ammo.ex:1016
#: lib/cannery/ammo.ex:1043
#, elixir-autogen, elixir-format
msgid "Invalid multiplier"
msgstr ""

View File

@ -519,8 +519,8 @@ msgstr ""
msgid "Shot log"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:173
#: lib/cannery_web/components/ammo_group_table_component.ex:251
#: lib/cannery_web/components/ammo_group_table_component.ex:180
#: lib/cannery_web/components/ammo_group_table_component.ex:263
#: lib/cannery_web/components/ammo_type_table_component.ex:235
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:45
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:50
@ -614,8 +614,8 @@ msgstr ""
msgid "Rounds:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:170
#: lib/cannery_web/components/ammo_group_table_component.ex:247
#: lib/cannery_web/components/ammo_group_table_component.ex:177
#: lib/cannery_web/components/ammo_group_table_component.ex:259
#: lib/cannery_web/components/ammo_type_table_component.ex:234
#: lib/cannery_web/live/ammo_type_live/show.html.heex:139
#, elixir-autogen, elixir-format
@ -790,7 +790,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:57
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:54
#, elixir-autogen, elixir-format
msgid "Container:"
msgstr ""
@ -803,7 +803,7 @@ msgstr ""
msgid "Show used"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:207
#: lib/cannery_web/components/ammo_group_table_component.ex:218
#: lib/cannery_web/live/ammo_group_live/show.html.heex:19
#, elixir-autogen, elixir-format
msgid "%{percentage}%"
@ -990,7 +990,7 @@ msgstr ""
msgid "Edit %{ammo_type_name}"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:255
#: lib/cannery_web/components/ammo_group_table_component.ex:267
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "Empty"
@ -1036,7 +1036,7 @@ msgstr ""
msgid "Last used on:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:191
#: lib/cannery_web/components/ammo_group_table_component.ex:198
#, elixir-autogen, elixir-format
msgid "Never used"
msgstr ""

View File

@ -519,8 +519,8 @@ msgstr ""
msgid "Shot log"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:173
#: lib/cannery_web/components/ammo_group_table_component.ex:251
#: lib/cannery_web/components/ammo_group_table_component.ex:180
#: lib/cannery_web/components/ammo_group_table_component.ex:263
#: lib/cannery_web/components/ammo_type_table_component.ex:235
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:45
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:50
@ -614,8 +614,8 @@ msgstr ""
msgid "Rounds:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:170
#: lib/cannery_web/components/ammo_group_table_component.ex:247
#: lib/cannery_web/components/ammo_group_table_component.ex:177
#: lib/cannery_web/components/ammo_group_table_component.ex:259
#: lib/cannery_web/components/ammo_type_table_component.ex:234
#: lib/cannery_web/live/ammo_type_live/show.html.heex:139
#, elixir-autogen, elixir-format
@ -790,7 +790,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:57
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:54
#, elixir-autogen, elixir-format, fuzzy
msgid "Container:"
msgstr ""
@ -803,7 +803,7 @@ msgstr ""
msgid "Show used"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:207
#: lib/cannery_web/components/ammo_group_table_component.ex:218
#: lib/cannery_web/live/ammo_group_live/show.html.heex:19
#, elixir-autogen, elixir-format
msgid "%{percentage}%"
@ -990,7 +990,7 @@ msgstr ""
msgid "Edit %{ammo_type_name}"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:255
#: lib/cannery_web/components/ammo_group_table_component.ex:267
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "Empty"
@ -1036,7 +1036,7 @@ msgstr ""
msgid "Last used on:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:191
#: lib/cannery_web/components/ammo_group_table_component.ex:198
#, elixir-autogen, elixir-format
msgid "Never used"
msgstr ""

View File

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Language: en\n"
#: lib/cannery/containers.ex:201
#: lib/cannery/containers.ex:220
#, elixir-autogen, elixir-format
msgid "Container must be empty before deleting"
msgstr ""
@ -155,7 +155,7 @@ msgstr ""
msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}"
msgstr ""
#: lib/cannery/ammo.ex:1016
#: lib/cannery/ammo.ex:1043
#, elixir-autogen, elixir-format
msgid "Invalid multiplier"
msgstr ""

View File

@ -10,7 +10,7 @@
msgid ""
msgstr ""
#: lib/cannery/containers.ex:201
#: lib/cannery/containers.ex:220
#, elixir-autogen, elixir-format
msgid "Container must be empty before deleting"
msgstr ""
@ -154,7 +154,7 @@ msgstr ""
msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}"
msgstr ""
#: lib/cannery/ammo.ex:1016
#: lib/cannery/ammo.ex:1043
#, elixir-autogen, elixir-format
msgid "Invalid multiplier"
msgstr ""

View File

@ -526,8 +526,8 @@ msgstr "No hay otros contenedores"
msgid "Shot log"
msgstr "Registro de tiros"
#: lib/cannery_web/components/ammo_group_table_component.ex:173
#: lib/cannery_web/components/ammo_group_table_component.ex:251
#: lib/cannery_web/components/ammo_group_table_component.ex:180
#: lib/cannery_web/components/ammo_group_table_component.ex:263
#: lib/cannery_web/components/ammo_type_table_component.ex:235
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:45
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:50
@ -621,8 +621,8 @@ msgstr "Editar etiquetas de %{name}"
msgid "Rounds:"
msgstr "Balas:"
#: lib/cannery_web/components/ammo_group_table_component.ex:170
#: lib/cannery_web/components/ammo_group_table_component.ex:247
#: lib/cannery_web/components/ammo_group_table_component.ex:177
#: lib/cannery_web/components/ammo_group_table_component.ex:259
#: lib/cannery_web/components/ammo_type_table_component.ex:234
#: lib/cannery_web/live/ammo_type_live/show.html.heex:139
#, elixir-autogen, elixir-format
@ -798,7 +798,7 @@ msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
"Deje \"Usos restantes\" en blanco para hacer las invitaciónes ilimitadas"
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:57
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:54
#, elixir-autogen, elixir-format
msgid "Container:"
msgstr "Contenedor:"
@ -811,7 +811,7 @@ msgstr "Contenedor:"
msgid "Show used"
msgstr "Mostrar usadas"
#: lib/cannery_web/components/ammo_group_table_component.ex:207
#: lib/cannery_web/components/ammo_group_table_component.ex:218
#: lib/cannery_web/live/ammo_group_live/show.html.heex:19
#, elixir-autogen, elixir-format
msgid "%{percentage}%"
@ -998,7 +998,7 @@ msgstr ""
msgid "Edit %{ammo_type_name}"
msgstr "Editar %{ammo_type_name}"
#: lib/cannery_web/components/ammo_group_table_component.ex:255
#: lib/cannery_web/components/ammo_group_table_component.ex:267
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "Empty"
@ -1044,7 +1044,7 @@ msgstr "Usada por última vez en"
msgid "Last used on:"
msgstr "Usada por última vez en:"
#: lib/cannery_web/components/ammo_group_table_component.ex:191
#: lib/cannery_web/components/ammo_group_table_component.ex:198
#, elixir-autogen, elixir-format
msgid "Never used"
msgstr "Nunca usada"

View File

@ -23,7 +23,7 @@ msgstr ""
## Run "mix gettext.extract" to bring this file up to
## date. Leave "msgstr"s empty as changing them here has no
## effect: edit them in PO (.po) files instead.
#: lib/cannery/containers.ex:201
#: lib/cannery/containers.ex:220
#, elixir-autogen, elixir-format
msgid "Container must be empty before deleting"
msgstr "El contenedor debe estar vacío antes de ser borrado"
@ -170,7 +170,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:1016
#: lib/cannery/ammo.ex:1043
#, elixir-autogen, elixir-format
msgid "Invalid multiplier"
msgstr "Multiplicador inválido"

View File

@ -527,8 +527,8 @@ msgstr "Aucun autre conteneur"
msgid "Shot log"
msgstr "Évènements de tir"
#: lib/cannery_web/components/ammo_group_table_component.ex:173
#: lib/cannery_web/components/ammo_group_table_component.ex:251
#: lib/cannery_web/components/ammo_group_table_component.ex:180
#: lib/cannery_web/components/ammo_group_table_component.ex:263
#: lib/cannery_web/components/ammo_type_table_component.ex:235
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:45
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:50
@ -622,8 +622,8 @@ msgstr "Éditer les tags de %{name}"
msgid "Rounds:"
msgstr "Cartouches:"
#: lib/cannery_web/components/ammo_group_table_component.ex:170
#: lib/cannery_web/components/ammo_group_table_component.ex:247
#: lib/cannery_web/components/ammo_group_table_component.ex:177
#: lib/cannery_web/components/ammo_group_table_component.ex:259
#: lib/cannery_web/components/ammo_type_table_component.ex:234
#: lib/cannery_web/live/ammo_type_live/show.html.heex:139
#, elixir-autogen, elixir-format
@ -799,7 +799,7 @@ msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
"Laissez \"Utilisations restantes\" vide pour rendre l'invitation illimitée"
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:57
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:54
#, elixir-autogen, elixir-format, fuzzy
msgid "Container:"
msgstr "Conteneur"
@ -812,7 +812,7 @@ msgstr "Conteneur"
msgid "Show used"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:207
#: lib/cannery_web/components/ammo_group_table_component.ex:218
#: lib/cannery_web/live/ammo_group_live/show.html.heex:19
#, elixir-autogen, elixir-format
msgid "%{percentage}%"
@ -999,7 +999,7 @@ msgstr ""
msgid "Edit %{ammo_type_name}"
msgstr "Éditer %{name}"
#: lib/cannery_web/components/ammo_group_table_component.ex:255
#: lib/cannery_web/components/ammo_group_table_component.ex:267
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "Empty"
@ -1045,7 +1045,7 @@ msgstr ""
msgid "Last used on:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:191
#: lib/cannery_web/components/ammo_group_table_component.ex:198
#, elixir-autogen, elixir-format
msgid "Never used"
msgstr ""

View File

@ -23,7 +23,7 @@ msgstr ""
# # Run "mix gettext.extract" to bring this file up to
# # date. Leave "msgstr"s empty as changing them here has no
# # effect: edit them in PO (.po) files instead.
#: lib/cannery/containers.ex:201
#: lib/cannery/containers.ex:220
#, elixir-autogen, elixir-format
msgid "Container must be empty before deleting"
msgstr "Le conteneur doit être vide pour être supprimé"
@ -171,7 +171,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:1016
#: lib/cannery/ammo.ex:1043
#, elixir-autogen, elixir-format
msgid "Invalid multiplier"
msgstr "Multiplicateur invalide"

View File

@ -521,8 +521,8 @@ msgstr ""
msgid "Shot log"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:173
#: lib/cannery_web/components/ammo_group_table_component.ex:251
#: lib/cannery_web/components/ammo_group_table_component.ex:180
#: lib/cannery_web/components/ammo_group_table_component.ex:263
#: lib/cannery_web/components/ammo_type_table_component.ex:235
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:45
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:50
@ -616,8 +616,8 @@ msgstr ""
msgid "Rounds:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:170
#: lib/cannery_web/components/ammo_group_table_component.ex:247
#: lib/cannery_web/components/ammo_group_table_component.ex:177
#: lib/cannery_web/components/ammo_group_table_component.ex:259
#: lib/cannery_web/components/ammo_type_table_component.ex:234
#: lib/cannery_web/live/ammo_type_live/show.html.heex:139
#, elixir-autogen, elixir-format
@ -792,7 +792,7 @@ msgstr ""
msgid "Leave \"Uses left\" blank to make invite unlimited"
msgstr ""
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:57
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:54
#, elixir-autogen, elixir-format
msgid "Container:"
msgstr ""
@ -805,7 +805,7 @@ msgstr ""
msgid "Show used"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:207
#: lib/cannery_web/components/ammo_group_table_component.ex:218
#: lib/cannery_web/live/ammo_group_live/show.html.heex:19
#, elixir-autogen, elixir-format
msgid "%{percentage}%"
@ -992,7 +992,7 @@ msgstr ""
msgid "Edit %{ammo_type_name}"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:255
#: lib/cannery_web/components/ammo_group_table_component.ex:267
#: lib/cannery_web/components/core_components/ammo_group_card.html.heex:17
#, elixir-autogen, elixir-format
msgid "Empty"
@ -1038,7 +1038,7 @@ msgstr ""
msgid "Last used on:"
msgstr ""
#: lib/cannery_web/components/ammo_group_table_component.ex:191
#: lib/cannery_web/components/ammo_group_table_component.ex:198
#, elixir-autogen, elixir-format
msgid "Never used"
msgstr ""

View File

@ -24,7 +24,7 @@ msgstr ""
## Run "mix gettext.extract" to bring this file up to
## date. Leave "msgstr"s empty as changing them here has no
## effect: edit them in PO (.po) files instead.
#: lib/cannery/containers.ex:201
#: lib/cannery/containers.ex:220
#, elixir-autogen, elixir-format
msgid "Container must be empty before deleting"
msgstr "Caithfidh an coimeádán a bheidh follamh roimh scriosadh"
@ -170,7 +170,7 @@ msgstr ""
msgid "Invalid number of copies, must be between 1 and %{max}. Was %{multiplier}"
msgstr ""
#: lib/cannery/ammo.ex:1016
#: lib/cannery/ammo.ex:1043
#, elixir-autogen, elixir-format
msgid "Invalid multiplier"
msgstr ""

View File

@ -45,7 +45,7 @@ defmodule Cannery.AmmoTest do
assert Ammo.list_ammo_types(current_user) == [ammo_type]
end
test "list_ammo_types/1 returns relevant ammo_types for a user",
test "list_ammo_types/2 returns relevant ammo_types for a user",
%{current_user: current_user} do
ammo_type_a =
%{"name" => "bullets", "desc" => "has some pews in it", "grains" => 5}
@ -89,12 +89,12 @@ defmodule Cannery.AmmoTest do
assert Ammo.list_ammo_types("tracer", current_user) == [ammo_type_c]
end
test "get_ammo_type!/1 returns the ammo_type with given id",
test "get_ammo_type!/2 returns the ammo_type with given id",
%{ammo_type: ammo_type, current_user: current_user} do
assert Ammo.get_ammo_type!(ammo_type.id, current_user) == ammo_type
end
test "create_ammo_type/1 with valid data creates a ammo_type",
test "create_ammo_type/2 with valid data creates a ammo_type",
%{current_user: current_user} do
assert {:ok, %AmmoType{} = ammo_type} = Ammo.create_ammo_type(@valid_attrs, current_user)
assert ammo_type.bullet_type == "some bullet_type"
@ -105,12 +105,12 @@ defmodule Cannery.AmmoTest do
assert ammo_type.grains == 120
end
test "create_ammo_type/1 with invalid data returns error changeset",
test "create_ammo_type/2 with invalid data returns error changeset",
%{current_user: current_user} do
assert {:error, %Changeset{}} = Ammo.create_ammo_type(@invalid_attrs, current_user)
end
test "update_ammo_type/2 with valid data updates the ammo_type",
test "update_ammo_type/3 with valid data updates the ammo_type",
%{ammo_type: ammo_type, current_user: current_user} do
assert {:ok, %AmmoType{} = ammo_type} =
Ammo.update_ammo_type(ammo_type, @update_attrs, current_user)
@ -123,7 +123,7 @@ defmodule Cannery.AmmoTest do
assert ammo_type.grains == 456
end
test "update_ammo_type/2 with invalid data returns error changeset",
test "update_ammo_type/3 with invalid data returns error changeset",
%{ammo_type: ammo_type, current_user: current_user} do
assert {:error, %Changeset{}} =
Ammo.update_ammo_type(ammo_type, @invalid_attrs, current_user)
@ -131,7 +131,7 @@ defmodule Cannery.AmmoTest do
assert ammo_type == Ammo.get_ammo_type!(ammo_type.id, current_user)
end
test "delete_ammo_type/1 deletes the ammo_type",
test "delete_ammo_type/2 deletes the ammo_type",
%{ammo_type: ammo_type, current_user: current_user} do
assert {:ok, %AmmoType{}} = Ammo.delete_ammo_type(ammo_type, current_user)
assert_raise Ecto.NoResultsError, fn -> Ammo.get_ammo_type!(ammo_type.id, current_user) end
@ -785,7 +785,7 @@ defmodule Cannery.AmmoTest do
assert %{^another_ammo_type_id => 1} = ammo_groups_count
end
test "list_staged_ammo_groups/2 returns all ammo_groups that are staged",
test "list_staged_ammo_groups/1 returns all ammo_groups that are staged",
%{
ammo_type: ammo_type,
container: container,
@ -797,7 +797,7 @@ defmodule Cannery.AmmoTest do
assert Ammo.list_staged_ammo_groups(current_user) == [another_ammo_group]
end
test "get_ammo_group!/1 returns the ammo_group with given id",
test "get_ammo_group!/2 returns the ammo_group with given id",
%{ammo_group: %{id: ammo_group_id} = ammo_group, current_user: current_user} do
assert Ammo.get_ammo_group!(ammo_group_id, current_user) == ammo_group
end
@ -861,7 +861,7 @@ defmodule Cannery.AmmoTest do
|> Ammo.create_ammo_groups(1, current_user)
end
test "update_ammo_group/2 with valid data updates the ammo_group",
test "update_ammo_group/3 with valid data updates the ammo_group",
%{ammo_group: ammo_group, current_user: current_user} do
assert {:ok, %AmmoGroup{} = ammo_group} =
Ammo.update_ammo_group(ammo_group, @update_attrs, current_user)
@ -871,7 +871,7 @@ defmodule Cannery.AmmoTest do
assert ammo_group.price_paid == 456.7
end
test "update_ammo_group/2 with invalid data returns error changeset",
test "update_ammo_group/3 with invalid data returns error changeset",
%{ammo_group: ammo_group, current_user: current_user} do
assert {:error, %Changeset{}} =
Ammo.update_ammo_group(ammo_group, @invalid_attrs, current_user)
@ -879,13 +879,13 @@ defmodule Cannery.AmmoTest do
assert ammo_group == Ammo.get_ammo_group!(ammo_group.id, current_user)
end
test "delete_ammo_group/1 deletes the ammo_group",
test "delete_ammo_group/2 deletes the ammo_group",
%{ammo_group: ammo_group, current_user: current_user} do
assert {:ok, %AmmoGroup{}} = Ammo.delete_ammo_group(ammo_group, current_user)
assert_raise KeyError, fn -> Ammo.get_ammo_group!(ammo_group.id, current_user) end
end
test "get_percentage_remaining/1 gets accurate total round count",
test "get_percentage_remaining/2 gets accurate total round count",
%{ammo_group: %{id: ammo_group_id} = ammo_group, current_user: current_user} do
assert 100 = ammo_group |> Ammo.get_percentage_remaining(current_user)
@ -902,6 +902,53 @@ defmodule Cannery.AmmoTest do
assert 0 = ammo_group |> Ammo.get_percentage_remaining(current_user)
end
test "get_percentages_remaining/2 gets accurate total round count", %{
ammo_group: %{id: ammo_group_id} = ammo_group,
ammo_type: ammo_type,
container: container,
current_user: current_user
} do
assert %{ammo_group_id => 100} ==
[ammo_group] |> Ammo.get_percentages_remaining(current_user)
{1, [%{id: another_ammo_group_id} = another_ammo_group]} =
%{"count" => 50, "price_paid" => 36.1}
|> ammo_group_fixture(ammo_type, container, current_user)
percentages =
[ammo_group, another_ammo_group] |> Ammo.get_percentages_remaining(current_user)
assert %{^ammo_group_id => 100} = percentages
assert %{^another_ammo_group_id => 100} = percentages
shot_group_fixture(%{"count" => 14}, current_user, ammo_group)
ammo_group = Ammo.get_ammo_group!(ammo_group_id, current_user)
percentages =
[ammo_group, another_ammo_group] |> Ammo.get_percentages_remaining(current_user)
assert %{^ammo_group_id => 72} = percentages
assert %{^another_ammo_group_id => 100} = percentages
shot_group_fixture(%{"count" => 11}, current_user, ammo_group)
ammo_group = Ammo.get_ammo_group!(ammo_group_id, current_user)
percentages =
[ammo_group, another_ammo_group] |> Ammo.get_percentages_remaining(current_user)
assert %{^ammo_group_id => 50} = percentages
assert %{^another_ammo_group_id => 100} = percentages
shot_group_fixture(%{"count" => 25}, current_user, ammo_group)
ammo_group = Ammo.get_ammo_group!(ammo_group_id, current_user)
percentages =
[ammo_group, another_ammo_group] |> Ammo.get_percentages_remaining(current_user)
assert %{^ammo_group_id => 0} = percentages
assert %{^another_ammo_group_id => 100} = percentages
end
test "get_cpr/2 gets accurate cpr",
%{ammo_type: ammo_type, container: container, current_user: current_user} do
{1, [ammo_group]} = ammo_group_fixture(%{"count" => 1}, ammo_type, container, current_user)

View File

@ -90,12 +90,24 @@ defmodule Cannery.ContainersTest do
assert Containers.list_containers("asajslkdflskdf", current_user) == []
end
test "get_container!/1 returns the container with given id",
test "get_container!/2 returns the container with given id",
%{current_user: current_user, container: container} do
assert Containers.get_container!(container.id, current_user) == container
assert_raise KeyError, fn -> Containers.get_container!(current_user.id, current_user) end
end
test "create_container/1 with valid data creates a container", %{current_user: current_user} do
test "get_containers/2 returns the container with given id",
%{current_user: current_user, container: %{id: container_id} = container} do
assert %{container_id => container} ==
Containers.get_containers([container_id], current_user)
%{id: another_container_id} = another_container = container_fixture(current_user)
containers = [container_id, another_container_id] |> Containers.get_containers(current_user)
assert %{^container_id => ^container} = containers
assert %{^another_container_id => ^another_container} = containers
end
test "create_container/2 with valid data creates a container", %{current_user: current_user} do
assert {:ok, %Container{} = container} =
@valid_attrs |> Containers.create_container(current_user)
@ -106,12 +118,12 @@ defmodule Cannery.ContainersTest do
assert container.user_id == current_user.id
end
test "create_container/1 with invalid data returns error changeset",
test "create_container/2 with invalid data returns error changeset",
%{current_user: current_user} do
assert {:error, %Changeset{}} = @invalid_attrs |> Containers.create_container(current_user)
end
test "update_container/2 with valid data updates the container",
test "update_container/3 with valid data updates the container",
%{current_user: current_user, container: container} do
assert {:ok, %Container{} = container} =
Containers.update_container(container, current_user, @update_attrs)
@ -122,7 +134,7 @@ defmodule Cannery.ContainersTest do
assert container.type == "some updated type"
end
test "update_container/2 with invalid data returns error changeset",
test "update_container/3 with invalid data returns error changeset",
%{current_user: current_user, container: container} do
assert {:error, %Changeset{}} =
Containers.update_container(container, current_user, @invalid_attrs)
@ -130,11 +142,11 @@ defmodule Cannery.ContainersTest do
assert container == Containers.get_container!(container.id, current_user)
end
test "delete_container/1 deletes the container",
test "delete_container/2 deletes the container",
%{current_user: current_user, container: container} do
assert {:ok, %Container{}} = Containers.delete_container(container, current_user)
assert_raise Ecto.NoResultsError, fn ->
assert_raise KeyError, fn ->
Containers.get_container!(container.id, current_user)
end
end
@ -168,36 +180,36 @@ defmodule Cannery.ContainersTest do
assert Containers.list_tags("hollows", current_user) == [tag_b]
end
test "get_tag!/1 returns the tag with given id", %{tag: tag, current_user: current_user} do
test "get_tag!/2 returns the tag with given id", %{tag: tag, current_user: current_user} do
assert Containers.get_tag!(tag.id, current_user) == tag
end
test "create_tag/1 with valid data creates a tag", %{current_user: current_user} do
test "create_tag/2 with valid data creates a tag", %{current_user: current_user} do
assert {:ok, %Tag{} = tag} = Containers.create_tag(@valid_tag_attrs, current_user)
assert tag.bg_color == "some bg-color"
assert tag.name == "some name"
assert tag.text_color == "some text-color"
end
test "create_tag/1 with invalid data returns error changeset",
test "create_tag/2 with invalid data returns error changeset",
%{current_user: current_user} do
assert {:error, %Changeset{}} = Containers.create_tag(@invalid_tag_attrs, current_user)
end
test "update_tag/2 with valid data updates the tag", %{tag: tag, current_user: current_user} do
test "update_tag/3 with valid data updates the tag", %{tag: tag, current_user: current_user} do
assert {:ok, %Tag{} = tag} = Containers.update_tag(tag, @update_tag_attrs, current_user)
assert tag.bg_color == "some updated bg-color"
assert tag.name == "some updated name"
assert tag.text_color == "some updated text-color"
end
test "update_tag/2 with invalid data returns error changeset",
test "update_tag/3 with invalid data returns error changeset",
%{tag: tag, current_user: current_user} do
assert {:error, %Changeset{}} = Containers.update_tag(tag, @invalid_tag_attrs, current_user)
assert tag == Containers.get_tag!(tag.id, current_user)
end
test "delete_tag/1 deletes the tag", %{tag: tag, current_user: current_user} do
test "delete_tag/2 deletes the tag", %{tag: tag, current_user: current_user} do
assert {:ok, %Tag{}} = Containers.delete_tag(tag, current_user)
assert_raise Ecto.NoResultsError, fn -> Containers.get_tag!(tag.id, current_user) end
end

View File

@ -309,12 +309,8 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
assert html =~ dgettext("actions", "Show used")
refute html =~ gettext("$%{amount}", amount: display_currency(50.00))
refute html =~
"\n" <>
gettext("%{percentage}%",
percentage: ammo_group |> Ammo.get_percentage_remaining(current_user)
) <>
"\n"
percentage = ammo_group |> Ammo.get_percentage_remaining(current_user)
refute html =~ "\n#{gettext("%{percentage}%", percentage: percentage)}\n"
html =
show_live
@ -323,12 +319,8 @@ defmodule CanneryWeb.AmmoGroupLiveTest do
assert html =~ gettext("$%{amount}", amount: display_currency(50.00))
assert html =~
"\n" <>
gettext("%{percentage}%",
percentage: ammo_group |> Ammo.get_percentage_remaining(current_user)
) <>
"\n"
percentage = ammo_group |> Ammo.get_percentage_remaining(current_user)
assert html =~ "\n#{gettext("%{percentage}%", percentage: percentage)}\n"
end
end