Skip to content

Commit

Permalink
feat: badge redeems
Browse files Browse the repository at this point in the history
  • Loading branch information
ruioliveira02 committed Jan 10, 2025
1 parent 7756e0f commit f3be358
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 1 deletion.
62 changes: 61 additions & 1 deletion lib/safira/contest.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Safira.Contest do

alias Ecto.Multi
alias Safira.Accounts.Attendee
alias Safira.Contest.{Badge, BadgeCategory, BadgeCondition, DailyTokens}
alias Safira.Contest.{Badge, BadgeCategory, BadgeCondition, BadgeRedeem, DailyTokens}

@doc """
Gets a single badge.
Expand Down Expand Up @@ -309,6 +309,31 @@ defmodule Safira.Contest do
BadgeCondition.changeset(condition, attrs)
end

def list_badge_redeems do
BadgeRedeem
|> Repo.all()
end

def create_badge_redeem(attrs) do
%BadgeRedeem{}
|> BadgeRedeem.changeset(attrs)
|> Repo.insert()
end

def update_badge_redeem(badge_redeem, attrs) do
badge_redeem
|> BadgeRedeem.changeset(attrs)
|> Repo.update()
end

def delete_badge_redeem(badge_redeem) do
Repo.delete(badge_redeem)
end

def change_badge_redeem(badge_redeem, attrs \\ %{}) do
BadgeRedeem.changeset(badge_redeem, attrs)
end

@doc """
Changes the attendee token balance and updates the daily tokens.
"""
Expand All @@ -317,6 +342,41 @@ defmodule Safira.Contest do
|> Repo.transaction()
end

def redeem_badge(badge, attendee, staff) do
if staff_can_redeem?(badge, staff) do
redeem_badge_transaction(badge, attendee, staff)
|> Repo.transaction()
else
{:error, reason: "Staff not authorized"}
end
end

defp staff_can_redeem?(badge, staff) do
is_admin = Enum.member?(Map.get(staff.role.permissions, "badge"), "give_without_restrictions")
has_permission = Enum.member?(Map.get(staff.role.permissions, "badge"), "give")

on_time =
DateTime.compare(DateTime.utc_now(), badge.start) != :lt and
DateTime.compare(DateTime.utc_now(), badge.end)

is_admin or (has_permission and on_time)
end

def redeem_badge_transaction(badge, attendee, staff) do
Multi.new()
|> Multi.insert(
:redeem,
BadgeRedeem.changeset(%BadgeRedeem{}, %{
badge_id: badge.id,
attendee_id: attendee.id,
redeemed_by_id: staff.id
})
)
|> Multi.merge(fn %{redeem: _redeem} ->
change_attendee_tokens_transaction(attendee, attendee.tokens + badge.tokens)
end)
end

@doc """
Transaction for updating the attendee token balance and the daily tokens.
"""
Expand Down
1 change: 1 addition & 0 deletions lib/safira/contest/badge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule Safira.Contest.Badge do
field :tokens, :integer
field :begin, :utc_datetime
field :end, :utc_datetime
# TODO: Filter redeems
field :counts_for_day, :boolean, default: true

belongs_to :category, Safira.Contest.BadgeCategory
Expand Down
30 changes: 30 additions & 0 deletions lib/safira/contest/badge_redeem.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule Safira.Contest.BadgeRedeem do
@moduledoc """
Event badge redeem.
"""

use Safira.Schema

alias Safira.Accounts.{Attendee, Staff}
alias Safira.Contest.Badge

@required_fields ~w(badge_id attendee_id)a
@optional_fields ~w(redeemed_by_id)a

schema "badge_redeems" do
belongs_to :badge, Badge

belongs_to :attendee, Attendee
belongs_to :redeemed_by, Staff

timestamps(type: :utc_datetime)
end

@doc false
def changeset(badge_redeem, attrs) do
badge_redeem
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> unique_constraint([:badge_id, :attendee_id])
end
end
20 changes: 20 additions & 0 deletions priv/repo/migrations/20250110121135_add_badge_redeems.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
defmodule Safira.Repo.Migrations.AddBadgeRedeems do
use Ecto.Migration

def change do
create table(:badge_redeems, primary_key: false) do
add :id, :binary_id, primary_key: true

add :badge_id, references(:badges, on_delete: :nothing, type: :binary_id), null: false
add :attendee_id, references(:attendees, on_delete: :delete_all, type: :binary_id), null: false
add :redeemed_by_id, references(:staffs, on_delete: :nilify_all, type: :binary_id), null: true

timestamps()
end

create unique_index(:badge_redeems, [:attendee_id, :badge_id])
create index(:badge_redeems, [:attendee_id])
create index(:badge_redeems, [:badge_id])
end

end

0 comments on commit f3be358

Please sign in to comment.