forked from shibao/cannery
show original count, current value, percentage remaining and shot history for ammo groups
This commit is contained in:
parent
91ff0c14e4
commit
dba53106fb
@ -4,7 +4,8 @@
|
||||
- Add "Cannery" to page titles
|
||||
- Don't show true/false column for ammo types if all values are false
|
||||
- Fix ammo type firing type display
|
||||
|
||||
- Show original count, current value, and percentage remaining for ammo groups
|
||||
- Show shot history for an ammo group
|
||||
|
||||
# 0.1.0
|
||||
- Initial release!
|
||||
|
@ -162,10 +162,12 @@ defmodule Cannery.Ammo do
|
||||
@spec list_ammo_groups_for_type(AmmoType.t(), User.t()) :: [AmmoGroup.t()]
|
||||
def list_ammo_groups_for_type(%AmmoType{id: ammo_type_id, user_id: user_id}, %User{id: user_id}) do
|
||||
Repo.all(
|
||||
from am in AmmoGroup,
|
||||
where: am.ammo_type_id == ^ammo_type_id,
|
||||
where: am.user_id == ^user_id,
|
||||
order_by: am.id
|
||||
from ag in AmmoGroup,
|
||||
left_join: sg in assoc(ag, :shot_groups),
|
||||
where: ag.ammo_type_id == ^ammo_type_id,
|
||||
where: ag.user_id == ^user_id,
|
||||
preload: [shot_groups: sg],
|
||||
order_by: ag.id
|
||||
)
|
||||
end
|
||||
|
||||
@ -182,12 +184,18 @@ defmodule Cannery.Ammo do
|
||||
@spec list_ammo_groups(User.t(), include_empty :: boolean()) :: [AmmoGroup.t()]
|
||||
def list_ammo_groups(%User{id: user_id}, include_empty \\ false) do
|
||||
if include_empty do
|
||||
from am in AmmoGroup, where: am.user_id == ^user_id, order_by: am.id
|
||||
from ag in AmmoGroup,
|
||||
left_join: sg in assoc(ag, :shot_groups),
|
||||
where: ag.user_id == ^user_id,
|
||||
preload: [shot_groups: sg],
|
||||
order_by: ag.id
|
||||
else
|
||||
from am in AmmoGroup,
|
||||
where: am.user_id == ^user_id,
|
||||
where: not (am.count == 0),
|
||||
order_by: am.id
|
||||
from ag in AmmoGroup,
|
||||
left_join: sg in assoc(ag, :shot_groups),
|
||||
where: ag.user_id == ^user_id,
|
||||
where: not (ag.count == 0),
|
||||
preload: [shot_groups: sg],
|
||||
order_by: ag.id
|
||||
end
|
||||
|> Repo.all()
|
||||
end
|
||||
@ -204,10 +212,12 @@ defmodule Cannery.Ammo do
|
||||
@spec list_staged_ammo_groups(User.t()) :: [AmmoGroup.t()]
|
||||
def list_staged_ammo_groups(%User{id: user_id}) do
|
||||
Repo.all(
|
||||
from am in AmmoGroup,
|
||||
where: am.user_id == ^user_id,
|
||||
where: am.staged == true,
|
||||
order_by: am.id
|
||||
from ag in AmmoGroup,
|
||||
left_join: sg in assoc(ag, :shot_groups),
|
||||
where: ag.user_id == ^user_id,
|
||||
where: ag.staged == true,
|
||||
preload: [shot_groups: sg],
|
||||
order_by: ag.id
|
||||
)
|
||||
end
|
||||
|
||||
@ -226,8 +236,42 @@ defmodule Cannery.Ammo do
|
||||
|
||||
"""
|
||||
@spec get_ammo_group!(AmmoGroup.id(), User.t()) :: AmmoGroup.t()
|
||||
def get_ammo_group!(id, %User{id: user_id}),
|
||||
do: Repo.one!(from am in AmmoGroup, where: am.id == ^id and am.user_id == ^user_id)
|
||||
def get_ammo_group!(id, %User{id: user_id}) do
|
||||
Repo.one!(
|
||||
from ag in AmmoGroup,
|
||||
left_join: sg in assoc(ag, :shot_groups),
|
||||
where: ag.id == ^id,
|
||||
where: ag.user_id == ^user_id,
|
||||
preload: [shot_groups: sg]
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the number of shot rounds for an ammo group
|
||||
"""
|
||||
@spec get_used_count(AmmoGroup.t()) :: non_neg_integer()
|
||||
def get_used_count(%AmmoGroup{} = ammo_group) do
|
||||
ammo_group
|
||||
|> Repo.preload(:shot_groups)
|
||||
|> Map.get(:shot_groups)
|
||||
|> Enum.map(fn %{count: count} -> count end)
|
||||
|> Enum.sum()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Calculates the percentage remaining of an ammo group out of 100
|
||||
"""
|
||||
@spec get_percentage_remaining(AmmoGroup.t()) :: non_neg_integer()
|
||||
def get_percentage_remaining(%AmmoGroup{count: 0}), do: 0
|
||||
|
||||
def get_percentage_remaining(%AmmoGroup{count: count} = ammo_group) do
|
||||
ammo_group = ammo_group |> Repo.preload(:shot_groups)
|
||||
|
||||
shot_group_sum =
|
||||
ammo_group.shot_groups |> Enum.map(fn %{count: count} -> count end) |> Enum.sum()
|
||||
|
||||
round(count / (count + shot_group_sum) * 100)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a ammo_group.
|
||||
|
@ -33,7 +33,7 @@
|
||||
<%= gettext("Price paid") %>
|
||||
</th>
|
||||
<th class="p-2">
|
||||
<%= gettext("Notes") %>
|
||||
<%= gettext("% left") %>
|
||||
</th>
|
||||
<th class="p-2">
|
||||
<%= gettext("Range") %>
|
||||
@ -68,7 +68,7 @@
|
||||
</td>
|
||||
|
||||
<td class="p-2">
|
||||
<%= ammo_group.notes %>
|
||||
<%= "#{ammo_group |> Ammo.get_percentage_remaining()}%" %>
|
||||
</td>
|
||||
|
||||
<td class="p-2">
|
||||
|
@ -9,6 +9,16 @@
|
||||
<%= @ammo_group.count %>
|
||||
</span>
|
||||
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Original count:") %>
|
||||
<%= @ammo_group.count + Ammo.get_used_count(@ammo_group) %>
|
||||
</span>
|
||||
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Percentage left:") %>
|
||||
<%= "#{@ammo_group |> Ammo.get_percentage_remaining()}%" %>
|
||||
</span>
|
||||
|
||||
<%= if @ammo_group.notes do %>
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Notes:") %>
|
||||
@ -18,11 +28,20 @@
|
||||
|
||||
<%= if @ammo_group.price_paid do %>
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Price paid:") %>
|
||||
<%= gettext("Original cost:") %>
|
||||
<%= gettext("$%{amount}",
|
||||
amount: @ammo_group.price_paid |> :erlang.float_to_binary(decimals: 2)
|
||||
) %>
|
||||
</span>
|
||||
|
||||
<span class="rounded-lg title text-lg">
|
||||
<%= gettext("Current value:") %>
|
||||
<%= gettext("$%{amount}",
|
||||
amount:
|
||||
(@ammo_group.price_paid * Ammo.get_percentage_remaining(@ammo_group) / 100)
|
||||
|> :erlang.float_to_binary(decimals: 2)
|
||||
) %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@ -84,6 +103,47 @@
|
||||
<%= gettext("This ammo group is not in a container") %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= unless @ammo_group.shot_groups |> Enum.empty?() do %>
|
||||
<hr class="mb-4 w-full" />
|
||||
|
||||
<h1 class="mb-4 px-4 py-2 text-center rounded-lg title text-xl">
|
||||
<%= gettext("Rounds used") %>
|
||||
</h1>
|
||||
|
||||
<div class="w-full overflow-x-auto border border-gray-600 rounded-lg shadow-lg bg-black">
|
||||
<table class="min-w-full table-auto text-center bg-white">
|
||||
<thead class="border-b border-primary-600">
|
||||
<tr>
|
||||
<th class="p-2">
|
||||
<%= gettext("Rounds shot") %>
|
||||
</th>
|
||||
<th class="p-2">
|
||||
<%= gettext("Notes") %>
|
||||
</th>
|
||||
<th class="p-2">
|
||||
<%= gettext("Date") %>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="shot_groups">
|
||||
<%= for shot_group <- @ammo_group.shot_groups do %>
|
||||
<tr id={"shot_group-#{shot_group.id}"}>
|
||||
<td class="p-2">
|
||||
<%= shot_group.count %>
|
||||
</td>
|
||||
<td class="p-2">
|
||||
<%= shot_group.notes %>
|
||||
</td>
|
||||
<td class="p-2">
|
||||
<%= shot_group.date |> display_date() %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= case @live_action do %>
|
||||
|
@ -161,13 +161,13 @@ msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:85
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:67
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:86
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:36
|
||||
msgid "Record shots"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:31
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:50
|
||||
msgid "Ammo Details"
|
||||
msgstr ""
|
||||
|
||||
@ -177,7 +177,7 @@ msgid "Add another container!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:61
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:80
|
||||
msgid "Move containers"
|
||||
msgstr ""
|
||||
|
||||
|
@ -358,7 +358,7 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/components/add_shot_group_component.html.heex:30
|
||||
#: lib/cannery_web/live/ammo_group_live/form_component.html.heex:41
|
||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:36
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:122
|
||||
#: lib/cannery_web/live/range_live/form_component.html.heex:29
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:67
|
||||
msgid "Notes"
|
||||
@ -366,7 +366,7 @@ msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/components/ammo_group_card.ex:35
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:14
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:24
|
||||
msgid "Notes:"
|
||||
msgstr ""
|
||||
|
||||
@ -390,7 +390,6 @@ msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/components/ammo_group_card.ex:42
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:21
|
||||
msgid "Price paid:"
|
||||
msgstr ""
|
||||
|
||||
@ -447,7 +446,7 @@ msgid "Steel"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:79
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:98
|
||||
msgid "Stored in"
|
||||
msgstr ""
|
||||
|
||||
@ -473,7 +472,7 @@ msgid "The self-hosted firearm tracker website"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:84
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:103
|
||||
msgid "This ammo group is not in a container"
|
||||
msgstr ""
|
||||
|
||||
@ -538,6 +537,7 @@ msgid "Range day"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:125
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:70
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
@ -553,13 +553,13 @@ msgid "No ammo staged"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:58
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:77
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:33
|
||||
msgid "Stage for range"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:57
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:76
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:32
|
||||
msgid "Unstage from range"
|
||||
msgstr ""
|
||||
@ -613,6 +613,7 @@ msgid "Rounds left"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:119
|
||||
#: lib/cannery_web/live/range_live/index.html.heex:64
|
||||
msgid "Rounds shot"
|
||||
msgstr ""
|
||||
@ -646,7 +647,8 @@ msgstr ""
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/components/ammo_group_card.ex:43
|
||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:64
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:22
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:32
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:39
|
||||
#: lib/cannery_web/live/ammo_type_live/show.html.heex:82
|
||||
msgid "$%{amount}"
|
||||
msgstr ""
|
||||
@ -760,3 +762,33 @@ msgstr ""
|
||||
#: lib/cannery_web/live/ammo_type_live/show.html.heex:88
|
||||
msgid "No cost information"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:36
|
||||
msgid "% left"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:38
|
||||
msgid "Current value:"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:31
|
||||
msgid "Original cost:"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:13
|
||||
msgid "Original count:"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:18
|
||||
msgid "Percentage left:"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:111
|
||||
msgid "Rounds used"
|
||||
msgstr ""
|
||||
|
@ -98,7 +98,7 @@ msgstr ""
|
||||
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/cannery_web/live/ammo_group_live/index.html.heex:120
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:47
|
||||
#: lib/cannery_web/live/ammo_group_live/show.html.heex:66
|
||||
#: lib/cannery_web/live/ammo_type_live/index.html.heex:68
|
||||
msgid "Are you sure you want to delete this ammo?"
|
||||
msgstr ""
|
||||
|
Loading…
Reference in New Issue
Block a user