HR-ATS-Portal/backend/search/views.py

105 lines
3.7 KiB
Python

from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from inbox.models import Inbox
from job.job_post.models import JobPosts
from role.models import EnumRoles, Roles
from search.serializers import (
serialize_search_candidate,
serialize_search_job,
serialize_search_manager,
)
from users.models import Users
from users.permissions import PermissionTag, has_permission
JOBS_CAP = 4
CANDIDATES_CAP = 4
MANAGERS_CAP = 3
class Search:
def __init__(self, session: AsyncSession):
self.session = session
async def fetch(self, q, limit, current_user):
query = (q or "").strip()
granted = current_user.get("permissions") or []
jobs = []
candidates = []
managers = []
if query:
if has_permission(granted, PermissionTag.JOBS_VIEW):
jobs = await self._jobs(query, min(limit, JOBS_CAP))
if has_permission(granted, PermissionTag.CANDIDATES_VIEW):
candidates = await self._candidates(query, min(limit, CANDIDATES_CAP))
managers = await self._managers(query, min(limit, MANAGERS_CAP))
data = {"jobs": jobs, "candidates": candidates, "managers": managers}
total = len(jobs) + len(candidates) + len(managers)
return data, total
async def _jobs(self, query, cap):
like = f"%{query}%"
statement = (
select(JobPosts)
.where(
JobPosts.is_deleted == False, # noqa: E712
or_(
JobPosts.title.ilike(like),
JobPosts.location.ilike(like),
JobPosts.department.ilike(like),
),
)
.order_by(JobPosts.created_at.desc())
.limit(cap)
)
result = await self.session.execute(statement)
return [serialize_search_job(r) for r in result.scalars().all()]
async def _candidates(self, query, cap):
like = f"%{query}%"
statement = (
select(Users)
.join(Roles, Users.role_id == Roles.id)
.where(
Roles.role_name == EnumRoles.CANDIDATE.value,
Users.is_deleted == False, # noqa: E712
or_(Users.name.ilike(like), Users.email.ilike(like)),
)
.order_by(Users.created_at.desc())
.limit(cap)
)
users = list((await self.session.execute(statement)).scalars().all())
inbox_by_user = {}
if users:
inbox_q = (
select(Inbox.user_id, Inbox.id)
.where(Inbox.user_id.in_([u.id for u in users]))
.order_by(Inbox.created_at.desc())
)
for user_id, inbox_id in (await self.session.execute(inbox_q)).all():
inbox_by_user.setdefault(user_id, inbox_id)
return [
serialize_search_candidate(u.id, u.name, u.email, inbox_by_user.get(u.id))
for u in users
]
async def _managers(self, query, cap):
like = f"%{query}%"
role = await Roles.get_role_by_name(self.session, EnumRoles.HIRING_MANAGER.value)
if role is None:
return []
statement = (
select(Users)
.options(selectinload(Users.role))
.where(
Users.role_id == role.id,
Users.is_deleted == False, # noqa: E712
or_(Users.name.ilike(like), Users.email.ilike(like)),
)
.order_by(Users.created_at.desc())
.limit(cap)
)
result = await self.session.execute(statement)
return [serialize_search_manager(u) for u in result.scalars().all()]