Skip to content

Commit

Permalink
Add inventory
Browse files Browse the repository at this point in the history
  • Loading branch information
feliciofilipe committed Jun 23, 2022
1 parent a95b13b commit 31bc612
Show file tree
Hide file tree
Showing 34 changed files with 1,259 additions and 71 deletions.
2 changes: 2 additions & 0 deletions lib/parzival/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Parzival.Accounts.User do
alias Parzival.Companies.Company
alias Parzival.Gamification.Curriculum
alias Parzival.Gamification.Mission
alias Parzival.Store.Item
alias Parzival.Store.Order
alias Parzival.Uploaders

Expand Down Expand Up @@ -62,6 +63,7 @@ defmodule Parzival.Accounts.User do
has_one :curriculum, Curriculum

has_many :orders, Order
has_many :inventory, Item

many_to_many :missions, Mission, join_through: "missions_users"

Expand Down
17 changes: 16 additions & 1 deletion lib/parzival/gamification.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule Parzival.Gamification do

alias Ecto.Multi

alias Parzival.Accounts
alias Parzival.Accounts.User
alias Parzival.Gamification.Curriculum
alias Parzival.Gamification.Curriculum.Education
Expand Down Expand Up @@ -786,7 +787,7 @@ defmodule Parzival.Gamification do

user
|> User.task_completion_changeset(%{
balance: user.balance + mission.tokens,
balance: user.balance + mission.tokens * get_tokens_multiplier(user),
exp: user.exp + mission.exp
})
|> repo.update()
Expand All @@ -807,6 +808,20 @@ defmodule Parzival.Gamification do
end
end

defp get_tokens_multiplier(%User{} = user) do

user = Accounts.load_user_fields(user, [inventory: [:boost]])

item = user.inventory
|> Enum.find_value(1.0,
fn item ->
if item.boost.type == :tokens && Timex.diff(DateTime.utc_now(), item.boost.expires_at, :minutes) <= 60 do
item.boost.multiplier
end
end)

end

def is_task_completed?(task_id, user_id) do
from(t in TaskUser, where: t.task_id == ^task_id and t.user_id == ^user_id)
|> Repo.exists?()
Expand Down
281 changes: 272 additions & 9 deletions lib/parzival/store.ex
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ defmodule Parzival.Store do
Order.changeset(order, attrs)
end

def purchase(user, product) do
def purchase_product(user, product) do
Multi.new()
|> Multi.update(
:update_balance,
Expand All @@ -265,34 +265,297 @@ defmodule Parzival.Store do
|> Repo.transaction()
|> case do
{:ok, transaction} ->
broadcast({:ok, transaction.update_stock}, :purchased)
broadcast({:ok, transaction.update_stock}, :product_purchased)

{:error, _transaction, changeset, _} ->
{:error, changeset}
end
end

def subscribe(topic) when topic in ["purchased", "updated", "deleted"] do
def subscribe(topic) when topic in ["product_purchased", "product_updated", "product_deleted"] do
Phoenix.PubSub.subscribe(Parzival.PubSub, topic)
end

defp broadcast({:error, _reason} = error, _event), do: error

defp broadcast({:ok, %Product{} = product}, event)
when event in [:purchased] do
Phoenix.PubSub.broadcast!(Parzival.PubSub, "purchased", {event, product.stock})
when event in [:product_purchased] do
Phoenix.PubSub.broadcast!(Parzival.PubSub, "product_purchased", {event, product.stock})
{:ok, product}
end

defp broadcast({:ok, %Product{} = product}, event)
when event in [:updated] do
Phoenix.PubSub.broadcast!(Parzival.PubSub, "updated", {event, product})
when event in [:product_updated] do
Phoenix.PubSub.broadcast!(Parzival.PubSub, "product_updated", {event, product})
{:ok, product}
end

defp broadcast({:ok, %Product{} = product}, event)
when event in [:deleted] do
Phoenix.PubSub.broadcast!(Parzival.PubSub, "deleted", {event, product})
when event in [:product_deleted] do
Phoenix.PubSub.broadcast!(Parzival.PubSub, "product_deleted", {event, product})
{:ok, product}
end

alias Parzival.Store.Boost

@doc """
Returns the list of boosts.
## Examples
iex> list_boosts()
[%Boost{}, ...]
"""
def list_boosts(params \\ %{})

def list_boosts(opts) when is_list(opts) do
Boost
|> apply_filters(opts)
|> Repo.all()
end

def list_boosts(flop) do
Flop.validate_and_run(Boost, flop, for: Boost)
end

def list_boosts(%{} = flop, opts) when is_list(opts) do
Boost
|> apply_filters(opts)
|> Flop.validate_and_run(flop, for: Boost)
end

@doc """
Gets a single boost.
Raises `Ecto.NoResultsError` if the Boost does not exist.
## Examples
iex> get_boost!(123)
%Boost{}
iex> get_boost!(456)
** (Ecto.NoResultsError)
"""
def get_boost!(id), do: Repo.get!(Boost, id)

@doc """
Creates a boost.
## Examples
iex> create_boost(%{field: value})
{:ok, %Boost{}}
iex> create_boost(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_boost(attrs \\ %{}) do
%Boost{}
|> Boost.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a boost.
## Examples
iex> update_boost(boost, %{field: new_value})
{:ok, %Boost{}}
iex> update_boost(boost, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_boost(%Boost{} = boost, attrs) do
boost
|> Boost.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a boost.
## Examples
iex> delete_boost(boost)
{:ok, %Boost{}}
iex> delete_boost(boost)
{:error, %Ecto.Changeset{}}
"""
def delete_boost(%Boost{} = boost) do
Repo.delete(boost)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking boost changes.
## Examples
iex> change_boost(boost)
%Ecto.Changeset{data: %Boost{}}
"""
def change_boost(%Boost{} = boost, attrs \\ %{}) do
Boost.changeset(boost, attrs)
end

alias Parzival.Store.Item

def purchase_boost(user, boost) do
Multi.new()
|> Multi.update(
:update_balance,
User.balance_changeset(user, %{balance: user.balance - boost.price})
)
|> Multi.insert(:insert, %Item{user_id: user.id, boost_id: boost.id})
|> Repo.transaction()
|> case do
{:ok, transaction} ->
{:ok, transaction}
# broadcast({:ok, transaction.update_stock}, :boost_purchased)

{:error, _transaction, changeset, _} ->
{:error, changeset}
end
end

# def subscribe(topic) when topic in ["product_purchased", "product_updated", "product_deleted"] do
# Phoenix.PubSub.subscribe(Parzival.PubSub, topic)
# end

# defp broadcast({:error, _reason} = error, _event), do: error

# defp broadcast({:ok, %Product{} = product}, event)
# when event in [:product_purchased] do
# Phoenix.PubSub.broadcast!(Parzival.PubSub, "product_purchased", {event, product.stock})
# {:ok, product}
# end

# defp broadcast({:ok, %Product{} = product}, event)
# when event in [:product_updated] do
# Phoenix.PubSub.broadcast!(Parzival.PubSub, "product_updated", {event, product})
# {:ok, product}
# end

# defp broadcast({:ok, %Product{} = product}, event)
# when event in [:product_deleted] do
# Phoenix.PubSub.broadcast!(Parzival.PubSub, "product_deleted", {event, product})
# {:ok, product}
# end


@doc """
Returns the list of items.
## Examples
iex> list_items()
[%Item{}, ...]
"""
def list_items(params \\ %{})

def list_items(opts) when is_list(opts) do
Item
|> apply_filters(opts)
|> Repo.all()
end

def list_items(flop) do
Flop.validate_and_run(Item, flop, for: Item)
end

def list_items(%{} = flop, opts) when is_list(opts) do
Item
|> apply_filters(opts)
|> Flop.validate_and_run(flop, for: Item)
end

@doc """
Gets a single item.
Raises `Ecto.NoResultsError` if the Item does not exist.
## Examples
iex> get_item!(123)
%Item{}
iex> get_item!(456)
** (Ecto.NoResultsError)
"""
def get_item!(id), do: Repo.get!(Item, id)

@doc """
Creates a item.
## Examples
iex> create_item(%{field: value})
{:ok, %Item{}}
iex> create_item(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_item(attrs \\ %{}) do
%Item{}
|> Item.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a item.
## Examples
iex> update_item(item, %{field: new_value})
{:ok, %Item{}}
iex> update_item(item, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_item(%Item{} = item, attrs) do
item
|> Item.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a item.
## Examples
iex> delete_item(item)
{:ok, %Item{}}
iex> delete_item(item)
{:error, %Ecto.Changeset{}}
"""
def delete_item(%Item{} = item) do
Repo.delete(item)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking item changes.
## Examples
iex> change_item(item)
%Ecto.Changeset{data: %Item{}}
"""
def change_item(%Item{} = item, attrs \\ %{}) do
Item.changeset(item, attrs)
end
end
Loading

0 comments on commit 31bc612

Please sign in to comment.