defmodule Ami.CourseSearch do defstruct id: 0, title: "", description: "", teaser_description: "", slug: "", rank: 0.0, introduction: "" @doc """ Search for open course periods matching given term accessible by given user Returns `{ :ok, %{courses: [course_period_struct], packages: [package_struct]} }` ## Examples iex> Ami.CourseSearch.search_for_user_with_term(user, "manage") {:ok, %courses: [%Ami.CoursePeriod{}], packages: [%Ami.Package{}]} """ def search_for_user_with_term(user, term) do course_periods = search(term) |> Enum.map(fn course -> Ami.CoursePeriod.currents_for(course, user) |> List.first() end) packages = if user.status in [0, 1], do: Ami.Package.on_air(), else: [] if length(course_periods) > 0 do {:ok, %{courses: course_periods, packages: packages}} else {:error, "no results found"} end end def search_for_user_with_term(term) do # course_periods = search(term) |> Enum.map(fn course -> Ami.CoursePeriod.currents_for(course) |> List.first() end) end def search_for_user_with_term_of_type(user, term, type) do course_periods = search(term) |> Enum.map(fn course -> Ami.CoursePeriod.currents_for(course, user) |> filter_by_type(type) |> List.first() end) packages = if user.status in [0, 1], do: Ami.Package.on_air(), else: [] if length(course_periods) > 0 do {:ok, %{courses: course_periods, packages: packages}} else {:error, "no results found"} end end def search_for_community_with_term(community, term) do # course_periods = search(term) |> Enum.map(fn course -> Ami.CoursePeriod.currents_for(community, course) |> List.first() end) |> Enum.filter(&(!is_nil(&1))) end def search(term) do Ecto.Adapters.SQL.query!(Ami.Repo, "SELECT * FROM course_search($1)", [term]) |> result_to_course_struct end # defp result_to_struct(res) do # cols = Enum.map(res.columns, &String.to_atom(&1)) # Enum.map(res.rows, fn row -> struct(__MODULE__, Enum.zip(cols, row)) end) # end defp result_to_course_struct(res) do cols = Enum.map(res.columns, &String.to_atom(&1)) Enum.map(res.rows, fn row -> struct(Ami.Course, Enum.zip(cols, row)) end) end defp filter_by_type(course_periods, type) do case type do "public" -> Enum.filter(course_periods, fn cp -> is_nil(cp.community_id) end) "community" -> Enum.filter(course_periods, fn cp -> !is_nil(cp.community_id) end) "learning_lab" -> Enum.filter(course_periods, fn cp -> cp.is_learning_lab == true end) nil -> course_periods end end end