forked from shibao/cannery
rename ammo type to type
This commit is contained in:
@ -4,7 +4,7 @@ defmodule Cannery.ActivityLog do
|
||||
"""
|
||||
|
||||
import Ecto.Query, warn: false
|
||||
alias Cannery.Ammo.{AmmoType, Pack}
|
||||
alias Cannery.Ammo.{Pack, Type}
|
||||
alias Cannery.{Accounts.User, ActivityLog.ShotRecord, Repo}
|
||||
alias Ecto.{Multi, Queryable}
|
||||
|
||||
@ -23,8 +23,8 @@ defmodule Cannery.ActivityLog do
|
||||
[%ShotRecord{notes: "Shot some rifle rounds"}, ...]
|
||||
|
||||
"""
|
||||
@spec list_shot_records(AmmoType.class() | :all, User.t()) :: [ShotRecord.t()]
|
||||
@spec list_shot_records(search :: nil | String.t(), AmmoType.class() | :all, User.t()) ::
|
||||
@spec list_shot_records(Type.class() | :all, User.t()) :: [ShotRecord.t()]
|
||||
@spec list_shot_records(search :: nil | String.t(), Type.class() | :all, User.t()) ::
|
||||
[ShotRecord.t()]
|
||||
def list_shot_records(search \\ nil, type, %{id: user_id}) do
|
||||
from(sg in ShotRecord,
|
||||
@ -32,9 +32,9 @@ defmodule Cannery.ActivityLog do
|
||||
left_join: ag in Pack,
|
||||
as: :ag,
|
||||
on: sg.pack_id == ag.id,
|
||||
left_join: at in AmmoType,
|
||||
left_join: at in Type,
|
||||
as: :at,
|
||||
on: ag.ammo_type_id == at.id,
|
||||
on: ag.type_id == at.id,
|
||||
where: sg.user_id == ^user_id,
|
||||
distinct: sg.id
|
||||
)
|
||||
@ -79,7 +79,7 @@ defmodule Cannery.ActivityLog do
|
||||
})
|
||||
end
|
||||
|
||||
@spec list_shot_records_filter_type(Queryable.t(), AmmoType.class() | :all) ::
|
||||
@spec list_shot_records_filter_type(Queryable.t(), Type.class() | :all) ::
|
||||
Queryable.t()
|
||||
defp list_shot_records_filter_type(query, :rifle),
|
||||
do: query |> where([at: at], at.class == :rifle)
|
||||
@ -347,50 +347,50 @@ defmodule Cannery.ActivityLog do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the total number of rounds shot for an ammo type
|
||||
Gets the total number of rounds shot for a type
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Ammo type does not exist.
|
||||
Raises `Ecto.NoResultsError` if the type does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_used_count_for_ammo_type(123, %User{id: 123})
|
||||
iex> get_used_count_for_type(123, %User{id: 123})
|
||||
35
|
||||
|
||||
iex> get_used_count_for_ammo_type(456, %User{id: 123})
|
||||
iex> get_used_count_for_type(456, %User{id: 123})
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
@spec get_used_count_for_ammo_type(AmmoType.t(), User.t()) :: non_neg_integer()
|
||||
def get_used_count_for_ammo_type(%AmmoType{id: ammo_type_id} = ammo_type, user) do
|
||||
[ammo_type]
|
||||
|> get_used_count_for_ammo_types(user)
|
||||
|> Map.get(ammo_type_id, 0)
|
||||
@spec get_used_count_for_type(Type.t(), User.t()) :: non_neg_integer()
|
||||
def get_used_count_for_type(%Type{id: type_id} = type, user) do
|
||||
[type]
|
||||
|> get_used_count_for_types(user)
|
||||
|> Map.get(type_id, 0)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the total number of rounds shot for multiple ammo types
|
||||
Gets the total number of rounds shot for multiple types
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_used_count_for_ammo_types(123, %User{id: 123})
|
||||
iex> get_used_count_for_types(123, %User{id: 123})
|
||||
35
|
||||
|
||||
"""
|
||||
@spec get_used_count_for_ammo_types([AmmoType.t()], User.t()) ::
|
||||
%{optional(AmmoType.id()) => non_neg_integer()}
|
||||
def get_used_count_for_ammo_types(ammo_types, %User{id: user_id}) do
|
||||
ammo_type_ids =
|
||||
ammo_types
|
||||
|> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end)
|
||||
@spec get_used_count_for_types([Type.t()], User.t()) ::
|
||||
%{optional(Type.id()) => non_neg_integer()}
|
||||
def get_used_count_for_types(types, %User{id: user_id}) do
|
||||
type_ids =
|
||||
types
|
||||
|> Enum.map(fn %Type{id: type_id, user_id: ^user_id} -> type_id end)
|
||||
|
||||
Repo.all(
|
||||
from ag in Pack,
|
||||
left_join: sg in ShotRecord,
|
||||
on: ag.id == sg.pack_id,
|
||||
where: ag.ammo_type_id in ^ammo_type_ids,
|
||||
where: ag.type_id in ^type_ids,
|
||||
where: not (sg.count |> is_nil()),
|
||||
group_by: ag.ammo_type_id,
|
||||
select: {ag.ammo_type_id, sum(sg.count)}
|
||||
group_by: ag.type_id,
|
||||
select: {ag.type_id, sum(sg.count)}
|
||||
)
|
||||
|> Map.new()
|
||||
end
|
||||
|
@ -8,46 +8,46 @@ defmodule Cannery.Ammo do
|
||||
alias Cannery.{Accounts.User, Containers, Repo}
|
||||
alias Cannery.Containers.{Container, ContainerTag, Tag}
|
||||
alias Cannery.{ActivityLog, ActivityLog.ShotRecord}
|
||||
alias Cannery.Ammo.{AmmoType, Pack}
|
||||
alias Cannery.Ammo.{Pack, Type}
|
||||
alias Ecto.{Changeset, Queryable}
|
||||
|
||||
@pack_create_limit 10_000
|
||||
@pack_preloads [:ammo_type]
|
||||
@ammo_type_preloads [:packs]
|
||||
@pack_preloads [:type]
|
||||
@type_preloads [:packs]
|
||||
|
||||
@doc """
|
||||
Returns the list of ammo_types.
|
||||
Returns the list of types.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_ammo_types(%User{id: 123}, :all)
|
||||
[%AmmoType{}, ...]
|
||||
iex> list_types(%User{id: 123}, :all)
|
||||
[%Type{}, ...]
|
||||
|
||||
iex> list_ammo_types("cool", %User{id: 123}, :shotgun)
|
||||
[%AmmoType{name: "My cool ammo type", class: :shotgun}, ...]
|
||||
iex> list_types("cool", %User{id: 123}, :shotgun)
|
||||
[%Type{name: "My cool type", class: :shotgun}, ...]
|
||||
|
||||
"""
|
||||
@spec list_ammo_types(User.t(), AmmoType.class() | :all) :: [AmmoType.t()]
|
||||
@spec list_ammo_types(search :: nil | String.t(), User.t(), AmmoType.class() | :all) ::
|
||||
[AmmoType.t()]
|
||||
def list_ammo_types(search \\ nil, user, type)
|
||||
@spec list_types(User.t(), Type.class() | :all) :: [Type.t()]
|
||||
@spec list_types(search :: nil | String.t(), User.t(), Type.class() | :all) ::
|
||||
[Type.t()]
|
||||
def list_types(search \\ nil, user, type)
|
||||
|
||||
def list_ammo_types(search, %{id: user_id}, type) do
|
||||
from(at in AmmoType,
|
||||
def list_types(search, %{id: user_id}, type) do
|
||||
from(at in Type,
|
||||
as: :at,
|
||||
where: at.user_id == ^user_id,
|
||||
preload: ^@ammo_type_preloads
|
||||
preload: ^@type_preloads
|
||||
)
|
||||
|> list_ammo_types_filter_type(type)
|
||||
|> list_ammo_types_filter_search(search)
|
||||
|> list_types_filter_type(type)
|
||||
|> list_types_filter_search(search)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@spec list_ammo_types_filter_search(Queryable.t(), search :: String.t() | nil) :: Queryable.t()
|
||||
defp list_ammo_types_filter_search(query, search) when search in ["", nil],
|
||||
@spec list_types_filter_search(Queryable.t(), search :: String.t() | nil) :: Queryable.t()
|
||||
defp list_types_filter_search(query, search) when search in ["", nil],
|
||||
do: query |> order_by([at: at], at.name)
|
||||
|
||||
defp list_ammo_types_filter_search(query, search) when search |> is_binary() do
|
||||
defp list_types_filter_search(query, search) when search |> is_binary() do
|
||||
trimmed_search = String.trim(search)
|
||||
|
||||
query
|
||||
@ -72,31 +72,31 @@ defmodule Cannery.Ammo do
|
||||
)
|
||||
end
|
||||
|
||||
@spec list_ammo_types_filter_type(Queryable.t(), AmmoType.class() | :all) :: Queryable.t()
|
||||
defp list_ammo_types_filter_type(query, :rifle),
|
||||
@spec list_types_filter_type(Queryable.t(), Type.class() | :all) :: Queryable.t()
|
||||
defp list_types_filter_type(query, :rifle),
|
||||
do: query |> where([at: at], at.class == :rifle)
|
||||
|
||||
defp list_ammo_types_filter_type(query, :pistol),
|
||||
defp list_types_filter_type(query, :pistol),
|
||||
do: query |> where([at: at], at.class == :pistol)
|
||||
|
||||
defp list_ammo_types_filter_type(query, :shotgun),
|
||||
defp list_types_filter_type(query, :shotgun),
|
||||
do: query |> where([at: at], at.class == :shotgun)
|
||||
|
||||
defp list_ammo_types_filter_type(query, _all), do: query
|
||||
defp list_types_filter_type(query, _all), do: query
|
||||
|
||||
@doc """
|
||||
Returns a count of ammo_types.
|
||||
Returns a count of types.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_ammo_types_count!(%User{id: 123})
|
||||
iex> get_types_count!(%User{id: 123})
|
||||
3
|
||||
|
||||
"""
|
||||
@spec get_ammo_types_count!(User.t()) :: integer()
|
||||
def get_ammo_types_count!(%User{id: user_id}) do
|
||||
@spec get_types_count!(User.t()) :: integer()
|
||||
def get_types_count!(%User{id: user_id}) do
|
||||
Repo.one(
|
||||
from at in AmmoType,
|
||||
from at in Type,
|
||||
where: at.user_id == ^user_id,
|
||||
select: count(at.id),
|
||||
distinct: true
|
||||
@ -104,67 +104,67 @@ defmodule Cannery.Ammo do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single ammo_type.
|
||||
Gets a single type.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Ammo type does not exist.
|
||||
Raises `Ecto.NoResultsError` if the type does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_ammo_type!(123, %User{id: 123})
|
||||
%AmmoType{}
|
||||
iex> get_type!(123, %User{id: 123})
|
||||
%Type{}
|
||||
|
||||
iex> get_ammo_type!(456, %User{id: 123})
|
||||
iex> get_type!(456, %User{id: 123})
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
@spec get_ammo_type!(AmmoType.id(), User.t()) :: AmmoType.t()
|
||||
def get_ammo_type!(id, %User{id: user_id}) do
|
||||
@spec get_type!(Type.id(), User.t()) :: Type.t()
|
||||
def get_type!(id, %User{id: user_id}) do
|
||||
Repo.one!(
|
||||
from at in AmmoType,
|
||||
from at in Type,
|
||||
where: at.id == ^id,
|
||||
where: at.user_id == ^user_id,
|
||||
preload: ^@ammo_type_preloads
|
||||
preload: ^@type_preloads
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the average cost of an ammo type from packs with price information.
|
||||
Gets the average cost of a type from packs with price information.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_average_cost_for_ammo_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
iex> get_average_cost_for_type(
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
1.50
|
||||
|
||||
"""
|
||||
@spec get_average_cost_for_ammo_type(AmmoType.t(), User.t()) :: float() | nil
|
||||
def get_average_cost_for_ammo_type(%AmmoType{id: ammo_type_id} = ammo_type, user) do
|
||||
[ammo_type]
|
||||
|> get_average_cost_for_ammo_types(user)
|
||||
|> Map.get(ammo_type_id)
|
||||
@spec get_average_cost_for_type(Type.t(), User.t()) :: float() | nil
|
||||
def get_average_cost_for_type(%Type{id: type_id} = type, user) do
|
||||
[type]
|
||||
|> get_average_cost_for_types(user)
|
||||
|> Map.get(type_id)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the average cost of ammo types from packs with price information
|
||||
for multiple ammo types.
|
||||
Gets the average cost of types from packs with price information
|
||||
for multiple types.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_average_cost_for_ammo_types(
|
||||
...> [%AmmoType{id: 123, user_id: 456}],
|
||||
iex> get_average_cost_for_types(
|
||||
...> [%Type{id: 123, user_id: 456}],
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
1.50
|
||||
|
||||
"""
|
||||
@spec get_average_cost_for_ammo_types([AmmoType.t()], User.t()) ::
|
||||
%{optional(AmmoType.id()) => float()}
|
||||
def get_average_cost_for_ammo_types(ammo_types, %User{id: user_id}) do
|
||||
ammo_type_ids =
|
||||
ammo_types
|
||||
|> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end)
|
||||
@spec get_average_cost_for_types([Type.t()], User.t()) ::
|
||||
%{optional(Type.id()) => float()}
|
||||
def get_average_cost_for_types(types, %User{id: user_id}) do
|
||||
type_ids =
|
||||
types
|
||||
|> Enum.map(fn %Type{id: type_id, user_id: ^user_id} -> type_id end)
|
||||
|
||||
sg_total_query =
|
||||
from sg in ShotRecord,
|
||||
@ -177,202 +177,200 @@ defmodule Cannery.Ammo do
|
||||
as: :pack,
|
||||
left_join: sg_query in subquery(sg_total_query),
|
||||
on: ag.id == sg_query.pack_id,
|
||||
where: ag.ammo_type_id in ^ammo_type_ids,
|
||||
group_by: ag.ammo_type_id,
|
||||
where: ag.type_id in ^type_ids,
|
||||
group_by: ag.type_id,
|
||||
where: not (ag.price_paid |> is_nil()),
|
||||
select:
|
||||
{ag.ammo_type_id, sum(ag.price_paid) / sum(ag.count + coalesce(sg_query.total, 0))}
|
||||
select: {ag.type_id, sum(ag.price_paid) / sum(ag.count + coalesce(sg_query.total, 0))}
|
||||
)
|
||||
|> Map.new()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the total number of rounds for an ammo type
|
||||
Gets the total number of rounds for a type
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_round_count_for_ammo_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
iex> get_round_count_for_type(
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
35
|
||||
|
||||
"""
|
||||
@spec get_round_count_for_ammo_type(AmmoType.t(), User.t()) :: non_neg_integer()
|
||||
def get_round_count_for_ammo_type(%AmmoType{id: ammo_type_id} = ammo_type, user) do
|
||||
[ammo_type]
|
||||
|> get_round_count_for_ammo_types(user)
|
||||
|> Map.get(ammo_type_id, 0)
|
||||
@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)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the total number of rounds for multiple ammo types
|
||||
Gets the total number of rounds for multiple types
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_round_count_for_ammo_types(
|
||||
...> [%AmmoType{id: 123, user_id: 456}],
|
||||
iex> get_round_count_for_types(
|
||||
...> [%Type{id: 123, user_id: 456}],
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
%{123 => 35}
|
||||
|
||||
"""
|
||||
@spec get_round_count_for_ammo_types([AmmoType.t()], User.t()) ::
|
||||
%{optional(AmmoType.id()) => non_neg_integer()}
|
||||
def get_round_count_for_ammo_types(ammo_types, %User{id: user_id}) do
|
||||
ammo_type_ids =
|
||||
ammo_types
|
||||
|> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end)
|
||||
@spec get_round_count_for_types([Type.t()], User.t()) ::
|
||||
%{optional(Type.id()) => non_neg_integer()}
|
||||
def get_round_count_for_types(types, %User{id: user_id}) do
|
||||
type_ids =
|
||||
types
|
||||
|> Enum.map(fn %Type{id: type_id, user_id: ^user_id} -> type_id end)
|
||||
|
||||
Repo.all(
|
||||
from ag in Pack,
|
||||
where: ag.ammo_type_id in ^ammo_type_ids,
|
||||
where: ag.type_id in ^type_ids,
|
||||
where: ag.user_id == ^user_id,
|
||||
group_by: ag.ammo_type_id,
|
||||
select: {ag.ammo_type_id, sum(ag.count)}
|
||||
group_by: ag.type_id,
|
||||
select: {ag.type_id, sum(ag.count)}
|
||||
)
|
||||
|> Map.new()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the total number of ammo ever bought for an ammo type
|
||||
Gets the total number of ammo ever bought for a type
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_historical_count_for_ammo_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
iex> get_historical_count_for_type(
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
5
|
||||
|
||||
"""
|
||||
@spec get_historical_count_for_ammo_type(AmmoType.t(), User.t()) :: non_neg_integer()
|
||||
def get_historical_count_for_ammo_type(%AmmoType{id: ammo_type_id} = ammo_type, user) do
|
||||
[ammo_type]
|
||||
|> get_historical_count_for_ammo_types(user)
|
||||
|> Map.get(ammo_type_id, 0)
|
||||
@spec get_historical_count_for_type(Type.t(), User.t()) :: non_neg_integer()
|
||||
def get_historical_count_for_type(%Type{id: type_id} = type, user) do
|
||||
[type]
|
||||
|> get_historical_count_for_types(user)
|
||||
|> Map.get(type_id, 0)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the total number of ammo ever bought for multiple ammo types
|
||||
Gets the total number of ammo ever bought for multiple types
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_historical_count_for_ammo_types(
|
||||
...> [%AmmoType{id: 123, user_id: 456}],
|
||||
iex> get_historical_count_for_types(
|
||||
...> [%Type{id: 123, user_id: 456}],
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
%{123 => 5}
|
||||
|
||||
"""
|
||||
@spec get_historical_count_for_ammo_types([AmmoType.t()], User.t()) ::
|
||||
%{optional(AmmoType.id()) => non_neg_integer()}
|
||||
def get_historical_count_for_ammo_types(ammo_types, %User{id: user_id} = user) do
|
||||
used_counts = ammo_types |> ActivityLog.get_used_count_for_ammo_types(user)
|
||||
round_counts = ammo_types |> get_round_count_for_ammo_types(user)
|
||||
@spec get_historical_count_for_types([Type.t()], User.t()) ::
|
||||
%{optional(Type.id()) => non_neg_integer()}
|
||||
def get_historical_count_for_types(types, %User{id: user_id} = user) do
|
||||
used_counts = types |> ActivityLog.get_used_count_for_types(user)
|
||||
round_counts = types |> get_round_count_for_types(user)
|
||||
|
||||
ammo_types
|
||||
|> Enum.filter(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} ->
|
||||
Map.has_key?(used_counts, ammo_type_id) or Map.has_key?(round_counts, ammo_type_id)
|
||||
types
|
||||
|> Enum.filter(fn %Type{id: type_id, user_id: ^user_id} ->
|
||||
Map.has_key?(used_counts, type_id) or Map.has_key?(round_counts, type_id)
|
||||
end)
|
||||
|> Map.new(fn %{id: ammo_type_id} ->
|
||||
historical_count =
|
||||
Map.get(used_counts, ammo_type_id, 0) + Map.get(round_counts, ammo_type_id, 0)
|
||||
|> Map.new(fn %{id: type_id} ->
|
||||
historical_count = Map.get(used_counts, type_id, 0) + Map.get(round_counts, type_id, 0)
|
||||
|
||||
{ammo_type_id, historical_count}
|
||||
{type_id, historical_count}
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a ammo_type.
|
||||
Creates a type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_ammo_type(%{field: value}, %User{id: 123})
|
||||
{:ok, %AmmoType{}}
|
||||
iex> create_type(%{field: value}, %User{id: 123})
|
||||
{:ok, %Type{}}
|
||||
|
||||
iex> create_ammo_type(%{field: bad_value}, %User{id: 123})
|
||||
iex> create_type(%{field: bad_value}, %User{id: 123})
|
||||
{:error, %Changeset{}}
|
||||
|
||||
"""
|
||||
@spec create_ammo_type(attrs :: map(), User.t()) ::
|
||||
{:ok, AmmoType.t()} | {:error, AmmoType.changeset()}
|
||||
def create_ammo_type(attrs \\ %{}, %User{} = user) do
|
||||
%AmmoType{}
|
||||
|> AmmoType.create_changeset(user, attrs)
|
||||
@spec create_type(attrs :: map(), User.t()) ::
|
||||
{:ok, Type.t()} | {:error, Type.changeset()}
|
||||
def create_type(attrs \\ %{}, %User{} = user) do
|
||||
%Type{}
|
||||
|> Type.create_changeset(user, attrs)
|
||||
|> Repo.insert()
|
||||
|> case do
|
||||
{:ok, ammo_type} -> {:ok, ammo_type |> preload_ammo_type()}
|
||||
{:ok, type} -> {:ok, type |> preload_type()}
|
||||
{:error, changeset} -> {:error, changeset}
|
||||
end
|
||||
end
|
||||
|
||||
@spec preload_ammo_type(AmmoType.t()) :: AmmoType.t()
|
||||
@spec preload_ammo_type([AmmoType.t()]) :: [AmmoType.t()]
|
||||
defp preload_ammo_type(ammo_type_or_ammo_types) do
|
||||
ammo_type_or_ammo_types |> Repo.preload(@ammo_type_preloads)
|
||||
@spec preload_type(Type.t()) :: Type.t()
|
||||
@spec preload_type([Type.t()]) :: [Type.t()]
|
||||
defp preload_type(type_or_types) do
|
||||
type_or_types |> Repo.preload(@type_preloads)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a ammo_type.
|
||||
Updates a type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_ammo_type(ammo_type, %{field: new_value}, %User{id: 123})
|
||||
{:ok, %AmmoType{}}
|
||||
iex> update_type(type, %{field: new_value}, %User{id: 123})
|
||||
{:ok, %Type{}}
|
||||
|
||||
iex> update_ammo_type(ammo_type, %{field: bad_value}, %User{id: 123})
|
||||
iex> update_type(type, %{field: bad_value}, %User{id: 123})
|
||||
{:error, %Changeset{}}
|
||||
|
||||
"""
|
||||
@spec update_ammo_type(AmmoType.t(), attrs :: map(), User.t()) ::
|
||||
{:ok, AmmoType.t()} | {:error, AmmoType.changeset()}
|
||||
def update_ammo_type(%AmmoType{user_id: user_id} = ammo_type, attrs, %User{id: user_id}) do
|
||||
ammo_type
|
||||
|> AmmoType.update_changeset(attrs)
|
||||
@spec update_type(Type.t(), attrs :: map(), User.t()) ::
|
||||
{:ok, Type.t()} | {:error, Type.changeset()}
|
||||
def update_type(%Type{user_id: user_id} = type, attrs, %User{id: user_id}) do
|
||||
type
|
||||
|> Type.update_changeset(attrs)
|
||||
|> Repo.update()
|
||||
|> case do
|
||||
{:ok, ammo_type} -> {:ok, ammo_type |> preload_ammo_type()}
|
||||
{:ok, type} -> {:ok, type |> preload_type()}
|
||||
{:error, changeset} -> {:error, changeset}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a ammo_type.
|
||||
Deletes a type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_ammo_type(ammo_type, %User{id: 123})
|
||||
{:ok, %AmmoType{}}
|
||||
iex> delete_type(type, %User{id: 123})
|
||||
{:ok, %Type{}}
|
||||
|
||||
iex> delete_ammo_type(ammo_type, %User{id: 123})
|
||||
iex> delete_type(type, %User{id: 123})
|
||||
{:error, %Changeset{}}
|
||||
|
||||
"""
|
||||
@spec delete_ammo_type(AmmoType.t(), User.t()) ::
|
||||
{:ok, AmmoType.t()} | {:error, AmmoType.changeset()}
|
||||
def delete_ammo_type(%AmmoType{user_id: user_id} = ammo_type, %User{id: user_id}) do
|
||||
ammo_type
|
||||
@spec delete_type(Type.t(), User.t()) ::
|
||||
{:ok, Type.t()} | {:error, Type.changeset()}
|
||||
def delete_type(%Type{user_id: user_id} = type, %User{id: user_id}) do
|
||||
type
|
||||
|> Repo.delete()
|
||||
|> case do
|
||||
{:ok, ammo_type} -> {:ok, ammo_type |> preload_ammo_type()}
|
||||
{:ok, type} -> {:ok, type |> preload_type()}
|
||||
{:error, changeset} -> {:error, changeset}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a ammo_type.
|
||||
Deletes a type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_ammo_type!(ammo_type, %User{id: 123})
|
||||
%AmmoType{}
|
||||
iex> delete_type!(type, %User{id: 123})
|
||||
%Type{}
|
||||
|
||||
"""
|
||||
@spec delete_ammo_type!(AmmoType.t(), User.t()) :: AmmoType.t()
|
||||
def delete_ammo_type!(ammo_type, user) do
|
||||
{:ok, ammo_type} = delete_ammo_type(ammo_type, user)
|
||||
ammo_type
|
||||
@spec delete_type!(Type.t(), User.t()) :: Type.t()
|
||||
def delete_type!(type, user) do
|
||||
{:ok, type} = delete_type(type, user)
|
||||
type
|
||||
end
|
||||
|
||||
@doc """
|
||||
@ -381,32 +379,32 @@ defmodule Cannery.Ammo do
|
||||
## Examples
|
||||
|
||||
iex> list_packs_for_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
[%Pack{}, ...]
|
||||
|
||||
iex> list_packs_for_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456},
|
||||
...> true
|
||||
...> )
|
||||
[%Pack{}, %Pack{}, ...]
|
||||
|
||||
"""
|
||||
@spec list_packs_for_type(AmmoType.t(), User.t()) :: [Pack.t()]
|
||||
@spec list_packs_for_type(AmmoType.t(), User.t(), show_used :: boolean()) ::
|
||||
@spec list_packs_for_type(Type.t(), User.t()) :: [Pack.t()]
|
||||
@spec list_packs_for_type(Type.t(), User.t(), show_used :: boolean()) ::
|
||||
[Pack.t()]
|
||||
def list_packs_for_type(ammo_type, user, show_used \\ false)
|
||||
def list_packs_for_type(type, user, show_used \\ false)
|
||||
|
||||
def list_packs_for_type(
|
||||
%AmmoType{id: ammo_type_id, user_id: user_id},
|
||||
%Type{id: type_id, user_id: user_id},
|
||||
%User{id: user_id},
|
||||
show_used
|
||||
) do
|
||||
from(ag in Pack,
|
||||
as: :ag,
|
||||
where: ag.ammo_type_id == ^ammo_type_id,
|
||||
where: ag.type_id == ^type_id,
|
||||
where: ag.user_id == ^user_id,
|
||||
preload: ^@pack_preloads
|
||||
)
|
||||
@ -443,7 +441,7 @@ defmodule Cannery.Ammo do
|
||||
"""
|
||||
@spec list_packs_for_container(
|
||||
Container.t(),
|
||||
AmmoType.t() | :all,
|
||||
Type.t() | :all,
|
||||
User.t()
|
||||
) :: [Pack.t()]
|
||||
def list_packs_for_container(
|
||||
@ -453,7 +451,7 @@ defmodule Cannery.Ammo do
|
||||
) do
|
||||
from(ag in Pack,
|
||||
as: :ag,
|
||||
join: at in assoc(ag, :ammo_type),
|
||||
join: at in assoc(ag, :type),
|
||||
as: :at,
|
||||
where: ag.container_id == ^container_id,
|
||||
where: ag.user_id == ^user_id,
|
||||
@ -464,7 +462,7 @@ defmodule Cannery.Ammo do
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@spec list_packs_for_container_filter_type(Queryable.t(), AmmoType.class() | :all) ::
|
||||
@spec list_packs_for_container_filter_type(Queryable.t(), Type.class() | :all) ::
|
||||
Queryable.t()
|
||||
defp list_packs_for_container_filter_type(query, :rifle),
|
||||
do: query |> where([at: at], at.class == :rifle)
|
||||
@ -509,71 +507,71 @@ defmodule Cannery.Ammo do
|
||||
defp get_packs_count_show_used(query, _true), do: query
|
||||
|
||||
@doc """
|
||||
Returns the count of packs for an ammo type.
|
||||
Returns the count of packs for a type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_packs_count_for_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
3
|
||||
|
||||
iex> get_packs_count_for_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456},
|
||||
...> true
|
||||
...> )
|
||||
5
|
||||
|
||||
"""
|
||||
@spec get_packs_count_for_type(AmmoType.t(), User.t()) :: non_neg_integer()
|
||||
@spec get_packs_count_for_type(AmmoType.t(), User.t(), show_used :: boolean()) ::
|
||||
@spec get_packs_count_for_type(Type.t(), User.t()) :: non_neg_integer()
|
||||
@spec get_packs_count_for_type(Type.t(), User.t(), show_used :: boolean()) ::
|
||||
non_neg_integer()
|
||||
def get_packs_count_for_type(
|
||||
%AmmoType{id: ammo_type_id} = ammo_type,
|
||||
%Type{id: type_id} = type,
|
||||
user,
|
||||
show_used \\ false
|
||||
) do
|
||||
[ammo_type]
|
||||
[type]
|
||||
|> get_packs_count_for_types(user, show_used)
|
||||
|> Map.get(ammo_type_id, 0)
|
||||
|> Map.get(type_id, 0)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the count of packs for multiple ammo types.
|
||||
Returns the count of packs for multiple types.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_packs_count_for_types(
|
||||
...> [%AmmoType{id: 123, user_id: 456}],
|
||||
...> [%Type{id: 123, user_id: 456}],
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
3
|
||||
|
||||
iex> get_packs_count_for_types(
|
||||
...> [%AmmoType{id: 123, user_id: 456}],
|
||||
...> [%Type{id: 123, user_id: 456}],
|
||||
...> %User{id: 456},
|
||||
...> true
|
||||
...> )
|
||||
5
|
||||
|
||||
"""
|
||||
@spec get_packs_count_for_types([AmmoType.t()], User.t()) ::
|
||||
%{optional(AmmoType.id()) => non_neg_integer()}
|
||||
@spec get_packs_count_for_types([AmmoType.t()], User.t(), show_used :: boolean()) ::
|
||||
%{optional(AmmoType.id()) => non_neg_integer()}
|
||||
def get_packs_count_for_types(ammo_types, %User{id: user_id}, show_used \\ false) do
|
||||
ammo_type_ids =
|
||||
ammo_types
|
||||
|> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end)
|
||||
@spec get_packs_count_for_types([Type.t()], User.t()) ::
|
||||
%{optional(Type.id()) => non_neg_integer()}
|
||||
@spec get_packs_count_for_types([Type.t()], User.t(), show_used :: boolean()) ::
|
||||
%{optional(Type.id()) => non_neg_integer()}
|
||||
def get_packs_count_for_types(types, %User{id: user_id}, show_used \\ false) do
|
||||
type_ids =
|
||||
types
|
||||
|> Enum.map(fn %Type{id: type_id, user_id: ^user_id} -> type_id end)
|
||||
|
||||
from(ag in Pack,
|
||||
as: :ag,
|
||||
where: ag.user_id == ^user_id,
|
||||
where: ag.ammo_type_id in ^ammo_type_ids,
|
||||
group_by: ag.ammo_type_id,
|
||||
select: {ag.ammo_type_id, count(ag.id)}
|
||||
where: ag.type_id in ^type_ids,
|
||||
group_by: ag.type_id,
|
||||
select: {ag.type_id, count(ag.id)}
|
||||
)
|
||||
|> get_packs_count_for_types_maybe_show_used(show_used)
|
||||
|> Repo.all()
|
||||
@ -589,50 +587,50 @@ defmodule Cannery.Ammo do
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the count of used packs for an ammo type.
|
||||
Returns the count of used packs for a type.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_used_packs_count_for_type(
|
||||
...> %AmmoType{id: 123, user_id: 456},
|
||||
...> %Type{id: 123, user_id: 456},
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
3
|
||||
|
||||
"""
|
||||
@spec get_used_packs_count_for_type(AmmoType.t(), User.t()) :: non_neg_integer()
|
||||
def get_used_packs_count_for_type(%AmmoType{id: ammo_type_id} = ammo_type, user) do
|
||||
[ammo_type]
|
||||
@spec get_used_packs_count_for_type(Type.t(), User.t()) :: non_neg_integer()
|
||||
def get_used_packs_count_for_type(%Type{id: type_id} = type, user) do
|
||||
[type]
|
||||
|> get_used_packs_count_for_types(user)
|
||||
|> Map.get(ammo_type_id, 0)
|
||||
|> Map.get(type_id, 0)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns the count of used packs for multiple ammo types.
|
||||
Returns the count of used packs for multiple types.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_used_packs_count_for_types(
|
||||
...> [%AmmoType{id: 123, user_id: 456}],
|
||||
...> [%Type{id: 123, user_id: 456}],
|
||||
...> %User{id: 456}
|
||||
...> )
|
||||
%{123 => 3}
|
||||
|
||||
"""
|
||||
@spec get_used_packs_count_for_types([AmmoType.t()], User.t()) ::
|
||||
%{optional(AmmoType.id()) => non_neg_integer()}
|
||||
def get_used_packs_count_for_types(ammo_types, %User{id: user_id}) do
|
||||
ammo_type_ids =
|
||||
ammo_types
|
||||
|> Enum.map(fn %AmmoType{id: ammo_type_id, user_id: ^user_id} -> ammo_type_id end)
|
||||
@spec get_used_packs_count_for_types([Type.t()], User.t()) ::
|
||||
%{optional(Type.id()) => non_neg_integer()}
|
||||
def get_used_packs_count_for_types(types, %User{id: user_id}) do
|
||||
type_ids =
|
||||
types
|
||||
|> Enum.map(fn %Type{id: type_id, user_id: ^user_id} -> type_id end)
|
||||
|
||||
Repo.all(
|
||||
from ag in Pack,
|
||||
where: ag.user_id == ^user_id,
|
||||
where: ag.ammo_type_id in ^ammo_type_ids,
|
||||
where: ag.type_id in ^type_ids,
|
||||
where: ag.count == 0,
|
||||
group_by: ag.ammo_type_id,
|
||||
select: {ag.ammo_type_id, count(ag.id)}
|
||||
group_by: ag.type_id,
|
||||
select: {ag.type_id, count(ag.id)}
|
||||
)
|
||||
|> Map.new()
|
||||
end
|
||||
@ -748,18 +746,18 @@ defmodule Cannery.Ammo do
|
||||
[%Pack{notes: "My cool pack"}, ...]
|
||||
|
||||
"""
|
||||
@spec list_packs(search :: String.t() | nil, AmmoType.class() | :all, User.t()) ::
|
||||
@spec list_packs(search :: String.t() | nil, Type.class() | :all, User.t()) ::
|
||||
[Pack.t()]
|
||||
@spec list_packs(
|
||||
search :: nil | String.t(),
|
||||
AmmoType.class() | :all,
|
||||
Type.class() | :all,
|
||||
User.t(),
|
||||
show_used :: boolean()
|
||||
) :: [Pack.t()]
|
||||
def list_packs(search, type, %{id: user_id}, show_used \\ false) do
|
||||
from(ag in Pack,
|
||||
as: :ag,
|
||||
join: at in assoc(ag, :ammo_type),
|
||||
join: at in assoc(ag, :type),
|
||||
as: :at,
|
||||
join: c in Container,
|
||||
on: ag.container_id == c.id,
|
||||
@ -781,7 +779,7 @@ defmodule Cannery.Ammo do
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@spec list_packs_filter_on_type(Queryable.t(), AmmoType.class() | :all) :: Queryable.t()
|
||||
@spec list_packs_filter_on_type(Queryable.t(), Type.class() | :all) :: Queryable.t()
|
||||
defp list_packs_filter_on_type(query, :rifle),
|
||||
do: query |> where([at: at], at.class == :rifle)
|
||||
|
||||
@ -1063,13 +1061,13 @@ defmodule Cannery.Ammo do
|
||||
end
|
||||
|
||||
defp do_create_packs(
|
||||
%{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs,
|
||||
%{"type_id" => type_id, "container_id" => container_id} = attrs,
|
||||
multiplier,
|
||||
user
|
||||
)
|
||||
when multiplier >= 1 and
|
||||
multiplier <= @pack_create_limit and
|
||||
ammo_type_id |> is_binary() and
|
||||
type_id |> is_binary() and
|
||||
container_id |> is_binary() do
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
|
||||
@ -1077,7 +1075,7 @@ defmodule Cannery.Ammo do
|
||||
Enum.map(1..multiplier, fn _count ->
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(
|
||||
get_ammo_type!(ammo_type_id, user),
|
||||
get_type!(type_id, user),
|
||||
Containers.get_container!(container_id, user),
|
||||
user,
|
||||
attrs
|
||||
@ -1107,15 +1105,15 @@ defmodule Cannery.Ammo do
|
||||
end
|
||||
|
||||
defp do_create_packs(
|
||||
%{"ammo_type_id" => ammo_type_id, "container_id" => container_id} = attrs,
|
||||
%{"type_id" => type_id, "container_id" => container_id} = attrs,
|
||||
_multiplier,
|
||||
user
|
||||
)
|
||||
when is_binary(ammo_type_id) and is_binary(container_id) do
|
||||
when is_binary(type_id) and is_binary(container_id) do
|
||||
changeset =
|
||||
%Pack{}
|
||||
|> Pack.create_changeset(
|
||||
get_ammo_type!(ammo_type_id, user),
|
||||
get_type!(type_id, user),
|
||||
Containers.get_container!(container_id, user),
|
||||
user,
|
||||
attrs
|
||||
|
@ -1,4 +1,4 @@
|
||||
defmodule Cannery.Ammo.AmmoType do
|
||||
defmodule Cannery.Ammo.Type do
|
||||
@moduledoc """
|
||||
An ammunition type.
|
||||
|
||||
@ -38,7 +38,7 @@ defmodule Cannery.Ammo.AmmoType do
|
||||
]}
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
schema "ammo_types" do
|
||||
schema "types" do
|
||||
field :name, :string
|
||||
field :desc, :string
|
||||
|
||||
@ -127,9 +127,9 @@ defmodule Cannery.Ammo.AmmoType do
|
||||
inserted_at: NaiveDateTime.t(),
|
||||
updated_at: NaiveDateTime.t()
|
||||
}
|
||||
@type new_ammo_type :: %__MODULE__{}
|
||||
@type new_type :: %__MODULE__{}
|
||||
@type id :: UUID.t()
|
||||
@type changeset :: Changeset.t(t() | new_ammo_type())
|
||||
@type changeset :: Changeset.t(t() | new_type())
|
||||
@type class :: :rifle | :shotgun | :pistol | nil
|
||||
|
||||
@spec changeset_fields() :: [atom()]
|
||||
@ -197,10 +197,10 @@ defmodule Cannery.Ammo.AmmoType do
|
||||
]
|
||||
|
||||
@doc false
|
||||
@spec create_changeset(new_ammo_type(), User.t(), attrs :: map()) :: changeset()
|
||||
def create_changeset(ammo_type, %User{id: user_id}, attrs) do
|
||||
@spec create_changeset(new_type(), User.t(), attrs :: map()) :: changeset()
|
||||
def create_changeset(type, %User{id: user_id}, attrs) do
|
||||
changeset =
|
||||
ammo_type
|
||||
type
|
||||
|> change(user_id: user_id)
|
||||
|> cast(attrs, changeset_fields())
|
||||
|
||||
@ -210,10 +210,10 @@ defmodule Cannery.Ammo.AmmoType do
|
||||
end
|
||||
|
||||
@doc false
|
||||
@spec update_changeset(t() | new_ammo_type(), attrs :: map()) :: changeset()
|
||||
def update_changeset(ammo_type, attrs) do
|
||||
@spec update_changeset(t() | new_type(), attrs :: map()) :: changeset()
|
||||
def update_changeset(type, attrs) do
|
||||
changeset =
|
||||
ammo_type
|
||||
type
|
||||
|> cast(attrs, changeset_fields())
|
||||
|
||||
string_fields()
|
||||
|
@ -9,7 +9,7 @@ defmodule Cannery.Ammo.Pack do
|
||||
use Ecto.Schema
|
||||
import CanneryWeb.Gettext
|
||||
import Ecto.Changeset
|
||||
alias Cannery.Ammo.AmmoType
|
||||
alias Cannery.Ammo.Type
|
||||
alias Cannery.{Accounts.User, Containers, Containers.Container}
|
||||
alias Ecto.{Changeset, UUID}
|
||||
|
||||
@ -20,7 +20,7 @@ defmodule Cannery.Ammo.Pack do
|
||||
:notes,
|
||||
:price_paid,
|
||||
:staged,
|
||||
:ammo_type_id,
|
||||
:type_id,
|
||||
:container_id
|
||||
]}
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@ -32,7 +32,7 @@ defmodule Cannery.Ammo.Pack do
|
||||
field :staged, :boolean, default: false
|
||||
field :purchased_on, :date
|
||||
|
||||
belongs_to :ammo_type, AmmoType
|
||||
belongs_to :type, Type
|
||||
field :container_id, :binary_id
|
||||
field :user_id, :binary_id
|
||||
|
||||
@ -46,8 +46,8 @@ defmodule Cannery.Ammo.Pack do
|
||||
price_paid: float() | nil,
|
||||
staged: boolean(),
|
||||
purchased_on: Date.t(),
|
||||
ammo_type: AmmoType.t() | nil,
|
||||
ammo_type_id: AmmoType.id(),
|
||||
type: Type.t() | nil,
|
||||
type_id: Type.id(),
|
||||
container_id: Container.id(),
|
||||
user_id: User.id(),
|
||||
inserted_at: NaiveDateTime.t(),
|
||||
@ -60,36 +60,36 @@ defmodule Cannery.Ammo.Pack do
|
||||
@doc false
|
||||
@spec create_changeset(
|
||||
new_pack(),
|
||||
AmmoType.t() | nil,
|
||||
Type.t() | nil,
|
||||
Container.t() | nil,
|
||||
User.t(),
|
||||
attrs :: map()
|
||||
) :: changeset()
|
||||
def create_changeset(
|
||||
pack,
|
||||
%AmmoType{id: ammo_type_id},
|
||||
%Type{id: type_id},
|
||||
%Container{id: container_id, user_id: user_id},
|
||||
%User{id: user_id},
|
||||
attrs
|
||||
)
|
||||
when is_binary(ammo_type_id) and is_binary(container_id) and is_binary(user_id) do
|
||||
when is_binary(type_id) and is_binary(container_id) and is_binary(user_id) do
|
||||
pack
|
||||
|> change(ammo_type_id: ammo_type_id)
|
||||
|> change(type_id: type_id)
|
||||
|> change(user_id: user_id)
|
||||
|> change(container_id: container_id)
|
||||
|> cast(attrs, [:count, :price_paid, :notes, :staged, :purchased_on])
|
||||
|> validate_number(:count, greater_than: 0)
|
||||
|> validate_required([:count, :staged, :purchased_on, :ammo_type_id, :container_id, :user_id])
|
||||
|> validate_required([:count, :staged, :purchased_on, :type_id, :container_id, :user_id])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Invalid changeset, used to prompt user to select ammo type and container
|
||||
Invalid changeset, used to prompt user to select type and container
|
||||
"""
|
||||
def create_changeset(pack, _invalid_ammo_type, _invalid_container, _invalid_user, attrs) do
|
||||
def create_changeset(pack, _invalid_type, _invalid_container, _invalid_user, attrs) do
|
||||
pack
|
||||
|> cast(attrs, [:ammo_type_id, :container_id])
|
||||
|> validate_required([:ammo_type_id, :container_id])
|
||||
|> add_error(:invalid, dgettext("errors", "Please select an ammo type and container"))
|
||||
|> cast(attrs, [:type_id, :container_id])
|
||||
|> validate_required([:type_id, :container_id])
|
||||
|> add_error(:invalid, dgettext("errors", "Please select a type and container"))
|
||||
end
|
||||
|
||||
@doc false
|
||||
|
Reference in New Issue
Block a user