From 55c5a1da0103a9b4c0baf4d2b6af2b0ecc3fa4b7 Mon Sep 17 00:00:00 2001 From: nightbug-xx Date: Wed, 11 Jun 2025 10:53:46 +0900 Subject: [PATCH] Add endpoint for friend character public homeworks --- app/api/character.py | 1 + app/api/friend.py | 25 +++++++++++++-- app/api/homework.py | 2 ++ app/crud/character.py | 1 + app/crud/homework.py | 1 + app/schemas/character.py | 4 +++ app/schemas/friend.py | 10 ++++++ app/schemas/homework.py | 4 +++ app/services/friend_service.py | 57 ++++++++++++++++++++++++++++------ 9 files changed, 93 insertions(+), 12 deletions(-) diff --git a/app/api/character.py b/app/api/character.py index 3b76c05..855bbbc 100644 --- a/app/api/character.py +++ b/app/api/character.py @@ -76,6 +76,7 @@ def update_character( character.name = req.name character.server = req.server character.combat_power = req.power + character.is_public = req.is_public db.commit() return {"message": "캐릭터가 수정되었습니다."} diff --git a/app/api/friend.py b/app/api/friend.py index fecce43..9a4adef 100644 --- a/app/api/friend.py +++ b/app/api/friend.py @@ -1,8 +1,14 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.core.deps import get_db, get_current_user -from app.schemas.friend import FriendRequestCreate, FriendRequestResponse, FriendResponse +from app.schemas.friend import ( + FriendRequestCreate, + FriendRequestResponse, + FriendResponse, + FriendListItem, +) from app.schemas.character import CharacterResponse +from app.schemas.homework import HomeworkTypeResponse from app.services import friend_service from app.models.user import User @@ -55,7 +61,7 @@ def respond_to_request( return {"detail": "요청을 처리했습니다."} -@router.get("/list", response_model=list[int]) +@router.get("/list", response_model=list[FriendListItem]) def get_friend_list( db: Session = Depends(get_db), current_user: User = Depends(get_current_user) @@ -70,6 +76,21 @@ def get_friend_characters( ): return friend_service.get_public_characters_of_friend(db, current_user.id, friend_id) + +@router.get("/{friend_id}/characters/{character_id}/homeworks", response_model=list[HomeworkTypeResponse]) +def get_friend_character_homeworks( + friend_id: int, + character_id: int, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user) +): + return friend_service.get_public_homeworks_of_friend_character( + db, + current_user.id, + friend_id, + character_id, + ) + @router.delete("/{friend_id}") def delete_friend( friend_id: int, diff --git a/app/api/homework.py b/app/api/homework.py index 93c2cbf..37ddb4e 100644 --- a/app/api/homework.py +++ b/app/api/homework.py @@ -24,6 +24,7 @@ def register_homework_type( reset_type=homework_data.reset_type, reset_time=homework_data.reset_time or time(6, 0), clear_count=homework_data.clear_count or 0, + is_public=homework_data.is_public, created_at=datetime.utcnow(), ) db.add(homework_type) @@ -56,6 +57,7 @@ def update_homework_type( homework_type.description = req.description homework_type.reset_type = req.reset_type homework_type.clear_count = req.clear_count + homework_type.is_public = req.is_public db.commit() return {"message": "숙제가 수정되었습니다."} diff --git a/app/crud/character.py b/app/crud/character.py index 096c4d1..9a87960 100644 --- a/app/crud/character.py +++ b/app/crud/character.py @@ -21,6 +21,7 @@ def create_character(user_id: int, character_data: CharacterCreate, db: Session) server=character_data.server, job=character_data.job, combat_power=character_data.combat_power, # ← 수동 입력 허용 + is_public=character_data.is_public, created_at=datetime.utcnow(), updated_at=datetime.utcnow(), ) diff --git a/app/crud/homework.py b/app/crud/homework.py index 207b785..06a7fb2 100644 --- a/app/crud/homework.py +++ b/app/crud/homework.py @@ -10,6 +10,7 @@ def create_homework_type(user_id: int, data: HomeworkTypeCreate, db: Session): reset_type=data.reset_type, reset_time=data.reset_time, clear_count=data.clear_count, + is_public=data.is_public, ) db.add(new_homework) db.commit() diff --git a/app/schemas/character.py b/app/schemas/character.py index 5c2537a..6233026 100644 --- a/app/schemas/character.py +++ b/app/schemas/character.py @@ -10,6 +10,7 @@ class CharacterCreate(BaseModel): server: Optional[str] = None job: Optional[str] = None combat_power: Optional[int] = None # ← 추가 + is_public: bool = False # 캐릭터 응답용 class CharacterResponse(BaseModel): @@ -18,6 +19,7 @@ class CharacterResponse(BaseModel): server: Optional[str] job: Optional[str] combat_power: Optional[int] # ← 추가 + is_public: bool auto_synced_at: Optional[datetime] created_at: datetime @@ -28,6 +30,7 @@ class CharacterUpdateRequest(BaseModel): name: constr(min_length=1) server: constr(min_length=1) power: conint(ge=0) # 0 이상 정수 + is_public: bool class CharacterDetailResponse(BaseModel): id: int @@ -35,6 +38,7 @@ class CharacterDetailResponse(BaseModel): server: str combat_power: int user_id: int + is_public: bool created_at: datetime updated_at: datetime diff --git a/app/schemas/friend.py b/app/schemas/friend.py index 59b90b7..d981bba 100644 --- a/app/schemas/friend.py +++ b/app/schemas/friend.py @@ -18,6 +18,8 @@ class FriendRequestResponse(BaseModel): id: int from_user_id: int to_user_id: int + from_user_email: str | None = None + to_user_email: str | None = None status: FriendRequestStatus created_at: datetime updated_at: datetime @@ -34,3 +36,11 @@ class FriendResponse(BaseModel): class Config: orm_mode = True + + +class FriendListItem(BaseModel): + id: int + email: str + + class Config: + orm_mode = True diff --git a/app/schemas/homework.py b/app/schemas/homework.py index bc0c612..9f823a1 100644 --- a/app/schemas/homework.py +++ b/app/schemas/homework.py @@ -10,6 +10,7 @@ class HomeworkTypeCreate(BaseModel): reset_type: str reset_time: Optional[time] = None clear_count: Optional[int] = 0 + is_public: bool = False class HomeworkTypeResponse(BaseModel): id: int @@ -18,6 +19,7 @@ class HomeworkTypeResponse(BaseModel): reset_type: str reset_time: time clear_count: int + is_public: bool created_at: datetime class Config: @@ -35,6 +37,7 @@ class HomeworkTypeUpdateRequest(BaseModel): description: str | None = None reset_type: constr(min_length=1) clear_count: conint(ge=1) + is_public: bool class HomeworkTypeDetailResponse(BaseModel): id: int @@ -44,6 +47,7 @@ class HomeworkTypeDetailResponse(BaseModel): reset_type: str reset_time: time clear_count: int + is_public: bool created_at: datetime model_config = { diff --git a/app/services/friend_service.py b/app/services/friend_service.py index 466c663..e529c01 100644 --- a/app/services/friend_service.py +++ b/app/services/friend_service.py @@ -1,4 +1,5 @@ -from sqlalchemy.orm import Session +from sqlalchemy.orm import Session, aliased +from sqlalchemy import select from app.models.friend import FriendRequest, Friend, FriendRequestStatus from app.models.user import User from app.models.character import Character, CharacterHomework @@ -44,17 +45,51 @@ def send_friend_request(db: Session, from_user_id: int, to_user_email: str): def get_received_requests(db: Session, user_id: int): - return db.query(FriendRequest).filter( - FriendRequest.to_user_id == user_id, - FriendRequest.status == FriendRequestStatus.pending - ).all() + sender = aliased(User) + receiver = aliased(User) + stmt = ( + select( + FriendRequest.id, + FriendRequest.from_user_id, + FriendRequest.to_user_id, + sender.email.label("from_user_email"), + receiver.email.label("to_user_email"), + FriendRequest.status, + FriendRequest.created_at, + FriendRequest.updated_at, + ) + .join(sender, FriendRequest.from_user_id == sender.id) + .join(receiver, FriendRequest.to_user_id == receiver.id) + .where( + FriendRequest.to_user_id == user_id, + FriendRequest.status == FriendRequestStatus.pending, + ) + ) + return db.execute(stmt).mappings().all() def get_sent_requests(db: Session, user_id: int): - return db.query(FriendRequest).filter( - FriendRequest.from_user_id == user_id, - FriendRequest.status == FriendRequestStatus.pending - ).all() + sender = aliased(User) + receiver = aliased(User) + stmt = ( + select( + FriendRequest.id, + FriendRequest.from_user_id, + FriendRequest.to_user_id, + sender.email.label("from_user_email"), + receiver.email.label("to_user_email"), + FriendRequest.status, + FriendRequest.created_at, + FriendRequest.updated_at, + ) + .join(sender, FriendRequest.from_user_id == sender.id) + .join(receiver, FriendRequest.to_user_id == receiver.id) + .where( + FriendRequest.from_user_id == user_id, + FriendRequest.status == FriendRequestStatus.pending, + ) + ) + return db.execute(stmt).mappings().all() def cancel_sent_request(db: Session, request_id: int, user_id: int): @@ -104,7 +139,9 @@ def get_friend_list(db: Session, user_id: int): result = [] for f in friends: friend_id = f.user_id_2 if f.user_id_1 == user_id else f.user_id_1 - result.append(friend_id) + friend = db.query(User).filter(User.id == friend_id).first() + friend_email = friend.email if friend else None + result.append({"id": friend_id, "email": friend_email}) return result