from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app import crud, models, schemas from app.api import deps router = APIRouter() @router.get("/", response_model=List[schemas.Employee]) def read_employees( db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve employees. """ employees = crud.employee.get_all(db, skip=skip, limit=limit) return employees @router.post("/", response_model=schemas.Employee) def create_employee( *, db: Session = Depends(deps.get_db), employee_in: schemas.EmployeeCreate, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Create new employee. """ # Check if email already exists employee = crud.employee.get_by_email(db, email=employee_in.email) if employee: raise HTTPException( status_code=400, detail="The employee with this email already exists in the system", ) # Check if department exists department = crud.department.get(db, id=employee_in.department_id) if not department: raise HTTPException( status_code=404, detail=f"Department with id {employee_in.department_id} not found", ) # Check if job title exists job_title = crud.job_title.get(db, id=employee_in.job_title_id) if not job_title: raise HTTPException( status_code=404, detail=f"Job title with id {employee_in.job_title_id} not found", ) # Check if manager exists (if provided) if employee_in.manager_id: manager = crud.employee.get(db, id=employee_in.manager_id) if not manager: raise HTTPException( status_code=404, detail=f"Manager with id {employee_in.manager_id} not found", ) employee = crud.employee.create(db, obj_in=employee_in) return employee @router.get("/{employee_id}", response_model=schemas.EmployeeWithDetails) def read_employee( *, db: Session = Depends(deps.get_db), employee_id: str, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Get employee by ID. """ employee = crud.employee.get(db, id=employee_id) if not employee: raise HTTPException(status_code=404, detail="Employee not found") return employee @router.put("/{employee_id}", response_model=schemas.Employee) def update_employee( *, db: Session = Depends(deps.get_db), employee_id: str, employee_in: schemas.EmployeeUpdate, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Update an employee. """ employee = crud.employee.get(db, id=employee_id) if not employee: raise HTTPException(status_code=404, detail="Employee not found") # If email is being updated, check if it already exists if employee_in.email and employee_in.email != employee.email: existing_employee = crud.employee.get_by_email(db, email=employee_in.email) if existing_employee: raise HTTPException( status_code=400, detail="The employee with this email already exists in the system", ) # Check if department exists (if provided) if employee_in.department_id: department = crud.department.get(db, id=employee_in.department_id) if not department: raise HTTPException( status_code=404, detail=f"Department with id {employee_in.department_id} not found", ) # Check if job title exists (if provided) if employee_in.job_title_id: job_title = crud.job_title.get(db, id=employee_in.job_title_id) if not job_title: raise HTTPException( status_code=404, detail=f"Job title with id {employee_in.job_title_id} not found", ) # Check if manager exists (if provided) if employee_in.manager_id: # Prevent self-assignment as manager if employee_in.manager_id == employee_id: raise HTTPException( status_code=400, detail="An employee cannot be their own manager", ) manager = crud.employee.get(db, id=employee_in.manager_id) if not manager: raise HTTPException( status_code=404, detail=f"Manager with id {employee_in.manager_id} not found", ) employee = crud.employee.update(db, db_obj=employee, obj_in=employee_in) return employee @router.delete("/{employee_id}", status_code=204, response_model=None) def delete_employee( *, db: Session = Depends(deps.get_db), employee_id: str, current_user: models.User = Depends(deps.get_current_active_superuser), ) -> Any: """ Delete an employee. """ employee = crud.employee.get(db, id=employee_id) if not employee: raise HTTPException(status_code=404, detail="Employee not found") # Check if this employee is a manager for other employees subordinates = db.query(models.Employee).filter(models.Employee.manager_id == employee_id).first() if subordinates: raise HTTPException( status_code=400, detail="Cannot delete employee who is a manager. Reassign subordinates first.", ) crud.employee.remove(db, id=employee_id) return None @router.get("/department/{department_id}", response_model=List[schemas.Employee]) def read_employees_by_department( *, db: Session = Depends(deps.get_db), department_id: str, skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve employees by department. """ # Check if department exists department = crud.department.get(db, id=department_id) if not department: raise HTTPException(status_code=404, detail="Department not found") employees = crud.employee.get_by_department( db, department_id=department_id, skip=skip, limit=limit ) return employees @router.get("/job-title/{job_title_id}", response_model=List[schemas.Employee]) def read_employees_by_job_title( *, db: Session = Depends(deps.get_db), job_title_id: str, skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve employees by job title. """ # Check if job title exists job_title = crud.job_title.get(db, id=job_title_id) if not job_title: raise HTTPException(status_code=404, detail="Job title not found") employees = crud.employee.get_by_job_title( db, job_title_id=job_title_id, skip=skip, limit=limit ) return employees @router.get("/manager/{manager_id}", response_model=List[schemas.Employee]) def read_employees_by_manager( *, db: Session = Depends(deps.get_db), manager_id: str, skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve employees by manager. """ # Check if manager exists manager = crud.employee.get(db, id=manager_id) if not manager: raise HTTPException(status_code=404, detail="Manager not found") employees = crud.employee.get_by_manager( db, manager_id=manager_id, skip=skip, limit=limit ) return employees @router.get("/search/", response_model=List[schemas.Employee]) def search_employees( *, db: Session = Depends(deps.get_db), department_id: Optional[str] = None, job_title_id: Optional[str] = None, name: Optional[str] = None, skills: Optional[List[str]] = Query(None), categories: Optional[List[str]] = Query(None), is_active: Optional[bool] = True, skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Search employees by various criteria including categories and skills. """ search_params = schemas.EmployeeSearchParams( department_id=department_id, job_title_id=job_title_id, name=name, skills=skills, categories=categories, is_active=is_active, ) employees = crud.employee.search( db, params=search_params, skip=skip, limit=limit ) return employees