Automated Action 27c9268a6a Implement HR platform backend with FastAPI and SQLite
- Set up project structure with FastAPI framework
- Create database models for users, employees, departments, and job titles
- Implement JWT authentication and authorization system
- Set up SQLite database with SQLAlchemy ORM
- Add Alembic migrations for database versioning
- Create CRUD API endpoints for employee management
- Implement category-based search functionality
- Add OpenAPI documentation and health check endpoint
- Update README with comprehensive setup and usage instructions
2025-06-03 01:18:41 +00:00

275 lines
8.5 KiB
Python

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