Skip to content
Open
Show file tree
Hide file tree
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
61 changes: 61 additions & 0 deletions lib/atlas/university/degrees/courses/shifts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Atlas.University.Degrees.Courses.Shifts do
use Atlas.Context

alias Atlas.University.Degrees.Courses.Shifts.Shift
alias Ecto.Multi

@doc """
Returns the list of shifts.
Expand All @@ -21,6 +22,13 @@ defmodule Atlas.University.Degrees.Courses.Shifts do
|> Repo.all()
end

def list_shifts_with_timeslots(opts \\ []) do
Shift
|> apply_filters(opts)
|> Repo.all()
|> Repo.preload([:timeslots])
end

@doc """
Gets a single shift.

Expand All @@ -41,6 +49,13 @@ defmodule Atlas.University.Degrees.Courses.Shifts do
|> Repo.get!(id)
end

def get_shift_with_timeslots(id, opts \\ []) do
Shift
|> apply_filters(opts)
|> Repo.get(id)
|> Repo.preload([:timeslots])
end

@doc """
Creates a shift.

Expand Down Expand Up @@ -208,4 +223,50 @@ defmodule Atlas.University.Degrees.Courses.Shifts do
def change_timeslot(%Timeslot{} = timeslot, attrs \\ %{}) do
Timeslot.changeset(timeslot, attrs)
end

@doc """
Updates a shift that contains
"""

def update_shift_with_timeslots(shift, shift_attrs, timeslot_attrs) do
Multi.new()
|> Multi.update(:shift, change_shift(shift, shift_attrs))
|> process_timeslots(shift, timeslot_attrs)
|> Repo.transact()
end

defp process_timeslots(multi, shift, timeslot_attrs) do
multi
|> then(fn multi ->
timeslot_attrs
|> Enum.with_index()
|> Enum.reduce(multi, fn {timeslot_attr, index}, acc_multi ->
process_timeslot(acc_multi, timeslot_attr, shift.id, index)
end)
end)
end

defp process_timeslot(multi, timeslot_attr, shift_id, index) do
if timeslot_attr["id"] && timeslot_exists?(timeslot_attr["id"]) do
timeslot = get_timeslot!(timeslot_attr["id"])
changeset = change_timeslot(timeslot, Map.delete(timeslot_attr, "id"))
Multi.update(multi, {:timeslot, index}, changeset)
else
clean_attrs =
timeslot_attr
|> Map.delete("id")
|> Map.put("shift_id", shift_id)
|> Map.replace("weekday", timeslot_attr["weekday"] |> String.to_atom())

changeset = change_timeslot(%Timeslot{}, clean_attrs)
Multi.insert(multi, {:timeslot, index}, changeset)
end
end

defp timeslot_exists?(id) do
case Repo.get(Timeslot, id) do
nil -> false
_ -> true
end
end
end
55 changes: 55 additions & 0 deletions lib/atlas_web/controllers/shifts/shifts_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
defmodule AtlasWeb.ShiftsController do
use AtlasWeb, :controller

alias Atlas.Repo
alias Atlas.University.Degrees.Courses.Shifts

action_fallback AtlasWeb.FallbackController

def index(conn, attrs) do
{user, _} = Guardian.Plug.current_resource(conn)

if user_has_elevated_privileges?(user) do
shifts = Shifts.list_shifts_with_timeslots(attrs)

conn
|> put_view(AtlasWeb.University.ShiftJSON)
|> render(:index, shifts: shifts)
else
conn
|> put_status(:forbidden)
|> json(%{error: "Unauthorized"})
end
end

def update(conn, %{"id" => id} = attrs) do
{user, _} = Guardian.Plug.current_resource(conn)

if user_has_elevated_privileges?(user) do
shift = Shifts.get_shift_with_timeslots(id)
timeslot_attrs = Map.get(attrs, "timeslots", [])
shift_attrs = Map.delete(attrs, "timeslots")

case Shifts.update_shift_with_timeslots(shift, shift_attrs, timeslot_attrs) do
{:ok, %{shift: updated_shift} = _results} ->
conn
|> put_view(AtlasWeb.University.ShiftJSON)
|> render(:show, shift: updated_shift |> Repo.preload([:timeslots]))

{:error, _operation, changeset, _changeset} ->
conn
|> put_status(:unprocessable_entity)
|> put_view(json: AtlasWeb.ChangesetJSON)
|> render(:error, changeset: changeset)
end
else
conn
|> put_status(:forbidden)
|> json(%{error: "Unauthorized"})
end
end

defp user_has_elevated_privileges?(user) do
(user && user.type == :admin) || user.type == :professor
end
end
14 changes: 14 additions & 0 deletions lib/atlas_web/controllers/timeslots_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule AtlasWeb.TimeslotsController do
use AtlasWeb, :controller

alias Atlas.University.Degrees.Courses.Shifts
alias Atlas.University.Degrees.Courses.Shifts.Timeslot

def delete(conn, %{"id" => id}) do
timeslot = Shifts.get_timeslot!(id)

with {:ok, %Timeslot{}} <- Shifts.delete_timeslot(timeslot) do
send_resp(conn, :no_content, "")
end
end
end
17 changes: 16 additions & 1 deletion lib/atlas_web/controllers/university/shift_json.ex
Comment thread
enricoprazeres marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ defmodule AtlasWeb.University.ShiftJSON do
alias Atlas.University.Degrees.Courses.Shifts.Shift
alias AtlasWeb.University.TimeslotJSON

def index(%{shifts: shifts}) do
%{data: for(shift <- shifts, do: data(shift))}
end

def show(%{shift: shift}) do
%{data: data(shift)}
end

def data(%Shift{} = shift) do
%{
id: shift.id,
number: shift.number,
type: shift.type,
professor: shift.professor,
timeslots: for(timeslot <- shift.timeslots, do: TimeslotJSON.data(timeslot)),
timeslots:
if Ecto.assoc_loaded?(shift.timeslots) do
for timeslot <- shift.timeslots, do: TimeslotJSON.data(timeslot)
else
[]
end,
enrollment_status:
if Ecto.assoc_loaded?(shift.enrollments) && shift.enrollments != [] do
hd(shift.enrollments).status
else
nil
end
}
end
Expand Down
9 changes: 9 additions & 0 deletions lib/atlas_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,15 @@ defmodule AtlasWeb.Router do

get "/students", University.StudentsController, :index

scope "/shifts" do
get "/", ShiftsController, :index
put "/:id", ShiftsController, :update

scope "/timeslots" do
delete "/:id", TimeslotsController, :delete
end
end

scope "/jobs" do
get "/", JobController, :index
get "/:id", JobController, :show
Expand Down