""" Jobs API routes """ from fastapi import APIRouter, Depends, HTTPException, status, Request from typing import List from pydantic import BaseModel from sqlalchemy.orm import Session from ..database import SessionLocal from ..models import JobPosting, User from ..config.settings import settings router = APIRouter() # Pydantic models for jobs class JobCreate(BaseModel): title: str description: str requirements: str location: str = None salary_min: int = None salary_max: int = None is_remote: bool = False class JobUpdate(BaseModel): title: str = None description: str = None requirements: str = None location: str = None salary_min: int = None salary_max: int = None is_active: bool = None is_remote: bool = None class JobResponse(BaseModel): id: int title: str description: str requirements: str location: str salary_min: int salary_max: int is_active: bool is_remote: bool tenant_id: int created_by_user_id: int class Config: from_attributes = True @router.get("/", response_model=List[JobResponse]) async def get_jobs(skip: int = 0, limit: int = 100, is_active: bool = True, db: Session = Depends(SessionLocal), request: Request = None): """Get all jobs for the current tenant""" tenant_id = getattr(request.state, 'tenant_id', None) if not tenant_id and settings.MULTI_TENANT_ENABLED: raise HTTPException(status_code=400, detail="Tenant ID is required") query = db.query(JobPosting).filter(JobPosting.tenant_id == tenant_id) if is_active is not None: query = query.filter(JobPosting.is_active == is_active) jobs = query.offset(skip).limit(limit).all() return jobs @router.get("/{job_id}", response_model=JobResponse) async def get_job(job_id: int, db: Session = Depends(SessionLocal), request: Request = None): """Get a specific job""" tenant_id = getattr(request.state, 'tenant_id', None) if not tenant_id and settings.MULTI_TENANT_ENABLED: raise HTTPException(status_code=400, detail="Tenant ID is required") job = db.query(JobPosting).filter( JobPosting.id == job_id, JobPosting.tenant_id == tenant_id # Ensure job belongs to current tenant ).first() if not job: raise HTTPException(status_code=404, detail="Job not found") if not job.is_active: raise HTTPException(status_code=404, detail="Job not found") return job @router.post("/", response_model=JobResponse) async def create_job(job: JobCreate, db: Session = Depends(SessionLocal), request: Request = None, user_id: int = 1): # In real app, get from auth context """Create a new job posting""" tenant_id = getattr(request.state, 'tenant_id', None) if not tenant_id and settings.MULTI_TENANT_ENABLED: raise HTTPException(status_code=400, detail="Tenant ID is required") # Verify user exists and has permission to create job postings user = db.query(User).filter( User.id == user_id, User.tenant_id == tenant_id # Ensure user belongs to current tenant ).first() if not user or user.role not in ["job_provider", "admin"]: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not authorized to create job postings" ) db_job = JobPosting( title=job.title, description=job.description, requirements=job.requirements, location=job.location, salary_min=job.salary_min, salary_max=job.salary_max, is_remote=job.is_remote, tenant_id=tenant_id, # Use current tenant created_by_user_id=user_id ) db.add(db_job) db.commit() db.refresh(db_job) return db_job @router.put("/{job_id}", response_model=JobResponse) async def update_job(job_id: int, job_update: JobUpdate, db: Session = Depends(SessionLocal), request: Request = None): """Update a job posting""" tenant_id = getattr(request.state, 'tenant_id', None) if not tenant_id and settings.MULTI_TENANT_ENABLED: raise HTTPException(status_code=400, detail="Tenant ID is required") db_job = db.query(JobPosting).filter( JobPosting.id == job_id, JobPosting.tenant_id == tenant_id # Ensure job belongs to current tenant ).first() if not db_job: raise HTTPException(status_code=404, detail="Job not found") # Update fields if provided for field, value in job_update.model_dump(exclude_unset=True).items(): setattr(db_job, field, value) db.commit() db.refresh(db_job) return db_job @router.delete("/{job_id}") async def delete_job(job_id: int, db: Session = Depends(SessionLocal), request: Request = None): """Delete a job posting (soft delete by setting is_active to False)""" tenant_id = getattr(request.state, 'tenant_id', None) if not tenant_id and settings.MULTI_TENANT_ENABLED: raise HTTPException(status_code=400, detail="Tenant ID is required") db_job = db.query(JobPosting).filter( JobPosting.id == job_id, JobPosting.tenant_id == tenant_id # Ensure job belongs to current tenant ).first() if not db_job: raise HTTPException(status_code=404, detail="Job not found") db_job.is_active = False db.commit() return {"message": "Job deactivated successfully"}