Skip to content

Commit

Permalink
chore: improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
ruioliveira02 committed Feb 1, 2025
1 parent 4141ed0 commit 7f708b0
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 9 deletions.
57 changes: 55 additions & 2 deletions lib/safira/activities.ex
Original file line number Diff line number Diff line change
Expand Up @@ -422,12 +422,33 @@ defmodule Safira.Activities do
|> Repo.all()
end

@doc """
Returns the list of enrolments of an attendee.
## Examples
iex> get_attendee_enrolments(attendee_id)
[%Enrolment{}, ...]
"""
def get_attendee_enrolments(attendee_id) do
Enrolment
|> where([e], e.attendee_id == ^attendee_id)
|> preload(:activity)
|> Repo.all()
end

@doc """
Enrols an attendee in an activity
## Examples
iex> enrol(attendee_id, activity_id)
{:ok, %{enrolment: %Enrolment{}, activity: %Activity{}, new_activity: %Activity{}}}
iex> enrol(attendee_id, activity_id)
{:error, :struct, %Ecto.Changeset{}, %{}}
"""
def enrol(attendee_id, activity_id) do
Ecto.Multi.new()
# We need to read the activity before updating the enrolment count to avoid
Expand All @@ -450,10 +471,42 @@ defmodule Safira.Activities do
|> Repo.transaction()
end

def delete_enrolment(%Enrolment{} = enrolment) do
Repo.delete(enrolment)
@doc """
Deletes an enrolment
## Examples
iex> unenrol(attendee_id, activity_id)
{:ok, %{enrolment: %Enrolment{}, activity: %Activity{}, new_activity: %Activity{}}}
iex> unenrol(attendee_id, activity_id)
{:error, :struct, %Ecto.Changeset{}, %{}}
"""
def unenrol(enrolment) do
Ecto.Multi.new()
# We need to read the activity before updating the enrolment count to avoid
# a race condition where the enrolment count changes after the activity was last
# read from the database, and before this transaction began
|> Ecto.Multi.one(:activity, Activity |> where([a], a.id == ^enrolment.activity_id))
|> Ecto.Multi.delete(
:enrolment,
enrolment
)
|> Ecto.Multi.update(:new_activity, fn %{activity: act} ->
Activity.changeset(act, %{enrolment_count: act.enrolment_count - 1})
end)
|> Repo.transaction()
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking enrolment changes.
## Examples
iex> change_enrolment(enrolment)
%Ecto.Changeset{data: %Enrolment{}}
"""
def change_enrolment(%Enrolment{} = enrolment, attrs \\ %{}) do
Enrolment.changeset(enrolment, attrs)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/safira/activities/activity.ex
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ defmodule Safira.Activities.Activity do
|> validate_required(@required_fields)
|> validate_activity_date()
|> validate_activity_times()
|> check_constraint(:max_enrolments,
name: :activity_not_overbooked,
message: "Activity overbooked"
)
end

@doc false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule SafiraWeb.Backoffice.ScheduleLive.EnrolmentLive.FormComponent do
</div>
</.simple_form>
<% else %>
<div class="grid space-x-2 grid-cols-9 pl-1 mb-6">
<div class="grid space-x-2 grid-cols-9 pl-1 my-3">
<p class="col-span-8"><%= enrolment.attendee.user.name %></p>
<.link
phx-click={JS.push("delete-enrolment", value: %{id: id})}
Expand Down Expand Up @@ -89,8 +89,8 @@ defmodule SafiraWeb.Backoffice.ScheduleLive.EnrolmentLive.FormComponent do

{:ok,
socket
|> assign(assigns)
|> assign(:enrolments, enrolments)
|> assign(:activity, assigns.activity)
|> assign(:attendees, Accounts.list_attendees())}
end

Expand Down Expand Up @@ -157,7 +157,7 @@ defmodule SafiraWeb.Backoffice.ScheduleLive.EnrolmentLive.FormComponent do

# If the enrolment has an id, delete it from the database
if enrolment.id != nil do
Activities.delete_enrolment(enrolment)
Activities.unenrol(enrolment)
end

# Remove the enrolment from the list
Expand All @@ -181,8 +181,8 @@ defmodule SafiraWeb.Backoffice.ScheduleLive.EnrolmentLive.FormComponent do

if valid_enrolments do
# For each enrolment, update or create it
Enum.each(enrolments, fn {_, _, _enrolment, form} ->
Activities.enrol(form.params.attendee_id, form.params.activity_id)
Enum.each(enrolments, fn {_, new, _enrolment, form} ->
if new, do: Activities.enrol(form.params["attendee_id"], form.params["activity_id"])
end)

{:noreply,
Expand Down
21 changes: 19 additions & 2 deletions lib/safira_web/live/landing/components/schedule.ex
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ defmodule SafiraWeb.Landing.Components.Schedule do
>
<%= gettext("Enrol") %>
</p>
<p
:if={already_enrolled(@activity, @enrolments)}
class="relative -mr-3 font-iregular text-lg text-accent sm:mr-1"
phx-value-activity_id={@activity.id}
>
<%= gettext("Enrolled") %>
</p>
</div>
<!-- Expand -->
<button
Expand Down Expand Up @@ -389,11 +396,21 @@ defmodule SafiraWeb.Landing.Components.Schedule do
Activities.list_activity_categories()
end

defp already_enrolled(activity, enrolments) do
Enum.member?(Enum.map(enrolments, & &1.activity_id), activity.id)
end

defp enrolments_enabled(activity, user_role, enrolments) do
not_full = activity.max_enrolments > activity.enrolment_count
already_enrolled = Enum.member?(enrolments, activity)
is_staff = user_role == :staff

not_full and activity.has_enrolments and not already_enrolled and not is_staff
enrolled_at_same_time =
Enum.any?(enrolments, fn e ->
Time.compare(e.activity.time_start, activity.time_end) == :lt and
Time.compare(e.activity.time_end, activity.time_start) == :gt and
e.activity.date == activity.date
end)

not_full and activity.has_enrolments and not enrolled_at_same_time and not is_staff
end
end

0 comments on commit 7f708b0

Please sign in to comment.