Skip to content

Commit

Permalink
Merge branch 'master' into ghatighorias/qa_bug_fix_update_delete_warn…
Browse files Browse the repository at this point in the history
…ing_messege
  • Loading branch information
ggpasqualino committed Aug 9, 2017
2 parents eeb3fcc + a21224c commit d6770c6
Show file tree
Hide file tree
Showing 24 changed files with 895 additions and 429 deletions.
5 changes: 4 additions & 1 deletion lib/course_planner/permissions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ defimpl Canada.Can, for: CoursePlanner.User do
User,
}

def can?(%User{role: "Coordinator"}, action, TaskController)
when action in [:grab, :drop], do: false

def can?(%User{role: "Coordinator"}, _action, _controller), do: true

def can?(%User{role: "Teacher"}, _action, AttendanceController), do: true
Expand All @@ -22,7 +25,7 @@ defimpl Canada.Can, for: CoursePlanner.User do
when action in [:index, :show], do: true

def can?(%User{role: "Volunteer"}, action, TaskController)
when action in [:index, :show, :grab], do: true
when action in [:index, :show, :grab, :drop], do: true

def can?(_user, _action, CalendarController), do: true
def can?(_user, _action, DashboardController), do: true
Expand Down
105 changes: 59 additions & 46 deletions lib/course_planner/tasks.ex
Original file line number Diff line number Diff line change
@@ -1,105 +1,118 @@
defmodule CoursePlanner.Tasks do
@moduledoc false
alias CoursePlanner.Repo
alias CoursePlanner.Tasks.Task
alias Ecto.Changeset
alias CoursePlanner.{Repo, Volunteers, Tasks.Task}
import Ecto.Query, except: [update: 2]

def all do
Repo.all(Task)
end
def all_with_users, do: all() |> Repo.preload(:user)
def all_with_users, do: all() |> Repo.preload(:volunteers)

def get(id) do
case Repo.get(Task, id) do
nil -> {:error, :not_found}
task -> {:ok, Repo.preload(task, :user)}
task -> {:ok, Repo.preload(task, :volunteers)}
end
end

def new(%{"user_id" => "0"} = params), do: new(Map.delete(params, "user_id"))
def new(params) do
%Task{}
|> Task.changeset(params)
|> Repo.insert()
end

def update(id, %{"user_id" => "0"} = params), do: update(id, Map.delete(params, "user_id"))
def update(id, params) do
def delete(id) do
case get(id) do
{:ok, task} ->
task
|> Task.changeset(params)
|> Repo.update()
|> format_error(task)
error -> error
Repo.delete(task)
error -> error
end
end

defp format_error({:ok, task}, _), do: {:ok, task}
defp format_error({:error, changeset}, task), do: {:error, task, changeset}

def delete(id) do
def update(id, params) do
case get(id) do
{:ok, task} ->
Repo.delete(task)
volunteer_ids = Map.get(params, "volunteer_ids", [])

task
|> Repo.preload([:volunteers])
|> Task.changeset(params, :update)
|> update_changeset_volunteers(volunteer_ids)
|> Repo.update()
error -> error
end
end

def get_unassigned(sort_opt, now) do
def get_availables(sort_opt, id, now) do
sort_opt
|> task_query()
|> where([t], is_nil(t.user_id))
|> where([t], t.finish_time > ^now)
|> Repo.all()
|> Enum.reject(fn(task) ->
length(task.volunteers) >= task.max_volunteers or
Enum.any?(task.volunteers, &(&1.id == id))
end)
end

def get_past(sort_opt, id, now) do
sort_opt
|> task_query()
|> where([t], t.user_id == ^id)
|> where([t], t.finish_time < ^now)
|> Repo.all()
|> Enum.filter(fn(task) ->
Enum.any?(task.volunteers, &(&1.id == id))
end)
end

def get_for_user(sort_opt, id, now) do
sort_opt
|> task_query()
|> where([t], t.user_id == ^id)
|> where([t], t.finish_time > ^now)
|> Repo.all()
|> Enum.filter(fn(task) ->
Enum.any?(task.volunteers, &(&1.id == id))
end)
end

def task_query(sort_opt), do: Task |> sort(sort_opt) |> preload(:user)
def task_query(sort_opt) do
Task
|> sort(sort_opt)
|> join(:left, [t], v in assoc(t, :volunteers))
|> preload([t, v], [volunteers: v])
end

defp sort(query, nil), do: query
defp sort(query, "fresh"), do: order_by(query, [t], desc: t.updated_at)
defp sort(query, "closest"), do: order_by(query, [t], asc: t.finish_time)

def grab(task_id, user_id, now) do
with {:ok, task} <- get(task_id),
%{valid?: true} = changeset <- Task.changeset(task),
{:ok, changeset} <- validate_finish_time(changeset, now),
{:ok, changeset} <- validate_already_assigned(changeset, task)
do
changeset
|> Changeset.put_change(:user_id, user_id)
|> Repo.update()
def grab(task_id, volunteer_id) do
with {:ok, task} <- get(task_id),
new_volunteer = Volunteers.get!(volunteer_id)
do
updated_volunteer_list =
[new_volunteer | task.volunteers]
|> Enum.uniq()

task
|> Task.changeset()
|> Task.update_volunteer(updated_volunteer_list)
|> Repo.update()
else
error -> error
end
end

defp validate_finish_time(changeset, now) do
fin = Changeset.get_field(changeset, :finish_time)
case Timex.compare(fin, now) do
1 -> {:ok, changeset}
-1 -> {:error, :already_finished}
_ -> {:error, :unkown}
def drop(task_id, volunteer_id) do
with {:ok, task} <- get(task_id),
drop_volunteer = Volunteers.get!(volunteer_id)
do
updated_volunteer_list = List.delete(task.volunteers, drop_volunteer)

task
|> Task.changeset()
|> Task.drop_volunteer(updated_volunteer_list)
|> Repo.update()
else
error -> error
end
end

defp validate_already_assigned(changeset, %{user_id: nil}), do: {:ok, changeset}
defp validate_already_assigned(_changeset, _), do: {:error, :already_assigned}
def update_changeset_volunteers(changeset, volunteer_ids) do
volunteers = Repo.all(from v in Volunteers.query(), where: v.id in ^volunteer_ids)
Task.update_volunteer(changeset, volunteers)
end
end
15 changes: 14 additions & 1 deletion lib/course_planner/volunteers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ defmodule CoursePlanner.Volunteers do
@moduledoc false
import Ecto.Query
alias Ecto.Changeset
alias CoursePlanner.{Repo, User, Users}
alias CoursePlanner.{Repo, User, Users, Tasks.Task}

@volunteers from u in User, where: u.role == "Volunteer"

def all do
Repo.all(@volunteers)
end

def query do
@volunteers
end

def get!(id) do
Repo.get!(User, id)
end
Expand All @@ -32,6 +36,15 @@ defmodule CoursePlanner.Volunteers do
end
end

def get_tasks(volunteer) do
query = from t in Task,
join: v in assoc(t, :volunteers),
preload: [volunteers: v],
where: v.id == ^volunteer.id

Repo.all(query)
end

defp format_error({:ok, volunteer}, _), do: {:ok, volunteer}
defp format_error({:error, changeset}, volunteer), do: {:error, volunteer, changeset}

Expand Down
10 changes: 10 additions & 0 deletions priv/repo/migrations/20170719103736_add_max_volunteer_per_task.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defmodule CoursePlanner.Repo.Migrations.AddMaxVolunteerPerTask do
use Ecto.Migration

def change do
alter table(:tasks) do
remove :user_id
add :max_volunteers, :integer, null: false, default: 1
end
end
end
12 changes: 12 additions & 0 deletions priv/repo/migrations/20170719131431_create_users_tasks.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule CoursePlanner.Repo.Migrations.CreateUsersTasks do
use Ecto.Migration

def change do
create table(:tasks_users, primary_key: false) do
add :task_id, references(:tasks, on_delete: :delete_all), null: false
add :user_id, references(:users, on_delete: :delete_all), null: false
end
create index(:tasks_users, [:task_id])
create index(:tasks_users, [:user_id])
end
end
Loading

0 comments on commit d6770c6

Please sign in to comment.