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

97 lines
3.7 KiB
Python

import uuid
from fastapi import HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from saved_search.models import SavedSearches
from saved_search.serializers import serialize_saved_search
VALID_ENTITIES = ("candidates", "jobs", "tasks", "inbox")
def _as_uuid(value):
if value in (None, ""):
return None
try:
return uuid.UUID(str(value))
except (TypeError, ValueError):
return None
def _user_id(current_user):
if not current_user or not current_user.get("id"):
raise HTTPException(status_code=401, detail="Not authenticated")
uid = _as_uuid(current_user["id"])
if uid is None:
raise HTTPException(status_code=401, detail="Invalid user id")
return uid
class SavedSearch:
def __init__(self, session: AsyncSession):
self.session = session
async def get_saved_searches(self, current_user, entity=None):
if entity and entity not in VALID_ENTITIES:
raise HTTPException(
status_code=422, detail=f"entity must be one of {', '.join(VALID_ENTITIES)}"
)
rows, total = await SavedSearches.fetch_saved_searches(
self.session, user_id=_user_id(current_user), entity=entity
)
return [serialize_saved_search(r) for r in rows], total
async def create_saved_search(self, payload, current_user):
name = (payload.get("name") or "").strip()
if not name:
raise HTTPException(status_code=422, detail="name is required")
entity = (payload.get("entity") or "").strip()
if entity not in VALID_ENTITIES:
raise HTTPException(
status_code=422, detail=f"entity must be one of {', '.join(VALID_ENTITIES)}"
)
filters = payload.get("filters") if isinstance(payload.get("filters"), dict) else {}
row = await SavedSearches.insert_saved_search(self.session, {
"user_id": _user_id(current_user),
"name": name,
"entity": entity,
"filters": filters,
})
return serialize_saved_search(row)
async def update_saved_search(self, record_id, payload, current_user):
uid = _user_id(current_user)
fields = {}
if "name" in payload:
name = (payload.get("name") or "").strip()
if not name:
raise HTTPException(status_code=422, detail="name cannot be blank")
fields["name"] = name
if "entity" in payload:
entity = (payload.get("entity") or "").strip()
if entity not in VALID_ENTITIES:
raise HTTPException(
status_code=422, detail=f"entity must be one of {', '.join(VALID_ENTITIES)}"
)
fields["entity"] = entity
if "filters" in payload:
if payload["filters"] is not None and not isinstance(payload["filters"], dict):
raise HTTPException(status_code=422, detail="filters must be an object")
fields["filters"] = payload["filters"] or {}
if not fields:
raise HTTPException(status_code=400, detail="No fields to update")
row = await SavedSearches.update_saved_search(
self.session, record_id, fields, user_id=uid
)
if not row:
raise HTTPException(status_code=404, detail="Saved search not found")
return serialize_saved_search(row)
async def delete_saved_search(self, record_id, current_user):
row = await SavedSearches.soft_delete_saved_search(
self.session, record_id, user_id=_user_id(current_user)
)
if not row:
raise HTTPException(status_code=404, detail="Saved search not found")
return {"id": str(row.id), "deleted": True}