Skip to content

Commit 68cf651

Browse files
committed
refactor: enhance job listing and filtering functionality
- Introduced new ordering and preloading mechanisms in the job listing and counting functions. - Added support for filtering by user handles and improved the user filtering logic. - Created a new migration for the job_interviews table and updated the JobPosting schema to include a relationship with interviews.
1 parent cf268f6 commit 68cf651

File tree

3 files changed

+70
-6
lines changed

3 files changed

+70
-6
lines changed

lib/algora/jobs/jobs.ex

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,22 @@ defmodule Algora.Jobs do
1717

1818
def list_jobs(opts \\ []) do
1919
JobPosting
20-
|> order_by([j], desc: j.inserted_at)
21-
|> maybe_filter_by_user(opts[:user_id])
20+
|> apply_ordering(opts)
21+
|> maybe_filter_by_user(opts)
22+
|> join(:inner, [j], u in User, on: u.id == j.user_id)
23+
|> maybe_filter_by_users(opts[:handles])
2224
|> maybe_filter_by_tech_stack(opts[:tech_stack])
2325
|> maybe_limit(opts[:limit])
2426
|> Repo.all()
25-
|> Repo.preload(:user)
27+
|> apply_preloads(opts)
2628
end
2729

2830
def count_jobs(opts \\ []) do
2931
JobPosting
3032
|> order_by([j], desc: j.inserted_at)
31-
|> maybe_filter_by_user(opts[:user_id])
33+
|> maybe_filter_by_user(opts)
34+
|> join(:inner, [j], u in User, on: u.id == j.user_id)
35+
|> maybe_filter_by_users(opts[:handles])
3236
|> maybe_filter_by_tech_stack(opts[:tech_stack])
3337
|> Repo.aggregate(:count)
3438
end
@@ -39,12 +43,30 @@ defmodule Algora.Jobs do
3943
|> Repo.insert()
4044
end
4145

42-
defp maybe_filter_by_user(query, nil), do: where(query, [j], j.status in [:active])
46+
defp maybe_filter_by_user(query, user_id: user_id, handles: handles) when is_nil(user_id) and is_nil(handles) do
47+
where(query, [j, u], j.status in [:active])
48+
end
4349

44-
defp maybe_filter_by_user(query, user_id) do
50+
defp maybe_filter_by_user(query, user_id: user_id) do
4551
where(query, [j], j.user_id == ^user_id and j.status in [:active, :processing])
4652
end
4753

54+
defp maybe_filter_by_user(query, _), do: query
55+
56+
defp maybe_filter_by_users(query, nil), do: query
57+
58+
defp maybe_filter_by_users(query, handles) do
59+
# Need to handle different query structures based on joins
60+
case query.joins do
61+
# When we have interview join, the user table is the 3rd binding ([j, i, u])
62+
[_interview_join, _user_join] -> where(query, [j, i, u], u.provider_login in ^handles)
63+
# When we only have user join, it's the 2nd binding ([j, u])
64+
[_user_join] -> where(query, [j, u], u.provider_login in ^handles)
65+
# No joins yet, will be added later
66+
[] -> where(query, [j, u], u.provider_login in ^handles)
67+
end
68+
end
69+
4870
defp maybe_filter_by_tech_stack(query, nil), do: query
4971
defp maybe_filter_by_tech_stack(query, []), do: query
5072

@@ -55,6 +77,27 @@ defmodule Algora.Jobs do
5577
defp maybe_limit(query, nil), do: query
5678
defp maybe_limit(query, limit), do: limit(query, ^limit)
5779

80+
defp apply_ordering(query, opts) do
81+
case opts[:order_by] do
82+
:last_interview_desc ->
83+
# Sort by most recent interview, then by job posting date
84+
# Use COALESCE to handle NULL values for jobs without interviews
85+
query
86+
|> join(:left, [j], i in "job_interviews", on: i.job_posting_id == j.id)
87+
|> group_by([j], [j.id, j.inserted_at])
88+
|> order_by([j, i], [desc: coalesce(max(i.inserted_at), j.inserted_at), desc: j.inserted_at])
89+
90+
_ ->
91+
# Default ordering by job posting date
92+
order_by(query, [j], desc: j.inserted_at)
93+
end
94+
end
95+
96+
defp apply_preloads(jobs, opts) do
97+
preloads = [:user | (opts[:preload] || [])]
98+
Repo.preload(jobs, preloads)
99+
end
100+
58101
@spec create_payment_session(User.t() | nil, JobPosting.t(), Money.t()) ::
59102
{:ok, String.t()} | {:error, atom()}
60103
def create_payment_session(user, job_posting, amount) do

lib/algora/jobs/schemas/job_posting.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ defmodule Algora.Jobs.JobPosting do
2424
field :seniority, :string
2525

2626
belongs_to :user, User, null: false
27+
has_many :interviews, AlgoraCloud.Interviews.JobInterview, foreign_key: :job_posting_id
2728

2829
timestamps()
2930
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
defmodule Algora.Repo.Migrations.CreateJobInterviews do
2+
use Ecto.Migration
3+
4+
def change do
5+
create table(:job_interviews) do
6+
add :user_id, references(:users, on_delete: :delete_all), null: false
7+
add :job_posting_id, references(:job_postings, on_delete: :delete_all), null: false
8+
add :status, :string, null: false
9+
add :notes, :text
10+
add :scheduled_at, :utc_datetime_usec
11+
add :completed_at, :utc_datetime_usec
12+
13+
timestamps()
14+
end
15+
16+
create index(:job_interviews, [:user_id])
17+
create index(:job_interviews, [:job_posting_id])
18+
create index(:job_interviews, [:status])
19+
end
20+
end

0 commit comments

Comments
 (0)