105 lines
3.7 KiB
Python
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()]
|