import logging from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile, status from pydantic import BaseModel try: from app.service.parent import ParentService from app.service import get_db_session from app.service.avatar_storage import AvatarStorageError from app.security import get_current_user_id except ModuleNotFoundError: from service.parent import ParentService from service import get_db_session from service.avatar_storage import AvatarStorageError from security import get_current_user_id router = APIRouter(prefix="/parents", tags=["parents"]) logger = logging.getLogger("app.parents") class ParentCreateRequest(BaseModel): openid: str unionid: str | None = None nickname: str | None = None avatar_url: str | None = None class ParentResponse(BaseModel): user_id: int openid: str unionid: str | None = None nickname: str | None = None avatar_url: str | None = None phone: str | None = None status: int class ParentUpdateRequest(BaseModel): nickname: str | None = None avatar_url: str | None = None phone: str | None = None class AvatarDownloadResponse(BaseModel): avatar_url: str expires_in: int | None = None @router.post("", response_model=ParentResponse, status_code=status.HTTP_201_CREATED) def create_parent(payload: ParentCreateRequest, request: Request, db=Depends(get_db_session)) -> ParentResponse: service = ParentService(db) parent = service.create(payload.openid, payload.unionid, payload.nickname, payload.avatar_url) return ParentResponse(**parent) @router.post("/me/avatar", response_model=ParentResponse) def upload_my_avatar( request: Request, file: UploadFile = File(...), current_user_id: int = Depends(get_current_user_id), db=Depends(get_db_session), ) -> ParentResponse: del request service = ParentService(db) try: content = file.file.read() parent = service.upload_avatar( user_id=current_user_id, filename=file.filename, content_type=file.content_type, content=content, ) except AvatarStorageError as exc: raise HTTPException(status_code=exc.status_code, detail=str(exc)) from exc finally: file.file.close() if not parent: raise HTTPException(status_code=404, detail="parent not found") return ParentResponse(**parent) @router.get("/{user_id}/avatar", response_model=AvatarDownloadResponse) def get_parent_avatar(user_id: int, request: Request, db=Depends(get_db_session)) -> AvatarDownloadResponse: del request service = ParentService(db) avatar = service.get_avatar_download(user_id) if not avatar: raise HTTPException(status_code=404, detail="avatar not found") return AvatarDownloadResponse(**avatar) @router.get("/{user_id}", response_model=ParentResponse) def get_parent(user_id: int, request: Request, db=Depends(get_db_session)) -> ParentResponse: service = ParentService(db) parent = service.get(user_id) if not parent: raise HTTPException(status_code=404, detail="parent not found") return ParentResponse(**parent) @router.patch("/{user_id}", response_model=ParentResponse) def update_parent(user_id: int, payload: ParentUpdateRequest, request: Request, db=Depends(get_db_session)) -> ParentResponse: service = ParentService(db) parent = service.update(user_id, payload.nickname, payload.avatar_url, payload.phone) if not parent: raise HTTPException(status_code=404, detail="parent not found") return ParentResponse(**parent)