defmodule Ami.CoursePeriod do use Ecto.Schema import Ecto.Query alias Ami.{ Course, Enrollment, Score, PackagePeriod, Repo, Community, User, CommunityUser } schema "course_periods" do field(:starts_on, :date) field(:ends_on, :date) field(:enrollment_end, :date) field(:created_at, :utc_datetime) field(:updated_at, :utc_datetime) field(:is_learning_lab, :boolean) field(:is_external, :boolean) field(:buddy_type, :integer) field(:manual_buddy_nomination, :boolean) field(:position, :integer) field(:one_for_all_email, :string, virtual: true) field(:community_title, :string, virtual: true) belongs_to(:course, Course) belongs_to(:package_period, PackagePeriod) belongs_to(:community, Community) belongs_to(:oneforall_buddy, User, foreign_key: :oneforall_id) has_many(:enrollments, Enrollment) has_many(:scores, Score) end def open_community_courses_for(user) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), join: com in assoc(cp, :community), join: cu in assoc(com, :community_users), where: c.on_air == true, where: cu.user_id == ^user.id, or_where: cu.user_id == ^user.id and cu.is_moderator == true, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.ends_on, asc: c.title], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) |> Enum.uniq_by(fn cp -> cp.course_id end) end def for_on_air_featured_courses do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: c.on_air == true, where: c.is_featured == true, order_by: [cp.ends_on, c.title], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) end def for_open_on_air_public_courses do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: c.on_air == true, where: is_nil(c.community_id), where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), where: is_nil(cp.community_id), preload: [course: {c, [:thumb_image_attachments, :instructors]}], order_by: [cp.ends_on, c.title] ) ) end def for_open_onair_universalpublic_community_courses do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), join: com in assoc(cp, :community), where: c.on_air == true, where: com.access_type in [0, 1], where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.ends_on, asc: c.title], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) |> Enum.uniq_by(fn cp -> cp.course_id end) end def for_learning_lab() do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: c.on_air == true, where: cp.is_learning_lab == true, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.ends_on, asc: c.title], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) end def is_active?(course_period) do Date.compare(course_period.starts_on, Date.utc_today()) in [:lt, :eq] && Date.compare(course_period.ends_on, Date.utc_today()) in [:gt, :eq] end def current_for(course) do Repo.all( from( cp in __MODULE__, where: cp.course_id == ^course.id, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.starts_on] ) ) |> List.first() end def currents_for(%Course{} = course) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: cp.course_id == ^course.id, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.starts_on], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) end def currents_for(%Community{} = community) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: cp.community_id == ^community.id, where: c.on_air == true, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.position, asc: c.title], preload: [:course] ) ) end def currents_for(%Community{} = community, %Course{} = course) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: c.on_air == true, where: cp.course_id == ^course.id, where: cp.community_id == ^community.id, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), order_by: [asc: cp.ends_on], preload: [:course] ) ) end @doc """ Return all open course periods for a given course depending on the passed user's status """ def currents_for(%Course{} = course, %User{} = user) do case user.status do 0 -> fetch_current_public_course_periods_for(course) |> Enum.concat(fetch_user_communities_current_cps_for(course, user)) 1 -> fetch_current_public_course_periods_for(course) |> Enum.concat(fetch_user_communities_current_cps_for(course, user)) 2 -> fetch_user_communities_current_cps_for(course, user) _ -> fetch_current_public_course_periods_for(course) end end @doc """ Return a List of all open/current public course periods for a given course """ def fetch_current_public_course_periods_for(%Course{} = course) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: cp.course_id == ^course.id, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), where: is_nil(cp.community_id), where: cp.is_learning_lab == false, where: is_nil(cp.package_period_id), order_by: [asc: cp.starts_on], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) end @doc """ Return a List of all open/current community course periods for passed course belonging to the communities the passed user belongs to, as member or moderator """ def fetch_user_communities_current_cps_for(%Course{} = course, %User{} = user) do query = from( cu in CommunityUser, where: cu.user_id == ^user.id, distinct: cu.community_id, select: cu.community_id ) # or Communities.Repo.all(query) but failing test, not sure how it impact performance though community_ids = Repo.all(query) Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: cp.course_id == ^course.id, where: cp.starts_on <= ^Date.utc_today() and cp.ends_on >= ^Date.utc_today(), where: cp.community_id in ^community_ids, order_by: [asc: cp.starts_on], preload: [course: {c, [:thumb_image_attachments, :instructors]}] ) ) end def automatic_buddy?(course_period), do: course_period.buddy_type == 1 def oneforall_buddy?(course_period), do: course_period.buddy_type == 2 def enrollments_count(course_period) do Repo.one( from( e in Enrollment, where: e.active == true, where: e.course_period_id == ^course_period.id, select: count(e.id) ) ) end def students_for(course_period) do Repo.all( from( e in Enrollment, where: e.active == true, where: e.course_period_id == ^course_period.id, join: u in assoc(e, :user), left_join: p in assoc(u, :profile), preload: [user: {u, profile: p}] ) ) end def students_for_matching(course_period, user_id, term) do from( u in User, where: u.id != ^user_id, join: e in assoc(u, :enrollments), left_join: p in assoc(u, :profile), where: e.active == true, where: e.course_period_id == ^course_period.id, where: ilike(u.name, ^"#{term}%") or ilike(p.first_name, ^"#{term}%") or ilike(p.last_name, ^"#{term}%"), preload: [profile: p], select: [:id, :name, profile: [:id, :first_name, :last_name]] ) |> Repo.all() end def public_cp_opening_today() do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), where: c.on_air == true, where: is_nil(c.community_id), where: cp.starts_on == ^Date.utc_today(), where: is_nil(cp.community_id), preload: [course: {c, [:thumb_image_attachments, :instructors]}], order_by: [cp.ends_on, c.title], distinct: cp.course_id ) ) end def community_cp_opening_today(user_id) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), join: com in assoc(cp, :community), join: cu in assoc(com, :community_users), where: cu.user_id == ^user_id, where: cp.starts_on == ^Date.utc_today(), preload: [course: c], order_by: [cp.ends_on, c.title], distinct: cp.course_id ) ) end def community_cp_opened_days_ago(user_id, count) do Repo.all( from( cp in __MODULE__, join: c in assoc(cp, :course), join: com in assoc(cp, :community), join: cu in assoc(com, :community_users), where: cu.user_id == ^user_id, where: cp.starts_on == ^Timex.shift(Date.utc_today(), days: -count), preload: [course: c], order_by: [cp.ends_on, c.title], distinct: cp.course_id ) ) end end