Packages

Package containing all AMI Models shared between micro-services.

Retired package: Deprecated - faulty

Current section

Files

Jump to
ami_models lib ami user.ex
Raw

lib/ami/user.ex

defmodule Ami.User do
use Ecto.Schema
# use Bitwise
import Ecto.{
Query
}
alias Ami.{
Company,
Profile,
Course,
Enrollment,
Score,
CommunityUser,
TemplateResult,
Job,
Repo,
RecentActivity,
Role,
Comment,
Post,
DownloadedTool,
DownloadedResource,
Buddyship
}
schema "users" do
field(:name, :string)
field(:email, :string)
field(:encrypted_password, :string)
field(:reset_password_token, :string)
field(:reset_password_sent_at, :utc_datetime)
field(:remember_created_at, :utc_datetime)
field(:sign_in_count, :integer)
field(:current_sign_in_at, :utc_datetime)
field(:last_sign_in_at, :utc_datetime)
field(:current_sign_in_ip, :string)
field(:last_sign_in_ip, :string)
field(:confirmation_token, :string)
field(:confirmed_at, :utc_datetime)
field(:confirmation_sent_at, :utc_datetime)
field(:unconfirmed_email, :string)
field(:created_at, :utc_datetime)
field(:updated_at, :utc_datetime)
field(:admin, :boolean)
field(:invitation_token, :string)
field(:invitation_created_at, :utc_datetime)
field(:invitation_sent_at, :utc_datetime)
field(:invitation_accepted_at, :utc_datetime)
field(:invitation_limit, :integer)
field(:invited_by_id, :integer)
field(:invited_by_type, :string)
field(:invitations_count, :integer)
field(:status, :integer)
field(:accountibility_partner_for, :integer)
field(:roles_mask, :integer)
field(:renewable_date, :date)
field(:job_matching, :boolean)
field(:downloaded_tools_count, :integer)
field(:downloaded_resources_count, :integer)
field(:sign_in_streak, :integer)
field(:yalie_authtoken, :string)
field(:group_label, :string)
field(:is_dormant, :boolean)
field(:session_id, :string)
field(:uuid, :binary)
field(:jwt, :binary)
field(:is_verified, :boolean)
field(:api_user, :boolean)
belongs_to(:company, Company)
has_one(:administered_course, Course, foreign_key: :course_admin_id)
has_one(:profile, Profile)
has_many(:posts, Post, foreign_key: :author_id)
has_many(:comments, Comment)
has_many(:enrollments, Enrollment)
has_many(:course_periods, through: [:enrollments, :course_period])
has_many(:courses, through: [:course_periods, :course])
has_many(:scores, Score)
has_many(:community_users, CommunityUser)
has_many(:communities, through: [:community_users, :community])
has_many(:template_results, TemplateResult)
has_many(:recent_activities, RecentActivity, on_delete: :delete_all)
has_many(:downloaded_resources, DownloadedResource)
has_many(:downloaded_tools, DownloadedTool)
has_many(:assigned_buddyships, Buddyship, foreign_key: :buddy_id)
end
def membership_status(status) do
case status do
0 -> "Non-member"
1 -> "Member"
2 -> "Business member"
_ -> status
end
end
def get_nonmembers() do
__MODULE__ |> Ecto.Query.where(status: 0)
end
def get_nonmembers(query) do
query |> Ecto.Query.where(status: 0)
end
def get_members() do
__MODULE__ |> Ecto.Query.where(status: 1)
end
def get_members(query) do
query |> Ecto.Query.where(status: 1)
end
def get_business_members() do
__MODULE__ |> Ecto.Query.where(status: 2)
end
def get_business_members(query) do
query |> Ecto.Query.where(status: 2)
end
def or_get_members(query) do
query |> Ecto.Query.or_where(status: 1)
end
def or_get_business_members(query) do
query |> Ecto.Query.or_where(status: 2)
end
def awaken do
__MODULE__ |> Ecto.Query.where(is_dormant: false)
end
def awaken(query) do
query |> Ecto.Query.where(is_dormant: false)
end
def icoach_progress_for(user) do
progress =
%{pcentage: 0, completed_goals: nil}
|> has_started_self_assessment(user)
|> has_completed_self_assessment(user)
|> has_started_360(user)
|> has_completed_360(user)
|> calculate_progress_percentage
progress
end
def has_started_self_assessment(progress_map, user) do
count =
Repo.one(
from(
tp in TemplateResult,
where: tp.user_id == ^user.id,
where: is_nil(tp.owner_result_id),
select: count(tp.id)
)
)
cond do
count > 0 -> Map.put_new(progress_map, :started_self_assessment, true)
count == 0 -> Map.put_new(progress_map, :started_self_assessment, false)
end
end
def has_completed_self_assessment(progress_map, user) do
count =
Repo.one(
from(
tp in TemplateResult,
where: tp.user_id == ^user.id,
where: tp.status == 1,
where: is_nil(tp.owner_result_id),
select: count(tp.id)
)
)
cond do
count > 0 -> Map.put_new(progress_map, :completed_self_assessment, true)
count == 0 -> Map.put_new(progress_map, :completed_self_assessment, false)
end
end
def has_started_360(progress_map, user) do
started =
TemplateResult.get_done_self_assessments_for(user)
|> Enum.any?(fn e -> length(e.respondent_results) > 0 end)
Map.put_new(progress_map, :started_360, started)
end
def has_completed_360(progress_map, user) do
completed =
TemplateResult.get_done_self_assessments_for(user)
|> Enum.any?(fn e -> length(e.respondent_results) >= 3 end)
Map.put_new(progress_map, :completed_360, completed)
end
def calculate_progress_percentage(progress_map) do
progress_map =
if progress_map[:started_self_assessment],
do: Map.update!(progress_map, :pcentage, &(&1 + 15)),
else: progress_map
progress_map =
if progress_map[:completed_self_assessment],
do: Map.update!(progress_map, :pcentage, &(&1 + 15)),
else: progress_map
progress_map =
if progress_map[:started_360],
do: Map.update!(progress_map, :pcentage, &(&1 + 15)),
else: progress_map
progress_map =
if progress_map[:completed_360],
do: Map.update!(progress_map, :pcentage, &(&1 + 20)),
else: progress_map
progress_map
end
def preload_jobs(user_struct) do
if Ecto.assoc_loaded?(user_struct.profile) do
Repo.preload(
user_struct.profile,
jobs: from(j in Job, where: j.current == true, select: [:role])
).jobs
else
Repo.preload(
user_struct,
profile: [jobs: from(j in Job, where: j.current == true), select: [:role]]
).profile.jobs
end
end
def roles do
[
:admin,
:instructor,
:community_moderator,
:course_admin,
:learning_facilitator,
:buddy,
:accountibility_partner,
:respondent,
:system_admin
]
end
def can_access_admin_panel(user_struct) do
grants = MapSet.new([:admin, :community_moderator, :course_admin])
if user_struct.roles_mask != nil do
user_roles =
Role.roles_from_mask(user_struct.roles_mask)
|> Enum.into(MapSet.new())
common_items = MapSet.intersection(grants, user_roles)
if MapSet.size(common_items) > 0, do: true, else: false
else
false
end
end
def can_manage_user(user_struct) do
has_role?(user_struct, :admin)
end
def has_role?(user_struct, role) do
Role.has_role?(user_struct, role)
end
def user_name(user_struct) do
user = Repo.preload(user_struct, :profile)
cond do
!profile_blank?(user.profile) ->
user.profile.first_name
profile_blank?(user.profile) && !name_blank?(user) ->
user.name
true ->
hd(String.split(user.email, "@"))
end
end
def user_message_name(user_struct, term) do
user = Repo.preload(user_struct, :profile)
if Regex.match?(~r/\w+@[\w+.]+/i, term) do
term
else
cond do
!profile_blank?(user.profile) ->
"#{user.profile.first_name} #{user.profile.last_name}"
profile_blank?(user.profile) && !name_blank?(user) ->
user.name
true ->
hd(String.split(user.email, "@"))
end
end
end
def user_message_name(user_struct) do
user = Repo.preload(user_struct, :profile)
cond do
!profile_blank?(user.profile) ->
"#{user.profile.first_name} #{user.profile.last_name}"
profile_blank?(user.profile) && !name_blank?(user) ->
user.name
true ->
hd(String.split(user.email, "@"))
end
end
def user_tag_name(user_struct) do
user = Repo.preload(user_struct, :profile)
cond do
!profile_blank?(user.profile) ->
"#{String.replace(user.profile.first_name, " ", "")}#{
String.replace(user.profile.last_name, " ", "")
}"
profile_blank?(user.profile) && !name_blank?(user) ->
String.replace(user.name, " ", "")
true ->
hd(String.split(user.email, "@"))
end
end
defp profile_blank?(profile) do
is_nil(profile) || profile.first_name == "" || is_nil(profile.first_name)
end
defp name_blank?(user) do
is_nil(user.name) || user.name == ""
end
def potential_msg_recipients_for(user, term) do
enr_query =
from(
e in Ami.Enrollment,
join: cp in assoc(e, :course_period)
)
user = Repo.preload(user, [:communities, [enrollments: {enr_query, [:course_period]}]])
# usernames =
cond do
!Role.has_role?(user, :community_moderator) &&
(Role.has_role?(user, :admin) || Role.has_role?(user, :system_admin)) ->
profile_query =
from(
p in Ami.Profile,
select: [:first_name, :last_name]
)
query =
from(
u in __MODULE__,
left_join: p in assoc(u, :profile),
select: [:id, :email, :name],
where: u.email == ^term,
or_where: ilike(u.name, ^"#{term}%"),
or_where: ilike(p.first_name, ^"#{term}%"),
or_where: ilike(p.last_name, ^"#{term}%"),
preload: [profile: ^profile_query]
)
Repo.all(query)
|> Enum.map(fn user ->
%{label: __MODULE__.user_message_name(user, term), value: user.id}
end)
|> List.insert_at(0, %{label: "All non-members", value: "allnonmembers"})
|> List.insert_at(0, %{label: "All members", value: "allmembers"})
|> List.insert_at(0, %{label: "All business members", value: "allbusinessmembers"})
|> List.insert_at(0, %{label: "All users", value: "allusers"})
Role.has_role?(user, :community_moderator) &&
(!Role.has_role?(user, :admin) && !Role.has_role?(user, :system_admin)) ->
community_recipients =
Enum.flat_map(user.communities, fn community ->
Ami.Community.other_community_members(community, user)
end)
|> Enum.uniq()
course_recipients =
Enum.flat_map(user.enrollments, fn enrollment ->
Ami.Enrollment.other_cp_students(enrollment.course_period, user)
end)
|> Enum.uniq()
tmp_usernames =
Enum.concat(community_recipients, course_recipients)
|> Enum.uniq()
|> Enum.map(fn user ->
%{
label: __MODULE__.user_message_name(user, term),
value: user.id
}
end)
__MODULE__.moderated_communities(user)
|> Enum.map(fn community ->
%{
label: "All #{community.title} members",
value: "community_#{community.id}"
}
end)
|> Enum.into(tmp_usernames)
Role.has_role?(user, :community_moderator) &&
(Role.has_role?(user, :admin) || Role.has_role?(user, :system_admin)) ->
profile_query =
from(
p in Ami.Profile,
select: [:first_name, :last_name]
)
query =
from(
u in __MODULE__,
left_join: p in assoc(u, :profile),
select: [:id, :email, :name],
where: u.email == ^term,
or_where: ilike(u.name, ^"#{term}%"),
or_where: ilike(p.first_name, ^"#{term}%"),
or_where: ilike(p.last_name, ^"#{term}%"),
preload: [profile: ^profile_query]
)
tmp_usernames =
Repo.all(query)
|> Enum.map(fn user ->
%{label: __MODULE__.user_message_name(user, term), value: user.id}
end)
|> List.insert_at(0, %{label: "All non-members", value: "allnonmembers"})
|> List.insert_at(0, %{label: "All members", value: "allmembers"})
|> List.insert_at(0, %{label: "All business members", value: "allbusinessmembers"})
|> List.insert_at(0, %{label: "All users", value: "allusers"})
__MODULE__.moderated_communities(user)
|> Enum.map(fn community ->
%{label: "All #{community.title} members", value: "community_#{community.id}"}
end)
|> Enum.into(tmp_usernames)
true ->
community_recipients =
Enum.flat_map(user.communities, fn community ->
Ami.Community.other_community_members(community, user)
end)
|> Enum.uniq()
course_recipients =
Enum.flat_map(user.enrollments, fn enrollment ->
Ami.Enrollment.other_cp_students(enrollment.course_period, user)
end)
|> Enum.uniq()
Enum.concat(community_recipients, course_recipients)
|> Enum.uniq()
|> Enum.map(fn user ->
%{label: __MODULE__.user_message_name(user, term), value: user.id}
end)
end
end
def moderated_communities(user) do
from(
c in Ami.Community,
join: cu in assoc(c, :community_users),
where: cu.user_id == ^user.id,
where: cu.is_moderator == true
)
|> Repo.all()
end
def get_users_for_digest(type, frequency) do
case type do
:nonmember ->
get_users_with_digest_settings(0, frequency)
:member ->
get_users_with_digest_settings(1, frequency)
:business_member ->
get_users_with_digest_settings(2, frequency)
_ ->
[]
end
end
def get_users_for_long_absence_notice() do
Enum.map([4, 6, 8], fn weeks ->
q =
__MODULE__.awaken()
|> last_sign_in_at_since(weeks)
|> email_only()
Repo.all(q)
end)
|> List.flatten()
end
def last_sign_in_at_since(query, weeks) when is_integer(weeks) do
start_boundary =
Timex.now()
|> Timex.shift(weeks: -weeks)
|> Timex.beginning_of_day()
end_boundary =
Timex.now()
|> Timex.shift(weeks: -(weeks + 1))
|> Timex.beginning_of_day()
from(u in query,
where: u.last_sign_in_at <= ^start_boundary,
where: u.last_sign_in_at > ^end_boundary
)
end
def email_only(query) do
from(u in query, select: u.email)
end
defmacro has_attribute(field, key, value) do
quote do
fragment("?::hstore -> ? = ?", unquote(field), unquote(key), unquote(value))
end
end
def get_users_with_digest_settings(status, frequency) do
from(
u in __MODULE__,
join: p in assoc(u, :profile),
where: u.status == ^status,
where: u.is_dormant == false,
where: has_attribute(p.settings, "notify", ^frequency),
select: [:id, :email, :is_dormant, :status]
)
|> Repo.all()
end
end