from fastapi import APIRouter,Depends,Query from fastapi.responses import JSONResponse from fastapi import HTTPException from db_setup import get_session from job.candidate.views import FileRead,CandidateView from sqlalchemy.ext.asyncio import AsyncSession from users.permissions import PermissionTag, require_permission from job.job_post.views import JobPost,JobPostCreate import logging from job.job_post.plugins import PlatformAlias from fastapi import UploadFile, File from dotenv import load_dotenv from datetime import datetime, time, timezone load_dotenv() logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) router = APIRouter() @router.get("/jobs/alias") async def get_job_alias(): try: alias_lst=[k.name for k in PlatformAlias] return JSONResponse(content={"data":alias_lst,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.post("/candidate/cv_upload") async def cv_upload( file: UploadFile = File(...), current_user: dict = Depends(require_permission(PermissionTag.CANDIDATES_CREATE)), session: AsyncSession = Depends(get_session), ): try: file_content = await file.read() logger.info(f"Received file: {file.filename} ({len(file_content)} bytes)") service=FileRead(session=session,filename=file.filename,file=file_content) data=await service.read_file() return JSONResponse(content={"data":data,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.post("/candidate/inbox-match") async def candidate_inbox_match( inbox_message_id: str = Query(...), current_user: dict = Depends(require_permission(PermissionTag.CANDIDATES_EDIT)), session: AsyncSession = Depends(get_session), ): try: service=FileRead(session=session) data=await service.match_inbox_cv(inbox_message_id) return JSONResponse(content={"data":data,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.post("/job/post-job") async def post_job( payload: JobPostCreate, current_user: dict = Depends(require_permission(PermissionTag.JOB_BOARD_CREATE)), session: AsyncSession = Depends(get_session), ): try: service=JobPost(session=session) data=payload.model_dump() if data['mode']=="customScheduled": data['due_at']=datetime.combine( data['scheduler_date'], data['scheduler_time'] or time(0, 0, 0), tzinfo=timezone.utc, ).strftime("%Y-%m-%dT%H:%M:%S.000Z") result=await service.post_job(data,current_user) return JSONResponse(content={"data":result,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.get("/job/buffer/channels") async def buffer_channels( current_user: dict = Depends(require_permission(PermissionTag.JOB_BOARD_VIEW)), session: AsyncSession = Depends(get_session), ): try: service=JobPost(session=session) data=await service.list_channels() return JSONResponse(content={"data":data,"total":len(data),"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.get("/candidate/fetch") async def fetch_candidate( user_id:str=Query(None), limit:int=Query(10), offset:int=Query(0), search:str=Query(None), current_user: dict = Depends(require_permission(PermissionTag.CANDIDATES_VIEW)), session: AsyncSession = Depends(get_session), ): try: service=CandidateView(session=session) data=await service.get_candidate(user_id=user_id,limit=limit,offset=offset,search=search) # total is the RESULT-SET size, not len(data) — a pager cannot be driven # off the page length. By id stays 1, per the house envelope. total=await service.count_candidates(user_id=user_id,search=search) if isinstance(data,list) else 1 return JSONResponse(content={"data":data,"total":total,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e))