126 lines
4.0 KiB
Python
126 lines
4.0 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.deps import get_current_user, require_role
|
|
from app.db.database import get_db
|
|
from app.db.models import User
|
|
from app.schemas.class_ import ClassCreate, ClassUpdate, ClassOut
|
|
from app.schemas.user import UserListItem
|
|
from app.schemas.common import PageResponse
|
|
from app.services.class_service import (
|
|
create_class,
|
|
update_class,
|
|
delete_class,
|
|
get_class_by_id,
|
|
list_classes,
|
|
get_member_count,
|
|
get_class_members,
|
|
)
|
|
|
|
router = APIRouter(prefix="/api/classes", tags=["classes"])
|
|
|
|
|
|
@router.get("/", response_model=PageResponse[ClassOut])
|
|
async def get_classes(
|
|
page: int = 1,
|
|
page_size: int = 50,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
classes, total = await list_classes(db, page, page_size)
|
|
total_pages = (total + page_size - 1) // page_size
|
|
result = []
|
|
for c in classes:
|
|
count = await get_member_count(db, c.id)
|
|
out = ClassOut.model_validate(c)
|
|
out.member_count = count
|
|
result.append(out)
|
|
return PageResponse(
|
|
items=result, total=total, page=page, page_size=page_size, total_pages=total_pages
|
|
)
|
|
|
|
|
|
@router.post("/", response_model=ClassOut)
|
|
async def create_new_class(
|
|
data: ClassCreate,
|
|
admin: User = Depends(require_role("super_admin")),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
class_ = await create_class(db, data)
|
|
out = ClassOut.model_validate(class_)
|
|
out.member_count = 0
|
|
return out
|
|
|
|
|
|
@router.put("/{class_id}", response_model=ClassOut)
|
|
async def update_existing_class(
|
|
class_id: int,
|
|
data: ClassUpdate,
|
|
admin: User = Depends(require_role("super_admin")),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
class_ = await get_class_by_id(db, class_id)
|
|
if class_ is None:
|
|
raise HTTPException(status_code=404, detail="Class not found")
|
|
updated = await update_class(db, class_, data)
|
|
out = ClassOut.model_validate(updated)
|
|
out.member_count = await get_member_count(db, class_id)
|
|
return out
|
|
|
|
|
|
@router.delete("/{class_id}")
|
|
async def delete_existing_class(
|
|
class_id: int,
|
|
admin: User = Depends(require_role("super_admin")),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
class_ = await get_class_by_id(db, class_id)
|
|
if class_ is None:
|
|
raise HTTPException(status_code=404, detail="Class not found")
|
|
await delete_class(db, class_)
|
|
return {"message": "Class deleted"}
|
|
|
|
|
|
@router.get("/{class_id}/members", response_model=PageResponse[UserListItem])
|
|
async def get_members(
|
|
class_id: int,
|
|
status: str | None = None,
|
|
page: int = 1,
|
|
page_size: int = 50,
|
|
admin: User = Depends(require_role("super_admin", "class_admin")),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
if admin.role == "class_admin" and admin.class_id != class_id:
|
|
raise HTTPException(status_code=403, detail="Access denied for this class")
|
|
|
|
members, total = await get_class_members(db, class_id, status, page, page_size)
|
|
total_pages = (total + page_size - 1) // page_size
|
|
return PageResponse(
|
|
items=[UserListItem.model_validate(m) for m in members],
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
total_pages=total_pages,
|
|
)
|
|
|
|
|
|
@router.get("/{class_id}/pending", response_model=PageResponse[UserListItem])
|
|
async def get_pending_members(
|
|
class_id: int,
|
|
page: int = 1,
|
|
page_size: int = 50,
|
|
admin: User = Depends(require_role("super_admin", "class_admin")),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
if admin.role == "class_admin" and admin.class_id != class_id:
|
|
raise HTTPException(status_code=403, detail="Access denied for this class")
|
|
|
|
members, total = await get_class_members(db, class_id, status="pending", page=page, page_size=page_size)
|
|
total_pages = (total + page_size - 1) // page_size
|
|
return PageResponse(
|
|
items=[UserListItem.model_validate(m) for m in members],
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
total_pages=total_pages,
|
|
)
|