defmodule Ami.Community do use Ecto.Schema import Ecto.{ Query } alias Ami.{ CoursePeriod, User, CommunityUser, CommunityTool, CommunityToolkit, Tool, Toolkit, RelatedLink, Image, Post, Repo, RecentActivity } schema "communities" do field(:title, :string) field(:description, :string) field(:status, :integer) field(:access_type, :integer) field(:is_dormant, :boolean) field(:created_at, :utc_datetime) field(:updated_at, :utc_datetime) field(:members_count, :integer, virtual: true, default: 0) field(:mine, :boolean, virtual: true, default: false) belongs_to(:user, User) has_many(:course_periods, CoursePeriod) has_many(:community_users, CommunityUser) has_many(:users, through: [:community_users, :user]) has_many(:community_tools, CommunityTool) has_many(:tools, through: [:community_tools, :tool]) has_many(:community_toolkits, CommunityToolkit) has_many(:toolkits, through: [:community_toolkits, :toolkit]) has_many(:direct_tools, Tool, foreign_key: :community_id) has_many(:direct_toolkits, Toolkit, foreign_key: :community_id) has_many(:posts, Post) has_many(:related_links, RelatedLink) has_many(:recent_activities, RecentActivity) has_one(:logo, Image, foreign_key: :imageable_id) end def community_moderators(community) do query = from(cu in CommunityUser, where: cu.is_moderator == true, preload: [user: :profile]) community = Repo.preload(community, community_users: query) Enum.map(community.community_users, fn cu -> cu.user end) |> Enum.reject(&is_nil(&1)) end def community_members(community) do query = community_members_query(community) Repo.all(query) end def community_members(community, limit_query) do query = community_members_query(community) |> Ecto.Query.limit(^limit_query) Repo.all(query) end def community_members_count(community) do from( u in User, join: cu in assoc(u, :community_users), where: cu.is_moderator == false, where: cu.community_id == ^community.id ) |> Ecto.Query.select(count("*")) |> Repo.one() end defp community_members_query(community) do from( u in User, join: cu in assoc(u, :community_users), left_join: pr in assoc(u, :profile), where: cu.is_moderator == false, where: cu.community_id == ^community.id, preload: [profile: pr], select: [:id, :email, :name, :uuid, profile: [:id, :first_name, :last_name, :image]] ) end defp other_community_members_query(community, user_id) do from( u in User, join: cu in assoc(u, :community_users), left_join: pr in assoc(u, :profile), where: u.id != ^user_id, where: cu.is_moderator == false, where: cu.community_id == ^community.id, preload: [profile: pr], select: [:id, :email, :name, :uuid, profile: [:id, :first_name, :last_name, :image]] ) end def other_community_members(community, user) do query = other_community_members_query(community, user.id) Repo.all(query) end def other_community_members_matching(community, user_id, term) do from( u in User, join: cu in assoc(u, :community_users), left_join: pr in assoc(u, :profile), where: u.id != ^user_id, where: cu.is_moderator == false, where: cu.community_id == ^community.id, where: ilike(u.name, ^"#{term}%"), or_where: ilike(pr.first_name, ^"#{term}%"), or_where: ilike(pr.last_name, ^"#{term}%"), preload: [profile: pr], select: [:id, :name, profile: [:id, :first_name, :last_name]] ) |> Repo.all() end def stringify_access_type(access_type) do case access_type do 0 -> "Universal" 1 -> "Public" 2 -> "Member" 3 -> "Protected" 4 -> "Private" end end def get_awaken_communities_for(user) do Repo.all( from( c in __MODULE__, join: cu in assoc(c, :community_users), where: cu.user_id == ^user.id, where: c.is_dormant == false, where: cu.status == 1, order_by: [asc: c.title] ) ) end def awaken, do: __MODULE__ |> Ecto.Query.where(is_dormant: false) def awaken(query) do query |> Ecto.Query.where(is_dormant: false) end def fetch_universal, do: __MODULE__ |> Ecto.Query.where(access_type: 0) def fetch_universal(query) do query |> Ecto.Query.where(access_type: 0) end def or_fetch_universal, do: __MODULE__ |> Ecto.Query.or_where(access_type: 0) def or_fetch_universal(query) do query |> Ecto.Query.or_where(access_type: 0) end def fetch_public, do: __MODULE__ |> Ecto.Query.where(access_type: 1) def fetch_public(query) do query |> Ecto.Query.where(access_type: 1) end def or_fetch_public, do: __MODULE__ |> Ecto.Query.or_where(access_type: 1) def or_fetch_public(query) do query |> Ecto.Query.or_where(access_type: 1) end def fetch_protected, do: __MODULE__ |> Ecto.Query.where(access_type: 3) def fetch_protected(query) do query |> Ecto.Query.where(access_type: 3) end def or_fetch_protected, do: __MODULE__ |> Ecto.Query.or_where(access_type: 3) def or_fetch_protected(query) do query |> Ecto.Query.or_where(access_type: 3) end def fetch_member, do: __MODULE__ |> Ecto.Query.where(access_type: 2) def fetch_member(query) do query |> Ecto.Query.where(access_type: 2) end def or_fetch_member, do: __MODULE__ |> Ecto.Query.or_where(access_type: 2) def or_fetch_member(query) do query |> Ecto.Query.or_where(access_type: 2) end def preload_logo(struct), do: Image.preload_image(struct, "Community") def public_or_universal?(community) do community.access_type == 0 || community.access_type == 1 end def universal_or_public_or_protected?(community) do community.access_type == 0 || community.access_type == 1 || community.access_type == 3 end def fetch_members_count(community) do count = length(Repo.preload(community, :users).users) %__MODULE__{community | members_count: count} end def fetch_awaken_universal_public_protected do or_fetch_universal() |> or_fetch_public() |> or_fetch_protected() |> awaken() |> Repo.all() end def fetch_awaken_universal_public do or_fetch_universal() |> or_fetch_public() |> awaken() |> Repo.all() end def fetch_all_for_user_with_tool(user, tool) do query = from( c in __MODULE__, join: cu in assoc(c, :community_users), where: cu.user_id == ^user.id ) # _communities = Repo.all( from(c in query, join: dt in assoc(c, :direct_tools), where: dt.id == ^tool.id ) ) |> Enum.concat( Repo.all( from(c in query, join: dtk in assoc(c, :direct_toolkits), join: dtk_t in assoc(dtk, :tools), where: dtk_t.id == ^tool.id ) ) ) |> Enum.concat( Repo.all( from(c in query, join: ctk in assoc(c, :community_toolkits), join: tk in assoc(ctk, :toolkit), join: tkt in assoc(tk, :tools), where: tkt.id == ^tool.id ) ) ) |> Enum.concat( Repo.all( from(c in query, join: ct in assoc(c, :community_tools), where: ct.tool_id == ^tool.id ) ) ) |> Enum.uniq() |> Enum.map(& &1.id) end end