"""Portfolio API endpoints.""" from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import Optional from uuid import UUID from app.database import get_db from app.schemas.portfolio import ( PortfolioCreate, PortfolioUpdate, PortfolioResponse, PortfolioListResponse ) from app.services.rebalancing_service import PortfolioService router = APIRouter() @router.post("/", response_model=PortfolioResponse, status_code=status.HTTP_201_CREATED) async def create_portfolio( portfolio: PortfolioCreate, user_id: Optional[str] = None, db: Session = Depends(get_db) ): """ 포트폴리오 생성. Args: portfolio: 포트폴리오 생성 요청 user_id: 사용자 ID (선택) db: 데이터베이스 세션 Returns: 생성된 포트폴리오 """ try: assets_data = [ {'ticker': asset.ticker, 'target_ratio': asset.target_ratio} for asset in portfolio.assets ] created_portfolio = PortfolioService.create_portfolio( name=portfolio.name, description=portfolio.description, assets=assets_data, user_id=user_id, db_session=db ) return created_portfolio except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"포트폴리오 생성 오류: {str(e)}" ) @router.get("/{portfolio_id}", response_model=PortfolioResponse) async def get_portfolio( portfolio_id: UUID, db: Session = Depends(get_db) ): """ 포트폴리오 조회. Args: portfolio_id: 포트폴리오 ID db: 데이터베이스 세션 Returns: 포트폴리오 """ portfolio = PortfolioService.get_portfolio(portfolio_id, db) if not portfolio: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="포트폴리오를 찾을 수 없습니다" ) return portfolio @router.get("/", response_model=PortfolioListResponse) async def list_portfolios( user_id: Optional[str] = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db) ): """ 포트폴리오 목록 조회. Args: user_id: 사용자 ID (필터) skip: 건너뛸 레코드 수 limit: 최대 레코드 수 db: 데이터베이스 세션 Returns: 포트폴리오 목록 """ result = PortfolioService.list_portfolios(db, user_id, skip, limit) return result @router.put("/{portfolio_id}", response_model=PortfolioResponse) async def update_portfolio( portfolio_id: UUID, portfolio: PortfolioUpdate, db: Session = Depends(get_db) ): """ 포트폴리오 수정. Args: portfolio_id: 포트폴리오 ID portfolio: 포트폴리오 수정 요청 db: 데이터베이스 세션 Returns: 수정된 포트폴리오 """ try: assets_data = None if portfolio.assets: assets_data = [ {'ticker': asset.ticker, 'target_ratio': asset.target_ratio} for asset in portfolio.assets ] updated_portfolio = PortfolioService.update_portfolio( portfolio_id=portfolio_id, name=portfolio.name, description=portfolio.description, assets=assets_data, db_session=db ) if not updated_portfolio: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="포트폴리오를 찾을 수 없습니다" ) return updated_portfolio except ValueError as e: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(e) ) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"포트폴리오 수정 오류: {str(e)}" ) @router.delete("/{portfolio_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_portfolio( portfolio_id: UUID, db: Session = Depends(get_db) ): """ 포트폴리오 삭제. Args: portfolio_id: 포트폴리오 ID db: 데이터베이스 세션 """ success = PortfolioService.delete_portfolio(portfolio_id, db) if not success: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="포트폴리오를 찾을 수 없습니다" )