from datetime import datetime from fastapi import APIRouter,Depends,Query from fastapi.responses import JSONResponse from fastapi import HTTPException from db_setup import get_session from sqlalchemy.ext.asyncio import AsyncSession from pydantic import BaseModel from offer.views import Offer from users.permissions import PermissionTag,require_permission from dotenv import load_dotenv load_dotenv() router = APIRouter() class OfferCreate(BaseModel): offer_id: str | None = None inbox_id: int | None = None manual_upload_candidate_id: str | None = None form_data_id: str | None = None job_post_id: str candidate_user_id: str | None = None status: str | None = "draft" base_salary: float | None = None currency: str | None = None salary_period: str | None = None signing_bonus: float | None = None annual_bonus_pct: float | None = None equity_units: int | None = None equity_instrument: str | None = None start_date: datetime | None = None expiry_date: datetime | None = None cadre: str | None = None gross_salary_in_words: str | None = None subsidized_services: str | None = None probation_period: str | None = None notice_period: str | None = None work_location: str | None = None work_timings: str | None = None change_reason: str | None = None class OfferUpdate(BaseModel): status: str | None = None base_salary: float | None = None currency: str | None = None salary_period: str | None = None signing_bonus: float | None = None annual_bonus_pct: float | None = None equity_units: int | None = None equity_instrument: str | None = None start_date: datetime | None = None expiry_date: datetime | None = None cadre: str | None = None gross_salary_in_words: str | None = None subsidized_services: str | None = None probation_period: str | None = None notice_period: str | None = None work_location: str | None = None work_timings: str | None = None sent_at: datetime | None = None responded_at: datetime | None = None closed_at: datetime | None = None issued_by: str | None = None inbox_id: int | None = None job_post_id: str | None = None candidate_user_id: str | None = None change_reason: str | None = None class OfferIssue(BaseModel): change_reason: str | None = None class OfferSent(BaseModel): offer_id: str | None = None inbox_id: int | None = None manual_upload_candidate_id: str | None = None form_data_id: str | None = None job_post_id: str | None = None candidate_user_id: str | None = None base_salary: float | None = None currency: str | None = "USD" salary_period: str | None = "year" signing_bonus: float | None = None annual_bonus_pct: float | None = None equity_units: int | None = None equity_instrument: str | None = None start_date: datetime | None = None expiry_date: datetime | None = None change_reason: str | None = None @router.get("/offers/fetch") async def fetch_offers( current_user: dict = Depends(require_permission(PermissionTag.OFFERS_VIEW)), offer_id: str | None = Query(None), status: str | None = Query(None), inbox_id: int | None = Query(None), job_post_id: str | None = Query(None), top: int | None = Query(None), skip: int = Query(0,ge=0), session: AsyncSession = Depends(get_session), ): try: service=Offer(session=session) data,total=await service.get_offers(offer_id,status,inbox_id,job_post_id,top,skip) 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)) @router.post("/offers/create") async def create_offer( payload: OfferCreate, current_user: dict = Depends(require_permission(PermissionTag.OFFERS_CREATE)), session: AsyncSession = Depends(get_session), ): try: service=Offer(session=session) data=await service.create_offer(payload.model_dump(exclude_unset=True),current_user) return JSONResponse(content={"data":data,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.patch("/offers/update") async def update_offer( payload: OfferUpdate, current_user: dict = Depends(require_permission(PermissionTag.OFFERS_EDIT)), offer_id: str = Query(...), session: AsyncSession = Depends(get_session), ): try: service=Offer(session=session) data=await service.update_offer(offer_id,payload.model_dump(exclude_unset=True),current_user) 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("/offers/issue") async def issue_offer( current_user: dict = Depends(require_permission(PermissionTag.OFFERS_APPROVE)), offer_id: str = Query(...), payload: OfferIssue | None = None, session: AsyncSession = Depends(get_session), ): try: service=Offer(session=session) data=await service.issue_offer(offer_id,current_user) return JSONResponse(content={"data":data,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e)) @router.get("/offers/jobs/candidates/lists") async def list_offer_candidates( current_user: dict = Depends(require_permission(PermissionTag.OFFERS_VIEW)), search: str | None = Query(None), top: int | None = Query(None), skip: int = Query(0,ge=0), session: AsyncSession = Depends(get_session), ): try: service=Offer(session=session) data,total=await service.list_candidates(current_user,search,top,skip) 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)) @router.post("/offers/jobs/sent") async def send_job_offer( payload: OfferSent, current_user: dict = Depends(require_permission(PermissionTag.OFFERS_CREATE)), session: AsyncSession = Depends(get_session), ): try: service=Offer(session=session) data=await service.send_offer(payload.model_dump(exclude_unset=True),current_user) return JSONResponse(content={"data":data,"status_code":200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500,detail=str(e))