Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions lib/atlas/exchange.ex
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ defmodule Atlas.Exchange do
|> Repo.insert()
|> case do
{:ok, request} ->
enqueue_shift_exchange_solver_job()
{:ok, request}
execute_create_shift_exchange_request(request)

{:error, changeset} ->
{:error, changeset}
Expand All @@ -94,6 +93,32 @@ defmodule Atlas.Exchange do
end
end

defp execute_create_shift_exchange_request(request) do
# Try auto approve
case Repo.transaction(maybe_auto_approve_request(request)) do
{:ok, _changes} ->
# Reload student and shift for notification email
user = University.get_student!(request.student_id, preloads: [:user]).user
shift_to = Shifts.get_shift!(request.shift_to, preloads: [:course])

UserNotifier.deliver_shift_exchange_request_fulfilled(
user,
shift_to.course.name,
Shifts.Shift.short_name(shift_to)
)

{:ok, %{request | status: :approved}}

{:error, :shift_has_space, :no_space, _} ->
# Couldn't auto approve → enqueue solver
enqueue_shift_exchange_solver_job()
{:ok, request}

{:error, _step, _reason, _changes} ->
{:ok, request}
end
end

defp enqueue_shift_exchange_solver_job do
# Enqueue job to try to solve exchanges
Oban.insert(Workers.ShiftExchange.new(%{}))
Expand Down Expand Up @@ -366,4 +391,43 @@ defmodule Atlas.Exchange do
{:error, :transaction_failed}
end
end

defp maybe_auto_approve_request(%ShiftExchangeRequest{} = req) do
Multi.new()
|> Multi.run(:shift_has_space, fn _repo, _changes ->
enrolled_count =
Repo.one(
from(se in ShiftEnrollment,
where: se.shift_id == ^req.shift_to and se.status == :active,
select: count(se.id)
)
)

shift = Shifts.get_shift!(req.shift_to)

if enrolled_count < shift.capacity do
{:ok, :has_space}
else
{:error, :no_space}
end
end)
|> Multi.update(
:approve_request,
Ecto.Changeset.change(req, status: :approved)
)
|> Multi.delete_all(
:delete_from_enrollment,
from(se in ShiftEnrollment,
where: se.student_id == ^req.student_id and se.shift_id == ^req.shift_from
)
)
|> Multi.insert(
:insert_to_enrollment,
ShiftEnrollment.changeset(%ShiftEnrollment{}, %{
student_id: req.student_id,
shift_id: req.shift_to,
status: :active
})
)
end
end