defmodule Claper.Events do @moduledoc """ The Events context. """ import Ecto.Query, warn: false alias Claper.Repo alias Claper.Events.{Event, ActivityLeader} @doc """ Returns the list of events. ## Examples iex> list_events() [%Event{}, ...] """ def list_events(user_id, preload \\ []) do from(e in Event, where: e.user_id == ^user_id, order_by: [desc: e.expired_at]) |> Repo.all() |> Repo.preload(preload) end def list_managed_events_by(email, preload \\ []) do from(a in ActivityLeader, join: u in Claper.Accounts.User, on: u.email == a.email, join: e in Event, on: e.id == a.event_id, where: a.email == ^email, order_by: [desc: e.expired_at], select: e ) |> Repo.all() |> Repo.preload(preload) end def count_events_month(user_id) do # minus 30 days, calculated as seconds seconds = -30 * 24 * 3600 last_month = DateTime.utc_now() |> DateTime.add(seconds, :second) from(e in Event, where: e.user_id == ^user_id and e.inserted_at <= ^DateTime.utc_now() and e.inserted_at >= ^last_month, order_by: [desc: e.id] ) |> Repo.aggregate(:count, :id) end @doc """ Gets a single event. Raises `Ecto.NoResultsError` if the Event does not exist. ## Examples iex> get_event!(123) %Event{} iex> get_event!(456) ** (Ecto.NoResultsError) """ def get_event!(id, preload \\ []), do: Repo.get_by!(Event, uuid: id) |> Repo.preload(preload) def get_managed_event!(current_user, id, preload \\ []) do event = Repo.get_by!(Event, uuid: id) is_leader = Claper.Events.is_leaded_by(current_user.email, event) || event.user_id == current_user.id if is_leader do event |> Repo.preload(preload) else raise Ecto.NoResultsError end end def get_user_event!(user_id, id, preload \\ []), do: Repo.get_by!(Event, uuid: id, user_id: user_id) |> Repo.preload(preload) def get_event_with_code!(code, preload \\ []) do now = NaiveDateTime.utc_now() from(e in Event, where: e.code == ^code and e.expired_at > ^now) |> Repo.one!() |> Repo.preload(preload) end def get_event_with_code(code, preload \\ []) do now = DateTime.utc_now() from(e in Event, where: e.code == ^code and e.expired_at > ^now) |> Repo.one() |> Repo.preload(preload) end def get_different_event_with_code(nil, _event_id), do: nil def get_different_event_with_code(code, event_id) do now = DateTime.utc_now() from(e in Event, where: e.code == ^code and e.id != ^event_id and e.expired_at > ^now) |> Repo.one() end def is_leaded_by(email, event) do from(a in ActivityLeader, join: u in Claper.Accounts.User, on: u.email == a.email, join: e in Event, on: e.id == a.event_id, where: a.email == ^email and e.id == ^event.id, order_by: [desc: e.expired_at] ) |> Repo.exists?() end @doc """ Creates a event. ## Examples iex> create_event(%{field: value}) {:ok, %Event{}} iex> create_event(%{field: bad_value}) {:error, %Ecto.Changeset{}} """ def create_event(attrs) do %Event{} |> Event.create_changeset(attrs) |> validate_unique_event() |> case do {:ok, event} -> Repo.insert(event, returning: [:uuid]) {:error, changeset} -> {:error, %{changeset | action: :insert}} end end defp validate_unique_event(%Ecto.Changeset{changes: %{code: code} = _changes} = event) do case get_event_with_code(code) do %Event{} -> {:error, Ecto.Changeset.add_error(event, :code, "Already exists")} nil -> {:ok, event} end end defp validate_unique_event(%Ecto.Changeset{data: event} = changeset) do case get_different_event_with_code(event.code, event.id) do %Event{} -> {:error, Ecto.Changeset.add_error(changeset, :code, "Already exists")} nil -> {:ok, changeset} end end @doc """ Updates a event. ## Examples iex> update_event(event, %{field: new_value}) {:ok, %Event{}} iex> update_event(event, %{field: bad_value}) {:error, %Ecto.Changeset{}} """ def update_event(%Event{} = event, attrs) do event |> Event.update_changeset(attrs) |> validate_unique_event() |> case do {:ok, event} -> Repo.update(event, returning: [:uuid]) {:error, changeset} -> {:error, %{changeset | action: :update}} end end @doc """ Deletes a event. ## Examples iex> delete_event(event) {:ok, %Event{}} iex> delete_event(event) {:error, %Ecto.Changeset{}} """ def delete_event(%Event{} = event) do Repo.delete(event) end @doc """ Returns an `%Ecto.Changeset{}` for tracking event changes. ## Examples iex> change_event(event) %Ecto.Changeset{data: %Event{}} """ def change_event(%Event{} = event, attrs \\ %{}) do Event.changeset(event, attrs) end alias Claper.Events.ActivityLeader @doc """ Returns the list of activity_leaders. ## Examples iex> list_activity_leaders() [%ActivityLeader{}, ...] """ def list_activity_leaders do Repo.all(ActivityLeader) end @doc """ Gets a single activity_leader. Raises `Ecto.NoResultsError` if the Activity leader does not exist. ## Examples iex> get_activity_leader!(123) %ActivityLeader{} iex> get_activity_leader!(456) ** (Ecto.NoResultsError) """ def get_activity_leader!(id), do: Repo.get!(ActivityLeader, id) def get_activity_leaders_for_event(event_id) do from(a in ActivityLeader, left_join: u in Claper.Accounts.User, on: u.email == a.email, where: a.event_id == ^event_id, select: %{a | user_id: u.id} ) |> Repo.all() end @doc """ Returns an `%Ecto.Changeset{}` for tracking activity_leader changes. ## Examples iex> change_activity_leader(activity_leader) %Ecto.Changeset{data: %ActivityLeader{}} """ def change_activity_leader(%ActivityLeader{} = activity_leader, attrs \\ %{}) do ActivityLeader.changeset(activity_leader, attrs) end end